OSDN Git Service

本家Nucleus CMS 4.0のリビジョン1626をコミット
[nucleus-jp/nucleus-next.git] / nucleus / libs / MEDIA.php
1 <?php
2 /*
3  * Nucleus: PHP/MySQL Weblog CMS (http://nucleuscms.org/)
4  * Copyright (C) 2002-2009 The Nucleus Group
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  * (see nucleus/documentation/index.html#license for more info)
11  */
12 /**
13  * Media classes for nucleus
14  *
15  * @license http://nucleuscms.org/license.txt GNU General Public License
16  * @copyright Copyright (C) 2002-2009 The Nucleus Group
17  * @version $Id: MEDIA.php 1525 2011-06-21 10:20:19Z sakamocchi $
18  */
19
20 define('PRIVATE_COLLECTION', 'Private Collection');
21 define('READ_ONLY_MEDIA_FOLDER', '(Read Only)');
22
23 /**
24   * Represents the media objects for a certain member
25   */
26 class MEDIA {
27
28         /**
29           * Gets the list of collections available to the currently logged
30           * in member
31           *
32           * @returns array of dirname => display name
33           */
34         function getCollectionList($exceptReadOnly = false) {
35                 global $member, $DIR_MEDIA;
36
37                 $collections = array();
38
39                 // add private directory for member
40                 $collections[$member->getID()] = PRIVATE_COLLECTION;
41
42                 // add global collections
43                 if (!is_dir($DIR_MEDIA)) return $collections;
44
45                 $dirhandle = opendir($DIR_MEDIA);
46                 while ($dirname = readdir($dirhandle)) {
47                         // only add non-numeric (numeric=private) dirs
48                         if (@is_dir($DIR_MEDIA . $dirname) &&
49                                 ($dirname != '.') &&
50                                 ($dirname != '..') &&
51                                 ($dirname != 'CVS') &&
52                                 (!is_numeric($dirname)))  {
53                                 if (@is_writable($DIR_MEDIA . $dirname))
54                                         $collections[$dirname] = $dirname;
55                                 else if ($exceptReadOnly == false)
56                                         $collections[$dirname] = $dirname . ' ' . READ_ONLY_MEDIA_FOLDER;
57                         }
58                 }
59                 closedir($dirhandle);
60
61                 return $collections;
62
63         }
64
65         /**
66           * Returns an array of MEDIAOBJECT objects for a certain collection
67           *
68           * @param $collection
69           *             name of the collection
70           * @param $filter
71           *             filter on filename (defaults to none)
72           */
73         function getMediaListByCollection($collection, $filter = '') {
74                 global $DIR_MEDIA;
75
76                 $filelist = array();
77
78                 // 1. go through all objects and add them to the filelist
79
80                 $mediadir = $DIR_MEDIA . $collection . '/';
81
82                 // return if dir does not exist
83                 if (!is_dir($mediadir)) return $filelist;
84
85                 $dirhandle = opendir($mediadir);
86                 while ($filename = readdir($dirhandle)) {
87                         // only add files that match the filter
88                         if (!@is_dir($filename) && MEDIA::checkFilter($filename, $filter))
89                                 array_push($filelist, new MEDIAOBJECT($collection, $filename, filemtime($mediadir . $filename)));
90                 }
91                 closedir($dirhandle);
92
93                 // sort array so newer files are shown first
94                 usort($filelist, 'sort_media');
95
96                 return $filelist;
97         }
98
99         function checkFilter($strText, $strFilter) {
100                 if ($strFilter == '')
101                         return 1;
102                 else
103                         return is_integer(i18n::strpos(strtolower($strText), strtolower($strFilter)));
104         }
105
106         /**
107           * checks if a collection exists with the given name, and if it's
108           * allowed for the currently logged in member to upload files to it
109           */
110         function isValidCollection($collectionName, $exceptReadOnly = false) {
111                 global $member, $DIR_MEDIA;
112
113                 // allow creating new private directory
114                 if ($collectionName === (string)$member->getID())
115                         return true;
116                         
117                 $collections = MEDIA::getCollectionList($exceptReadOnly);
118                 $dirname = $collections[$collectionName];
119                 if ($dirname == NULL || $dirname === PRIVATE_COLLECTION)
120                         return false;  
121
122                 // other collections should exist and be writable
123                 $collectionDir = $DIR_MEDIA . $collectionName;
124                 if ($exceptReadOnly)
125                         return (@is_dir($collectionDir) && @is_writable($collectionDir));
126
127                 // other collections should exist
128                 return @is_dir($collectionDir);
129        }
130
131         /**
132           * Adds an uploaded file to the media archive
133           *
134           * @param collection
135           *             collection
136           * @param uploadfile
137           *             the postFileInfo(..) array
138           * @param filename
139           *             the filename that should be used to save the file as
140           *             (date prefix should be already added here)
141           */
142         function addMediaObject($collection, $uploadfile, $filename) {
143                 global $DIR_MEDIA, $manager;
144
145                 // clean filename of characters that may cause trouble in a filename using cleanFileName() function from globalfunctions.php
146                 $filename = cleanFileName($filename);
147                 // should already have tested for allowable types before calling this method. This will only catch files with no extension at all
148                 if ($filename === false) 
149                         return _ERROR_BADFILETYPE;
150                 
151                 // trigger PreMediaUpload event
152                 $manager->notify('PreMediaUpload',array('collection' => &$collection, 'uploadfile' => $uploadfile, 'filename' => &$filename));
153
154                 // don't allow uploads to unknown or forbidden collections
155                 $exceptReadOnly = true;
156                 if (!MEDIA::isValidCollection($collection,$exceptReadOnly))
157                         return _ERROR_DISALLOWED;
158
159                 // check dir permissions (try to create dir if it does not exist)
160                 $mediadir = $DIR_MEDIA . $collection;
161
162                 // try to create new private media directories if needed
163                 if (!@is_dir($mediadir) && is_numeric($collection)) {
164                         $oldumask = umask(0000);
165                         if (!@mkdir($mediadir, 0777))
166                                 return _ERROR_BADPERMISSIONS;
167                         umask($oldumask);
168                 }
169
170                 // if dir still not exists, the action is disallowed
171                 if (!@is_dir($mediadir))
172                         return _ERROR_DISALLOWED;
173
174                 if (!is_writeable($mediadir))
175                         return _ERROR_BADPERMISSIONS;
176
177                 // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)
178                 $mediadir .= '/';
179
180                 if (file_exists($mediadir . $filename))
181                         return _ERROR_UPLOADDUPLICATE;
182
183                 // move file to directory
184                 if (is_uploaded_file($uploadfile)) {
185                         if (!@move_uploaded_file($uploadfile, $mediadir . $filename))
186                                 return _ERROR_UPLOADMOVEP;
187                 } else {
188                         if (!copy($uploadfile, $mediadir . $filename))
189                                 return _ERROR_UPLOADCOPY ;
190                 }
191
192                 // chmod uploaded file
193                 $oldumask = umask(0000);
194                 @chmod($mediadir . $filename, 0644);
195                 umask($oldumask);
196
197                 $manager->notify('PostMediaUpload',array('collection' => $collection, 'mediadir' => $mediadir, 'filename' => $filename));
198
199                 return '';
200
201         }
202
203         /**
204          * Adds an uploaded file to the media dir.
205          *
206          * @param $collection
207          *              collection to use
208          * @param $filename
209          *              the filename that should be used to save the file as
210          *              (date prefix should be already added here)
211          * @param &$data
212          *              File data (binary)
213          *
214          * NOTE: does not check if $collection is valid.
215          */
216         function addMediaObjectRaw($collection, $filename, &$data) {
217                 global $DIR_MEDIA;
218
219                 // check dir permissions (try to create dir if it does not exist)
220                 $mediadir = $DIR_MEDIA . $collection;
221
222                 // try to create new private media directories if needed
223                 if (!@is_dir($mediadir) && is_numeric($collection)) {
224                         $oldumask = umask(0000);
225                         if (!@mkdir($mediadir, 0777))
226                                 return _ERROR_BADPERMISSIONS;
227                         umask($oldumask);
228                 }
229
230                 // if dir still not exists, the action is disallowed
231                 if (!@is_dir($mediadir))
232                         return _ERROR_DISALLOWED;
233
234                 if (!is_writeable($mediadir))
235                         return _ERROR_BADPERMISSIONS;
236
237                 // add trailing slash (don't add it earlier since it causes mkdir to fail on some systems)
238                 $mediadir .= '/';
239
240                 if (file_exists($mediadir . $filename))
241                         return _ERROR_UPLOADDUPLICATE;
242
243                 // create file
244                 $fh = @fopen($mediadir . $filename, 'wb');
245                 if (!$fh)
246                         return _ERROR_UPLOADFAILED;
247                 $ok = @fwrite($fh, $data);
248                 @fclose($fh);
249                 if (!$ok)
250                         return _ERROR_UPLOADFAILED;
251
252                 // chmod uploaded file
253                 $oldumask = umask(0000);
254                 @chmod($mediadir . $filename, 0644);
255                 umask($oldumask);
256
257                 return '';
258
259         }
260
261 }
262
263 /**
264   * Represents the characteristics of one single media-object
265   *
266   * Description of properties:
267   *  - filename: filename, without paths
268   *  - timestamp: last modification (unix timestamp)
269   *  - collection: collection to which the file belongs (can also be a owner ID, for private collections)
270   *  - private: true if the media belongs to a private member collection
271   */
272 class MEDIAOBJECT {
273
274         var $private;
275         var $collection;
276         var $filename;
277         var $timestamp;
278
279         function MEDIAOBJECT($collection, $filename, $timestamp) {
280                 $this->private = is_numeric($collection);
281                 $this->collection = $collection;
282                 $this->filename = $filename;
283                 $this->timestamp = $timestamp;
284         }
285
286 }
287
288 /**
289   * User-defined sort method to sort an array of MEDIAOBJECTS
290   */
291 function sort_media($a, $b) {
292         if ($a->timestamp == $b->timestamp) return 0;
293         return ($a->timestamp > $b->timestamp) ? -1 : 1;
294 }
295
296 ?>