]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/IO/FileTrait.php
a983ac6d34ff2ea5e0b4bd7cf833a3ec52ad9821
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2013-2014 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2013-2014 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
34 * @link http://galette.tuxfamily.org
35 * @since Available since 0.8.1 - 2014-09-18
48 * @author Johan Cwiklinski <johan@x-tnd.be>
49 * @copyright 2013-2014 The Galette Team
50 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
51 * @link http://galette.tuxfamily.org
52 * @since Available since 0.8.1 - 2014-09-18
57 //array keys contain litteral value of each forbidden character
58 //(to be used when showing an error).
59 //Maybe is there a better way to handle this...
60 protected $bad_chars = array(
77 protected $allowed_extensions = array();
78 protected $allowed_mimes = array();
81 public static $mime_types = array(
82 'txt' => 'text/plain',
84 'html' => 'text/html',
85 'xhtml' => 'application/xhtml+xml',
86 'xht' => 'application/xhtml+xml',
89 'js' => 'application/javascript',
90 'json' => 'application/json',
91 'xml' => 'application/xml',
92 'xslt' => 'application/xslt+xml',
93 'xsl' => 'application/xml',
94 'dtd' => 'application/xml-dtd',
95 'atom' => 'application/atom+xml',
96 'mathml' => 'application/mathml+xml',
97 'rdf' => 'application/rdf+xml',
98 'smi' => 'application/smil',
99 'smil' => 'application/smil',
100 'vxml' => 'application/voicexml+xml',
101 'latex' => 'application/x-latex',
102 'tcl' => 'application/x-tcl',
103 'tex' => 'application/x-tex',
104 'texinfo' => 'application/x-texinfo',
105 'wrl' => 'model/vrml',
106 'wrml' => 'model/vrml',
107 'ics' => 'text/calendar',
108 'ifb' => 'text/calendar',
109 'sgml' => 'text/sgml',
110 'htc' => 'text/x-component',
111 'pgp' => 'application/pgp-signature',
112 'rtf' => 'application/rtf',
114 'png' => 'image/png',
115 'jpeg' => 'image/jpeg',
116 'jpg' => 'image/jpeg',
117 'gif' => 'image/gif',
118 'bmp' => 'image/bmp',
119 'ico' => 'image/x-icon',
120 'tiff' => 'image/tiff',
121 'tif' => 'image/tiff',
122 'svg' => 'image/svg+xml',
123 'svgz' => 'image/svg+xml',
124 'djvu' => 'image/vnd.djvu',
125 'djv' => 'image/vnd.djvu',
127 'zip' => 'application/zip',
128 'rar' => 'application/x-rar-compressed',
129 'tar' => 'application/x-tar',
130 'gz' => 'application/x-gzip',
131 'tgz' => 'application/x-gzip',
132 'bz2' => 'application/x-bzip2',
134 'mp2' => 'audio/mpeg',
135 'mp3' => 'audio/mpeg',
136 'qt' => 'video/quicktime',
137 'mov' => 'video/quicktime',
138 'mpeg' => 'video/mpeg',
139 'mpg' => 'video/mpeg',
140 'mpe' => 'video/mpeg',
141 'wav' => 'audio/wav',
142 'aiff' => 'audio/aiff',
143 'aif' => 'audio/aiff',
144 'avi' => 'video/msvideo',
145 'wmv' => 'video/x-ms-wmv',
146 'ogg' => 'application/ogg',
147 'flv' => 'video/x-flv',
148 'dvi' => 'application/x-dvi',
149 'au' => 'audio/basic',
150 'snd' => 'audio/basic',
151 'mid' => 'audio/midi',
152 'midi' => 'audio/midi',
153 'm3u' => 'audio/x-mpegurl',
154 'm4u' => 'video/vnd.mpegurl',
155 'ram' => 'audio/x-pn-realaudio',
156 'ra' => 'audio/x-pn-realaudio',
157 'rm' => 'application/vnd.rn-realmedia',
159 'pdf' => 'application/pdf',
160 'psd' => 'image/vnd.adobe.photoshop',
161 'ai' => 'application/postscript',
162 'eps' => 'application/postscript',
163 'ps' => 'application/postscript',
164 'swf' => 'application/x-shockwave-flash',
166 'doc' => 'application/msword',
167 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
168 'xls' => 'application/vnd.ms-excel',
169 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
170 'ppt' => 'application/vnd.ms-powerpoint',
171 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
172 'pps' => 'application/vnd.ms-powerpoint',
174 'odt' => 'application/vnd.oasis.opendocument.text',
175 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
176 'odc' => 'application/vnd.oasis.opendocument.chart',
177 'odb' => 'application/vnd.oasis.opendocument.database',
178 'odg' => 'application/vnd.oasis.opendocument.graphics',
179 'odp' => 'application/vnd.oasis.opendocument.presentation',
185 * @param string $dest File destination directory
186 * @param array $extensions Array of permitted extensions
187 * @param array $mimes Array of permitted mime types
188 * @param int $maxlenght Maximum lenght for each file
192 protected function init(
198 if ($dest !== null && substr($dest, -1) !== '/') {
202 $this->dest_dir
= $dest;
203 if ($extensions !== null) {
204 $this->allowed_extensions
= $extensions;
206 if ($mimes !== null) {
207 $this->allowed_mimes
= $mimes;
209 if ($maxlenght !== null) {
210 $this->maxlenght
= $maxlenght;
212 $this->maxlenght
= self
::MAX_FILE_SIZE
;
217 * Copy existing file to new Location
219 * @param string $dest Destination directory
223 public function copyTo($dest)
226 $this->dest_dir
. $this->name
,
230 $this->dest_dir
= $dest;
236 * Stores an file on the disk
238 * @param object $file the uploaded file
239 * @param boolean $ajax If the file cames from an ajax call (dnd)
241 * @return true|false result of the storage process
243 public function store($file, $ajax = false)
245 $class = get_class($this);
247 $this->name
= $file['name'];
248 $tmpfile = $file['tmp_name'];
250 //First, does the file have a valid name?
251 $reg = "/^([^" . implode('', $this->bad_chars
) . "]+)\.";
252 if (count($this->allowed_extensions
) > 0) {
253 $reg .= "(" . implode('|', $this->allowed_extensions
) . ")";
258 if (preg_match($reg, $this->name
, $matches)) {
260 '[' . $class . '] Filename and extension are OK, proceed.',
263 $extension = strtolower($matches[2]);
265 $erreg = "/^([^" . implode('', $this->bad_chars
) . "]+)\.(.*)/i";
266 $m = preg_match($erreg, $this->name
, $errmatches);
268 $err_msg = '[' . $class . '] ';
270 //ok, we got a good filename and an extension. Extension is bad :)
271 $err_msg .= 'Invalid extension for file ' . $this->name
. '.';
272 $ret = self
::INVALID_EXTENSION
;
274 $err_msg = 'Invalid filename `' . $this->name
. '` (Tip: ';
275 $err_msg .= preg_replace(
277 htmlentities($this->getBadChars()),
278 "file name should not contain any of: %s). "
280 $ret = self
::INVALID_FILENAME
;
290 //Second, let's check file size
291 if ($file['size'] > ($this->maxlenght
* 1024)) {
293 '[' . $class . '] File is too big (' . ($file['size'] * 1024) .
294 'Ko for maximum authorized ' . ($this->maxlenght
* 1024) .
298 return self
::FILE_TOO_BIG
;
300 Analog
::log('[' . $class . '] Filesize is OK, proceed', Analog
::DEBUG
);
303 $mime = $this->getMimeType($tmpfile);
306 count($this->allowed_mimes
) > 0
307 && !in_array($mime, $this->allowed_mimes
)
310 '[' . $class . '] Mimetype `' . $mime . '` not allowed',
313 return self
::MIME_NOT_ALLOWED
;
316 '[' . $class . '] Mimetype is allowed, proceed',
321 $new_file = $this->dest_dir
. $this->name
;
323 if (file_exists($new_file)) {
325 '[' . $class . '] File `' . $new_file . '` already exists',
328 return self
::NEW_FILE_EXISTS
;
332 if ($ajax === true) {
333 $in_place = rename($tmpfile, $new_file);
335 $in_place = move_uploaded_file($tmpfile, $new_file);
338 if ($in_place === false) {
339 return self
::CANT_WRITE
;
345 * Get destination dir
349 public function getDestDir()
351 return $this->dest_dir
;
355 * Set destination directory
357 * @param string $dir Directory
361 public function setDestDir($dir)
363 $this->dest_dir
= $dir;
371 public function getFileName()
379 * @param string $name file name
383 public function setFileName($name)
389 * Returns unauthorized characters litteral values quoted, comma separated values
391 * @return string comma separated disallowed characters
393 public function getBadChars()
395 return '`' . implode('`, `', array_keys($this->bad_chars
)) . '`';
399 * Returns allowed extensions
401 * @return string comma separated allowed extensiosn
403 public function getAllowedExts()
405 return implode(', ', $this->allowed_extensions
);
409 * Return the array of allowed mime types
413 public function getAllowedMimeTypes()
415 return $this->allowed_mimes
;
421 * @param string $file File
425 public static function getMimeType($file)
428 $class = get_called_class();
430 if (function_exists('finfo_open')) {
432 '[' . $class . '] Function File Info exist ',
435 $finfo = finfo_open(FILEINFO_MIME_TYPE
);
436 $mime = finfo_file($finfo, $file);
438 } elseif (function_exists('mime_content_type')) {
440 '[' . $class . '] Function mime_content_type exist ',
443 $mime = mime_content_type($file);
446 '[' . $class . '] Search from extension ',
449 $exploded = explode('.', $file);
450 $ext = strtolower(array_pop($exploded));
452 '[' . $class . '] Extension : ' . $ext,
455 if (array_key_exists($ext, self
::$mime_types)) {
456 $mime = self
::$mime_types[$ext];
458 $mime = 'application/octet-stream';
463 '[' . $class . '] Found mimetype : ' . $mime . ' for file ' . $file,
470 * Return textual error message
472 * @param int $code The error code
474 * @return string Localized message
476 protected function getErrorMessageFromCode($code)
478 $error = _T("An error occurred.");
481 case self
::INVALID_FILENAME
:
482 $error = _T("File name is invalid, it should not contain any special character or space.");
484 case self
::INVALID_EXTENSION
:
485 $error = preg_replace(
487 $this->getAllowedExts(),
488 _T("File extension is not allowed, only %s files are.")
491 case self
::FILE_TOO_BIG
:
492 $error = preg_replace(
495 _T("File is too big. Maximum allowed size is %dKo")
498 case self
::MIME_NOT_ALLOWED
:
499 /** FIXME: should be more descriptive */
500 $error = _T("Mime-Type not allowed");
502 case self
::NEW_FILE_EXISTS
:
503 $error = _T("A file with that name already exists!");
505 case self
::INVALID_FILE
:
506 $error = _T("File does not comply with requirements.");
508 case self
::CANT_WRITE
:
509 $error = _T("Unable to write file or temporary file");
517 * Return textual error message
519 * @param int $code The error code
521 * @return string Localized message
523 public function getErrorMessage($code)
525 return $this->getErrorMessageFromCode($code);
529 * Return textual error message send by PHP after upload attempt
531 * @param int $error_code The error code
533 * @return string Localized message
535 public function getPhpErrorMessage($error_code)
537 switch ($error_code) {
538 case UPLOAD_ERR_INI_SIZE
:
539 return _T("The uploaded file exceeds the upload_max_filesize directive in php.ini");
540 case UPLOAD_ERR_FORM_SIZE
:
541 return _T("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form");
542 case UPLOAD_ERR_PARTIAL
:
543 return _T("The uploaded file was only partially uploaded");
544 case UPLOAD_ERR_NO_FILE
:
545 return _T("No file was uploaded");
546 case UPLOAD_ERR_NO_TMP_DIR
:
547 return _T("Missing a temporary folder");
548 case UPLOAD_ERR_CANT_WRITE
:
549 return _T("Failed to write file to disk");
550 case UPLOAD_ERR_EXTENSION
:
551 return _T("File upload stopped by extension");
553 return _T("Unknown upload error");