OSDN Git Service

ADD: Mocchiが手がけたファイル管理プラグイン一式をコミット
[nucleus-jp/nucleus-plugins.git] / NP_MediaUtils / mediautils / MediaUtils.php
1 <?php
2 /**
3  * MediaUtils plugin for Nucleus CMS
4  * Version 0.9.6 (1.0 RC2) for PHP5
5  * Written By Mocchi, Apr. 04, 2011
6  * 
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  */
12
13 class MediaUtils {
14         static public $lib_path = '';
15         
16         static public $cookiename = 'blogid';
17         static public $blogid = FALSE;
18         static public $blogs = array();
19         static public $bshortname = '';
20         
21         static public $prefix = TRUE;
22         static public $maxsize = 2097152;
23         static public $suffixes = array();
24         
25         static public $algorism = 'md5';
26         static public $image_mime
27                 = array('image/jpeg'    => '.jpeg',
28                                 'image/png'     => '.png',
29                         /*      'image/bmp'     => '.bmp', not implemented*/
30                                 'image/gif'     => '.gif');
31         
32 /**
33  * error and exit
34  * @access      Public  MediaUtils::error
35  * @param       String  $message                Error message
36  * @exit        
37  */
38         static public function error ($message) {
39                 (string)        $message;
40                 header("HTTP/1.0 404 Not Found");
41                 exit($message);
42         }
43         
44 /**
45  * send resampled image via HTTP
46  * @access      Public  MediaUtils::responseResampledImage
47  * @param       Object  $medium         Medium Object
48  * @exit        
49  */
50         static public function responseResampledImage ($medium) {
51                 if (!class_exists('Medium', FALSE)) {
52                         include(self::$lib_path . '/Medium.php');
53                 }
54                 
55                 if ('Medium' !== get_class($medium)) {
56                         self::error ('NP_MediaUtils: Fail to generate resampled image');
57                         return;
58                 }
59                 
60                 if (FALSE === ($resampledimage = $medium->getResampledBinary(self::$image_mime))) {
61                         unset ($resampledimage);
62                         self::error ('NP_MediaUtils: Fail to generate resampled image');
63                         return;
64                 }
65                 
66                 header ('Content-type: ' . $medium->mime);
67                 echo $resampledimage;
68                 unset ($resampledimage);
69                 exit;
70         }
71         
72 /**
73  * Store resampled image binary to filesystem as file
74  * @access      Public  MediaUtils::storeResampledImage
75  * @param       String  $root                   root directory for media
76  * @param       String  $path                   Relative path from root to destination
77  * @param       Object  $medium         Medium Object
78  * @return      Boolean TRUE/FALSE
79  */
80         static public function storeResampledImage ($root, $target, $medium) {
81                 if (!class_exists('Medium', FALSE)) {
82                         include(self::$lib_path . '/Medium.php');
83                 }
84                 
85                 if ('Medium' !== get_class($medium)) {
86                         return FALSE;
87                 }
88                 
89                 if (FALSE === ($resampledimage = $medium->getResampledBinary(self::$image_mime))) {
90                         unset ($resampledimage);
91                         return FALSE;
92                 }
93                 
94                 if (FALSE === ($handle = @fopen ("{$root}/{$target}", 'w'))) {
95                         unset ($resampledimage);
96                         return FALSE;
97                 }
98                 
99                 if (@fwrite ($handle, $resampledimage) === FALSE) {
100                         unset ($resampledimage);
101                         @unlink ("{$root}/{$target}");
102                         return FALSE;
103                 }
104                 
105                 unset ($resampledimage);
106                 fclose ($handle);
107                 
108                 if (@chmod ("{$root}/{$target}", 0744) === FALSE) {
109                         @unlink ("{$root}/{$target}");
110                         return FALSE;
111                 }
112                 
113                 return TRUE;
114         }
115         
116 /**
117  * Check the path as directory and writable
118  * @access      Public  MediaUtils::checkDir
119  * @param       String  Fullpath
120  * @return      Boolean TRUE/FALSE
121  */
122         static public function checkDir ($fullpath) {
123                 $fullpath = (string) $fullpath;
124                 
125                 if (file_exists ($fullpath)) {
126                         if (is_dir ($fullpath) && is_writable ($fullpath)) {
127                                 return TRUE;
128                         } else {
129                                 return FALSE;
130                         }
131                 } else {
132                         if (!@mkdir ($fullpath, 0777)) {
133                                 return FALSE;
134                         } else {
135                                 return TRUE;
136                         }
137                 }
138         }
139         
140 /**
141  * Return file data list
142  * @access      Public  MediaUtils::getMediaList
143  * @param       String  $root           path to media root directory
144  * @param       Boolean $hidden show hidden files (.*) or not
145  * @param       Boolean $recursive      follow recursively or not
146  * @param       Boolean $prefix analyze its prefix or not
147  * @param       String  $suffix limit by suffix
148  * @param       String  $path           relative path from root to destination
149  * @return      Array           Array(Medium)
150  */
151         static public function getMediaList ($root, $hidden=TRUE, $recursive=TRUE, $suffix='', $path='', $media=array()) {
152                 $root           = (string)      $root;
153                 $hidden = (boolean) $hidden;
154                 $recursive      = (boolean) $recursive;
155                 $suffix = (string) $suffix;
156                 $path           = (string) $path;
157                 $media  = (array) $media;
158                 
159                 if (!class_exists('Medium', FALSE)) {
160                         include(self::$lib_path . '/Medium.php');
161                 }
162                 
163                 $root = rtrim($root, '/');
164                 if(!$root || !file_exists($root)) {
165                         return FALSE;
166                 }
167                 
168                 $fullpath = $root;
169                 if ($path) {
170                         $path = trim($path, '/');
171                         $fullpath = "{$root}/{$path}";
172                 }
173                 
174                 if (FALSE === ($handle = @opendir($fullpath))) {
175                         return FALSE;
176                 }
177                 while(FALSE !== ($filename = readdir($handle))) {
178                         if ($filename !== '.' && $filename !== '..') {
179                                 if (($hidden && preg_match("#^\.#", $filename))
180                                  || ($suffix && !preg_match("#\.$suffix$#", $filename))) {
181                                         continue;
182                                 }
183                                 
184                                 if($recursive && filetype("{$fullpath}/{$filename}") === "dir") {
185                                         $media = self::getMediaList($root, $hidden, $recursive, $suffix, trim("{$path}/{$filename}", '/'), $media);
186                                 } else if ($path !== '' && filetype("{$fullpath}/{$filename}") === "file") {
187                                         $media[] = new Medium($root, trim("{$path}/{$filename}", '/'), self::$prefix);
188                                         continue;
189                                 }
190                         }
191                 }
192                 closedir($handle);
193                 return $media;
194         }
195         
196 /*
197  * Purge directory
198  * @access      Public  MediaUtils::purgeDir
199  * @param       String  $root           path to media root directory
200  * @param       String  $path           relative path from root to destination
201  * @return      Array/FALSE             $logs           
202  * 
203  */
204         static public function purgeDir($root, $path='', $logs=array()) {
205                 $root   = (string) $root;
206                 $path   = (string) $path;
207                 $logs   = (array) $logs;
208                 
209                 $root = rtrim($root, '/');
210                 if(!$root || !file_exists($root)) {
211                         return FALSE;
212                 }
213                 
214                 $fullpath = $root;
215                 if ($path) {
216                         $path = trim($path, '/');
217                         $fullpath = "{$root}/{$path}";
218                 }
219                 
220                 if (FALSE === ($handle = @opendir($fullpath))) {
221                         return FALSE;
222                 }
223                 while(FALSE !== ($filename = readdir($handle))) {
224                         if ($filename !== '.' && $filename !== '..') {
225                                 if(filetype("{$fullpath}/{$filename}") === "dir") {
226                                         $logs = self::purgeDir($root, "{$path}/{$filename}", $logs);
227                                 } else {
228                                         if(!unlink("{$root}/{$path}/{$filename}")) {
229                                                 $logs[] = "Exists: {$path}/{$filename}";
230                                         } else {
231                                                 $logs[] = "Removed: {$path}/{$filename}";
232                                         }
233                                         continue;
234                                 }
235                         }
236                 }
237                 if(!rmdir("{$root}/{$path}")) {
238                         $logs[] = "Exists: {$path}";
239                 } else {
240                         $logs[] = "Removed: {$path}";
241                 }
242                 return $logs;
243         }
244
245 /*
246  * Return path list under root
247  * @access      Public  MediaUtils::getPathList
248  * @param       String  $root           full path to root directory
249  * @param       String  $path           certain path to search
250  * @param       Boolean $private        use private directory or not
251  * @param       Boolean $recursize      search recursively or not
252  * @param       Boolean $hidden do not list up the directory started with piriod or not
253  * @return      String  $name   
254  * 
255  */
256         static public function getPathList($root, $path='', $private=FALSE, $hidden=TRUE, $recursive=TRUE) {
257                 $root           = (string) $root;
258                 $path           = (string) $path;
259                 $hidden = (boolean) $hidden;
260                 $recursive = (boolean) $recursive;
261                 
262                 $paths=array();
263                 
264                 $root = rtrim($root, '/');
265                 if(!$root || !file_exists($root)) {
266                         return FALSE;
267                 }
268                 
269                 $fullpath = $root;
270                 if ($path) {
271                         $path = trim($path, '/');
272                         $fullpath = "{$root}/{$path}";
273                 }
274                 
275                 if (FALSE === ($handle = @opendir($fullpath))) {
276                         return FALSE;
277                 }
278                 while (FALSE !== ($filename = readdir($handle))) {
279                         if (in_array($filename, array('.', '..', 'CVS'))) {
280                                 continue;
281                         } else if (is_file("{$fullpath}/{$filename}")) {
282                                 continue;
283                         } else if ($hidden && preg_match('#^\.#', $filename)) {
284                                 continue;
285                         } else if ($private && is_numeric($filename) && $path==''&& $private != $filename) {
286                                 continue;
287                         }
288                         
289                         if (!$path) {
290                                 $relpath = $filename;
291                         } else {
292                                 $relpath = "{$path}/{$filename}";
293                         }
294                         
295                         $paths = self::getPathData($root, $relpath, $private, $hidden, $recursive, $paths);
296                 }
297                 closedir($handle);
298                 
299                 if ($path=='' && $private) {
300                         if (!array_key_exists($private, $paths)) {
301                                 $paths[$private] = array('root'=>$root , 'path'=>$private, 'files'=>0, 'dirs'=>0);
302                         }
303                         $paths[$private]['label'] = 'PRIVATE';
304                 }
305                 
306                 ksort($paths, SORT_STRING);
307                 return $paths;
308         }
309         
310 /*
311  * Return path data
312  * @access      Public  MediaUtils::getPathData
313  * @param       String  $root                   full path to root directory
314  * @param       String  $path                   relative path from root to target directory
315  * @param       Boolean $private                use private directory or not
316  * @param       Boolean $hidden         do not list up the directory started with piriod or not
317  * @param       Boolean $recursive      search recursively or not
318  * @return      Array           Array('root', 'parent', 'name', 'files', 'dirs', 'label')
319  */
320         static public function getPathData($root, $path, $private=FALSE, $hidden=TRUE, $recursive=FALSE, $paths=array()) {
321                 $root           = (string)      $root;
322                 $path           = (string)      $path;
323                 $private        = (boolean) $private;
324                 $hidden = (boolean) $hidden;
325                 $recursive = (boolean) $recursive;
326                 
327                 $cnt_files = 0;
328                 $cnt_dirs = 0;
329                 
330                 $root = rtrim($root, '/');
331                 if(!$root || !file_exists($root)) {
332                         return FALSE;
333                 }
334                 
335                 $fullpath = $root;
336                 if ($path) {
337                         $path = trim($path, '/');
338                         $fullpath = "{$root}/{$path}";
339                 }
340                 
341                 if (FALSE === ($handle = @opendir($fullpath))) {
342                         return FALSE;
343                 }
344                 while (FALSE !== ($filename = readdir($handle))) {
345                         if (in_array($filename, array('.', '..', 'CVS'))) {
346                                 continue;
347                         } else if (!is_dir("{$fullpath}/{$filename}")) {
348                                 if (!$hidden || !preg_match('#^\.#', $filename)){
349                                         $cnt_files++;
350                                 }
351                                 continue;
352                         } else if ($hidden && preg_match('#^\.#', $filename)) {
353                                 continue;
354                         }
355                         
356                         $cnt_dirs++;
357                         
358                         if (!$path) {
359                                 $relpath = $filename;
360                         } else {
361                                 $relpath = "{$path}/{$filename}";
362                         }
363                         
364                         if ($recursive) {
365                                 $paths = self::getPathData($root, $relpath, $private, $recursive, $hidden, $paths);
366                         }
367                 }
368                 closedir($handle);
369                 
370                 $paths[$path]['root'] = $root;
371                 $paths[$path]['parent'] = trim(str_replace(basename($fullpath), '', $path), '/');
372                 $paths[$path]['name'] = basename($fullpath);
373                 $paths[$path]['files'] = $cnt_files;
374                 $paths[$path]['dirs'] = $cnt_dirs;
375                 if ($private) {
376                         $paths[$path]['label'] = preg_replace("#^$private#", 'PRIVATE', $path);
377                 } else {
378                         $paths[$path]['label'] = $path;
379                 }
380                 
381                 return $paths;
382         }
383         
384 /*
385  * Store uploaded binary to filesystem
386  * @access      Public  MediaUtils::uploadMedium
387  * @param       String  $root                   path to edia root directory
388  * @param       String  $path                   relative path from root to target directory
389  * @param       Array           $medium         uploaded binary data.
390  * @param       String/FALSE    $overwrite      overwrite or not if the file already exists
391  * @param       Object  $manager                Nucleus Manager Object
392  * @return      String  $log                    Return '' if success, others is error messages
393  * 
394  */
395         static public function uploadMedium ($root, $path, &$temp, $overwrite='', &$manager='') {
396                 $root    = (string) $root;
397                 $path    = (string) $path;
398                 $temp = (array) $temp;
399                 $overwrite = (string) $overwrite;
400                 $manager = (object) $manager;
401                 
402                 /**
403                  * $temp should be derived from $_FILE
404                  */
405                 foreach(array('name', 'tmp_name','size', 'error') as $key) {
406                         if (!array_key_exists($key, $temp)) {
407                                 return 'NP_MediaUtils: Miss uploaded file.';
408                         }
409                 }
410                 
411                 $root = rtrim($root, '/');
412                 if(!$root || !file_exists($root) || !$path) {
413                         return 'NP_MediaUtils: Destination is invalid.';
414                 }
415                 $path = trim($path, '/');
416                 
417                 /**
418                  * see http://www.php.net/manual/en/features.file-upload.errors.php
419                  */
420                 switch ($temp['error']) {
421                         case UPLOAD_ERR_OK:
422                                 break;
423                         case UPLOAD_ERR_INI_SIZE:
424                         case UPLOAD_ERR_FORM_SIZE:
425                                 return 'NP_MediaUtils: Binary is too big.';
426                         case UPLOAD_ERR_PARTIAL:
427                         case UPLOAD_ERR_NO_FILE:
428                         case UPLOAD_ERR_NO_TMP_DIR:
429                         case UPLOAD_ERR_CANT_WRITE:
430                         case UPLOAD_ERR_EXTENSION :
431                         default:
432                                 return 'NP_MediaUtils: Request rejected';
433                 }
434                 
435                 if (preg_match ("#(\\\\|/|\\n)#", $temp['name'])) {
436                         return 'NP_MediaUtils: invalid filename';
437                 }
438                 
439                 if ($temp['size'] > self::$maxsize) {
440                         return 'NP_MediaUtils: Binary is too big';
441                 }
442                 
443                 if (!empty(self::$suffixes) && is_array(self::$suffixes)) {
444                         preg_match("#\.(.+)$#", $temp['name'], $match);
445                         $suffix = strtolower($match[1]);
446                         if (!in_array($suffix, self::$suffixes)) {
447                                 return 'NP_MediaUtils: Forbidden file suffix';
448                         }
449                 }
450                 
451                 if (!self::checkDir("{$root}/{$path}")) {
452                         return 'NP_MediaUtils: Invalid target directory';
453                 }
454                 
455                 if ($overwrite) {
456                         if (!preg_match("#\.($suffix)$#", strtolower($overwrite), $match)) {
457                                 return 'NP_MediaUtils: suffix is not the same.';
458                         }
459                         $temp['name'] = $overwrite;
460                 } else if (self::$prefix) {
461                         $temp['name'] = strftime ("%Y%m%d-", time ()) . $temp['name'];
462                 }
463                 
464                 if (!$overwrite && file_exists("{$root}/{$path}/{$temp['name']}")) {
465                         return 'NP_MediaUtils: The same filename already exists in this target directory.';
466                 }
467                 
468                 if ($manager) {
469                         $manager->notify('PreMediaUpload',array('collection' => &$path, 'uploadfile' => $temp['tmp_name'], 'filename' => $temp['name']));
470                 }
471                 
472                 if (is_uploaded_file($temp['tmp_name'])) {
473                         if (!@move_uploaded_file($temp['tmp_name'], "{$root}/{$path}/{$temp['name']}")) {
474                                         return 'NP_MediaUtils: Fail to move uploaded binary to file sytem.';
475                         }
476                 } else if (!copy($temp['tmp_name'], "{$root}/{$path}/{$temp['name']}")) {
477                                 return 'NP_MediaUtils: Fail to copy uploaded binary to file sytem.';
478                 }
479                 
480                 $oldumask = umask(0000);
481                 @chmod("{$root}/{$path}/{$temp['name']}", 0644);
482                 umask($oldumask);
483                 
484                 if ($manager) {
485                         $manager->notify('PostMediaUpload',array('collection' => $path, 'mediadir' => $root, 'filename' => $temp['name']));
486                 }
487                 
488                 return '';
489         }
490 }