OSDN Git Service

ADD: Mocchiが手がけたファイル管理プラグイン一式をコミット
[nucleus-jp/nucleus-plugins.git] / NP_MediaUtils / mediautils / MediaUtils.php
diff --git a/NP_MediaUtils/mediautils/MediaUtils.php b/NP_MediaUtils/mediautils/MediaUtils.php
new file mode 100755 (executable)
index 0000000..0766c01
--- /dev/null
@@ -0,0 +1,490 @@
+<?php
+/**
+ * MediaUtils plugin for Nucleus CMS
+ * Version 0.9.6 (1.0 RC2) for PHP5
+ * Written By Mocchi, Apr. 04, 2011
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 3
+ * of the License, or (at your option) any later version.
+ */
+
+class MediaUtils {
+       static public $lib_path = '';
+       
+       static public $cookiename = 'blogid';
+       static public $blogid = FALSE;
+       static public $blogs = array();
+       static public $bshortname = '';
+       
+       static public $prefix = TRUE;
+       static public $maxsize = 2097152;
+       static public $suffixes = array();
+       
+       static public $algorism = 'md5';
+       static public $image_mime
+               = array('image/jpeg'    => '.jpeg',
+                               'image/png'     => '.png',
+                       /*      'image/bmp'     => '.bmp', not implemented*/
+                               'image/gif'     => '.gif');
+       
+/**
+ * error and exit
+ * @access     Public  MediaUtils::error
+ * @param      String  $message                Error message
+ * @exit       
+ */
+       static public function error ($message) {
+               (string)        $message;
+               header("HTTP/1.0 404 Not Found");
+               exit($message);
+       }
+       
+/**
+ * send resampled image via HTTP
+ * @access     Public  MediaUtils::responseResampledImage
+ * @param      Object  $medium         Medium Object
+ * @exit       
+ */
+       static public function responseResampledImage ($medium) {
+               if (!class_exists('Medium', FALSE)) {
+                       include(self::$lib_path . '/Medium.php');
+               }
+               
+               if ('Medium' !== get_class($medium)) {
+                       self::error ('NP_MediaUtils: Fail to generate resampled image');
+                       return;
+               }
+               
+               if (FALSE === ($resampledimage = $medium->getResampledBinary(self::$image_mime))) {
+                       unset ($resampledimage);
+                       self::error ('NP_MediaUtils: Fail to generate resampled image');
+                       return;
+               }
+               
+               header ('Content-type: ' . $medium->mime);
+               echo $resampledimage;
+               unset ($resampledimage);
+               exit;
+       }
+       
+/**
+ * Store resampled image binary to filesystem as file
+ * @access     Public  MediaUtils::storeResampledImage
+ * @param      String  $root                   root directory for media
+ * @param      String  $path                   Relative path from root to destination
+ * @param      Object  $medium         Medium Object
+ * @return     Boolean TRUE/FALSE
+ */
+       static public function storeResampledImage ($root, $target, $medium) {
+               if (!class_exists('Medium', FALSE)) {
+                       include(self::$lib_path . '/Medium.php');
+               }
+               
+               if ('Medium' !== get_class($medium)) {
+                       return FALSE;
+               }
+               
+               if (FALSE === ($resampledimage = $medium->getResampledBinary(self::$image_mime))) {
+                       unset ($resampledimage);
+                       return FALSE;
+               }
+               
+               if (FALSE === ($handle = @fopen ("{$root}/{$target}", 'w'))) {
+                       unset ($resampledimage);
+                       return FALSE;
+               }
+               
+               if (@fwrite ($handle, $resampledimage) === FALSE) {
+                       unset ($resampledimage);
+                       @unlink ("{$root}/{$target}");
+                       return FALSE;
+               }
+               
+               unset ($resampledimage);
+               fclose ($handle);
+               
+               if (@chmod ("{$root}/{$target}", 0744) === FALSE) {
+                       @unlink ("{$root}/{$target}");
+                       return FALSE;
+               }
+               
+               return TRUE;
+       }
+       
+/**
+ * Check the path as directory and writable
+ * @access     Public  MediaUtils::checkDir
+ * @param      String  Fullpath
+ * @return     Boolean TRUE/FALSE
+ */
+       static public function checkDir ($fullpath) {
+               $fullpath = (string) $fullpath;
+               
+               if (file_exists ($fullpath)) {
+                       if (is_dir ($fullpath) && is_writable ($fullpath)) {
+                               return TRUE;
+                       } else {
+                               return FALSE;
+                       }
+               } else {
+                       if (!@mkdir ($fullpath, 0777)) {
+                               return FALSE;
+                       } else {
+                               return TRUE;
+                       }
+               }
+       }
+       
+/**
+ * Return file data list
+ * @access     Public  MediaUtils::getMediaList
+ * @param      String  $root           path to media root directory
+ * @param      Boolean $hidden show hidden files (.*) or not
+ * @param      Boolean $recursive      follow recursively or not
+ * @param      Boolean $prefix analyze its prefix or not
+ * @param      String  $suffix limit by suffix
+ * @param      String  $path           relative path from root to destination
+ * @return     Array           Array(Medium)
+ */
+       static public function getMediaList ($root, $hidden=TRUE, $recursive=TRUE, $suffix='', $path='', $media=array()) {
+               $root           = (string)      $root;
+               $hidden = (boolean) $hidden;
+               $recursive      = (boolean) $recursive;
+               $suffix = (string) $suffix;
+               $path           = (string) $path;
+               $media  = (array) $media;
+               
+               if (!class_exists('Medium', FALSE)) {
+                       include(self::$lib_path . '/Medium.php');
+               }
+               
+               $root = rtrim($root, '/');
+               if(!$root || !file_exists($root)) {
+                       return FALSE;
+               }
+               
+               $fullpath = $root;
+               if ($path) {
+                       $path = trim($path, '/');
+                       $fullpath = "{$root}/{$path}";
+               }
+               
+               if (FALSE === ($handle = @opendir($fullpath))) {
+                       return FALSE;
+               }
+               while(FALSE !== ($filename = readdir($handle))) {
+                       if ($filename !== '.' && $filename !== '..') {
+                               if (($hidden && preg_match("#^\.#", $filename))
+                                || ($suffix && !preg_match("#\.$suffix$#", $filename))) {
+                                       continue;
+                               }
+                               
+                               if($recursive && filetype("{$fullpath}/{$filename}") === "dir") {
+                                       $media = self::getMediaList($root, $hidden, $recursive, $suffix, trim("{$path}/{$filename}", '/'), $media);
+                               } else if ($path !== '' && filetype("{$fullpath}/{$filename}") === "file") {
+                                       $media[] = new Medium($root, trim("{$path}/{$filename}", '/'), self::$prefix);
+                                       continue;
+                               }
+                       }
+               }
+               closedir($handle);
+               return $media;
+       }
+       
+/*
+ * Purge directory
+ * @access     Public  MediaUtils::purgeDir
+ * @param      String  $root           path to media root directory
+ * @param      String  $path           relative path from root to destination
+ * @return     Array/FALSE             $logs           
+ * 
+ */
+       static public function purgeDir($root, $path='', $logs=array()) {
+               $root   = (string) $root;
+               $path   = (string) $path;
+               $logs   = (array) $logs;
+               
+               $root = rtrim($root, '/');
+               if(!$root || !file_exists($root)) {
+                       return FALSE;
+               }
+               
+               $fullpath = $root;
+               if ($path) {
+                       $path = trim($path, '/');
+                       $fullpath = "{$root}/{$path}";
+               }
+               
+               if (FALSE === ($handle = @opendir($fullpath))) {
+                       return FALSE;
+               }
+               while(FALSE !== ($filename = readdir($handle))) {
+                       if ($filename !== '.' && $filename !== '..') {
+                               if(filetype("{$fullpath}/{$filename}") === "dir") {
+                                       $logs = self::purgeDir($root, "{$path}/{$filename}", $logs);
+                               } else {
+                                       if(!unlink("{$root}/{$path}/{$filename}")) {
+                                               $logs[] = "Exists: {$path}/{$filename}";
+                                       } else {
+                                               $logs[] = "Removed: {$path}/{$filename}";
+                                       }
+                                       continue;
+                               }
+                       }
+               }
+               if(!rmdir("{$root}/{$path}")) {
+                       $logs[] = "Exists: {$path}";
+               } else {
+                       $logs[] = "Removed: {$path}";
+               }
+               return $logs;
+       }
+
+/*
+ * Return path list under root
+ * @access     Public  MediaUtils::getPathList
+ * @param      String  $root           full path to root directory
+ * @param      String  $path           certain path to search
+ * @param      Boolean $private        use private directory or not
+ * @param      Boolean $recursize      search recursively or not
+ * @param      Boolean $hidden do not list up the directory started with piriod or not
+ * @return     String  $name   
+ * 
+ */
+       static public function getPathList($root, $path='', $private=FALSE, $hidden=TRUE, $recursive=TRUE) {
+               $root           = (string) $root;
+               $path           = (string) $path;
+               $hidden = (boolean) $hidden;
+               $recursive = (boolean) $recursive;
+               
+               $paths=array();
+               
+               $root = rtrim($root, '/');
+               if(!$root || !file_exists($root)) {
+                       return FALSE;
+               }
+               
+               $fullpath = $root;
+               if ($path) {
+                       $path = trim($path, '/');
+                       $fullpath = "{$root}/{$path}";
+               }
+               
+               if (FALSE === ($handle = @opendir($fullpath))) {
+                       return FALSE;
+               }
+               while (FALSE !== ($filename = readdir($handle))) {
+                       if (in_array($filename, array('.', '..', 'CVS'))) {
+                               continue;
+                       } else if (is_file("{$fullpath}/{$filename}")) {
+                               continue;
+                       } else if ($hidden && preg_match('#^\.#', $filename)) {
+                               continue;
+                       } else if ($private && is_numeric($filename) && $path==''&& $private != $filename) {
+                               continue;
+                       }
+                       
+                       if (!$path) {
+                               $relpath = $filename;
+                       } else {
+                               $relpath = "{$path}/{$filename}";
+                       }
+                       
+                       $paths = self::getPathData($root, $relpath, $private, $hidden, $recursive, $paths);
+               }
+               closedir($handle);
+               
+               if ($path=='' && $private) {
+                       if (!array_key_exists($private, $paths)) {
+                               $paths[$private] = array('root'=>$root , 'path'=>$private, 'files'=>0, 'dirs'=>0);
+                       }
+                       $paths[$private]['label'] = 'PRIVATE';
+               }
+               
+               ksort($paths, SORT_STRING);
+               return $paths;
+       }
+       
+/*
+ * Return path data
+ * @access     Public  MediaUtils::getPathData
+ * @param      String  $root                   full path to root directory
+ * @param      String  $path                   relative path from root to target directory
+ * @param      Boolean $private                use private directory or not
+ * @param      Boolean $hidden         do not list up the directory started with piriod or not
+ * @param      Boolean $recursive      search recursively or not
+ * @return     Array           Array('root', 'parent', 'name', 'files', 'dirs', 'label')
+ */
+       static public function getPathData($root, $path, $private=FALSE, $hidden=TRUE, $recursive=FALSE, $paths=array()) {
+               $root           = (string)      $root;
+               $path           = (string)      $path;
+               $private        = (boolean) $private;
+               $hidden = (boolean) $hidden;
+               $recursive = (boolean) $recursive;
+               
+               $cnt_files = 0;
+               $cnt_dirs = 0;
+               
+               $root = rtrim($root, '/');
+               if(!$root || !file_exists($root)) {
+                       return FALSE;
+               }
+               
+               $fullpath = $root;
+               if ($path) {
+                       $path = trim($path, '/');
+                       $fullpath = "{$root}/{$path}";
+               }
+               
+               if (FALSE === ($handle = @opendir($fullpath))) {
+                       return FALSE;
+               }
+               while (FALSE !== ($filename = readdir($handle))) {
+                       if (in_array($filename, array('.', '..', 'CVS'))) {
+                               continue;
+                       } else if (!is_dir("{$fullpath}/{$filename}")) {
+                               if (!$hidden || !preg_match('#^\.#', $filename)){
+                                       $cnt_files++;
+                               }
+                               continue;
+                       } else if ($hidden && preg_match('#^\.#', $filename)) {
+                               continue;
+                       }
+                       
+                       $cnt_dirs++;
+                       
+                       if (!$path) {
+                               $relpath = $filename;
+                       } else {
+                               $relpath = "{$path}/{$filename}";
+                       }
+                       
+                       if ($recursive) {
+                               $paths = self::getPathData($root, $relpath, $private, $recursive, $hidden, $paths);
+                       }
+               }
+               closedir($handle);
+               
+               $paths[$path]['root'] = $root;
+               $paths[$path]['parent'] = trim(str_replace(basename($fullpath), '', $path), '/');
+               $paths[$path]['name'] = basename($fullpath);
+               $paths[$path]['files'] = $cnt_files;
+               $paths[$path]['dirs'] = $cnt_dirs;
+               if ($private) {
+                       $paths[$path]['label'] = preg_replace("#^$private#", 'PRIVATE', $path);
+               } else {
+                       $paths[$path]['label'] = $path;
+               }
+               
+               return $paths;
+       }
+       
+/*
+ * Store uploaded binary to filesystem
+ * @access     Public  MediaUtils::uploadMedium
+ * @param      String  $root                   path to edia root directory
+ * @param      String  $path                   relative path from root to target directory
+ * @param      Array           $medium         uploaded binary data.
+ * @param      String/FALSE    $overwrite      overwrite or not if the file already exists
+ * @param      Object  $manager                Nucleus Manager Object
+ * @return     String  $log                    Return '' if success, others is error messages
+ * 
+ */
+       static public function uploadMedium ($root, $path, &$temp, $overwrite='', &$manager='') {
+               $root    = (string) $root;
+               $path    = (string) $path;
+               $temp = (array) $temp;
+               $overwrite = (string) $overwrite;
+               $manager = (object) $manager;
+               
+               /**
+                * $temp should be derived from $_FILE
+                */
+               foreach(array('name', 'tmp_name','size', 'error') as $key) {
+                       if (!array_key_exists($key, $temp)) {
+                               return 'NP_MediaUtils: Miss uploaded file.';
+                       }
+               }
+               
+               $root = rtrim($root, '/');
+               if(!$root || !file_exists($root) || !$path) {
+                       return 'NP_MediaUtils: Destination is invalid.';
+               }
+               $path = trim($path, '/');
+               
+               /**
+                * see http://www.php.net/manual/en/features.file-upload.errors.php
+                */
+               switch ($temp['error']) {
+                       case UPLOAD_ERR_OK:
+                               break;
+                       case UPLOAD_ERR_INI_SIZE:
+                       case UPLOAD_ERR_FORM_SIZE:
+                               return 'NP_MediaUtils: Binary is too big.';
+                       case UPLOAD_ERR_PARTIAL:
+                       case UPLOAD_ERR_NO_FILE:
+                       case UPLOAD_ERR_NO_TMP_DIR:
+                       case UPLOAD_ERR_CANT_WRITE:
+                       case UPLOAD_ERR_EXTENSION :
+                       default:
+                               return 'NP_MediaUtils: Request rejected';
+               }
+               
+               if (preg_match ("#(\\\\|/|\\n)#", $temp['name'])) {
+                       return 'NP_MediaUtils: invalid filename';
+               }
+               
+               if ($temp['size'] > self::$maxsize) {
+                       return 'NP_MediaUtils: Binary is too big';
+               }
+               
+               if (!empty(self::$suffixes) && is_array(self::$suffixes)) {
+                       preg_match("#\.(.+)$#", $temp['name'], $match);
+                       $suffix = strtolower($match[1]);
+                       if (!in_array($suffix, self::$suffixes)) {
+                               return 'NP_MediaUtils: Forbidden file suffix';
+                       }
+               }
+               
+               if (!self::checkDir("{$root}/{$path}")) {
+                       return 'NP_MediaUtils: Invalid target directory';
+               }
+               
+               if ($overwrite) {
+                       if (!preg_match("#\.($suffix)$#", strtolower($overwrite), $match)) {
+                               return 'NP_MediaUtils: suffix is not the same.';
+                       }
+                       $temp['name'] = $overwrite;
+               } else if (self::$prefix) {
+                       $temp['name'] = strftime ("%Y%m%d-", time ()) . $temp['name'];
+               }
+               
+               if (!$overwrite && file_exists("{$root}/{$path}/{$temp['name']}")) {
+                       return 'NP_MediaUtils: The same filename already exists in this target directory.';
+               }
+               
+               if ($manager) {
+                       $manager->notify('PreMediaUpload',array('collection' => &$path, 'uploadfile' => $temp['tmp_name'], 'filename' => $temp['name']));
+               }
+               
+               if (is_uploaded_file($temp['tmp_name'])) {
+                       if (!@move_uploaded_file($temp['tmp_name'], "{$root}/{$path}/{$temp['name']}")) {
+                                       return 'NP_MediaUtils: Fail to move uploaded binary to file sytem.';
+                       }
+               } else if (!copy($temp['tmp_name'], "{$root}/{$path}/{$temp['name']}")) {
+                               return 'NP_MediaUtils: Fail to copy uploaded binary to file sytem.';
+               }
+               
+               $oldumask = umask(0000);
+               @chmod("{$root}/{$path}/{$temp['name']}", 0644);
+               umask($oldumask);
+               
+               if ($manager) {
+                       $manager->notify('PostMediaUpload',array('collection' => $path, 'mediadir' => $root, 'filename' => $temp['name']));
+               }
+               
+               return '';
+       }
+}