]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/IO/FileTrait.php
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
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.8.1 - 2014-09-18
47 * @author Johan Cwiklinski <johan@x-tnd.be>
48 * @copyright 2013-2014 The Galette Team
49 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
50 * @link http://galette.tuxfamily.org
51 * @since Available since 0.8.1 - 2014-09-18
56 //array keys contain litteral value of each forbidden character
57 //(to be used when showing an error).
58 //Maybe is there a better way to handle this...
59 protected $bad_chars = array(
76 protected $allowed_extensions = array();
77 protected $allowed_mimes = array();
80 public static $mime_types = array(
81 'txt' => 'text/plain',
83 'html' => 'text/html',
84 'xhtml' => 'application/xhtml+xml',
85 'xht' => 'application/xhtml+xml',
88 'js' => 'application/javascript',
89 'json' => 'application/json',
90 'xml' => 'application/xml',
91 'xslt' => 'application/xslt+xml',
92 'xsl' => 'application/xml',
93 'dtd' => 'application/xml-dtd',
94 'atom' => 'application/atom+xml',
95 'mathml' => 'application/mathml+xml',
96 'rdf' => 'application/rdf+xml',
97 'smi' => 'application/smil',
98 'smil' => 'application/smil',
99 'vxml' => 'application/voicexml+xml',
100 'latex' => 'application/x-latex',
101 'tcl' => 'application/x-tcl',
102 'tex' => 'application/x-tex',
103 'texinfo' => 'application/x-texinfo',
104 'wrl' => 'model/vrml',
105 'wrml' => 'model/vrml',
106 'ics' => 'text/calendar',
107 'ifb' => 'text/calendar',
108 'sgml' => 'text/sgml',
109 'htc' => 'text/x-component',
110 'pgp' => 'application/pgp-signature',
111 'rtf' => 'application/rtf',
113 'png' => 'image/png',
114 'jpeg' => 'image/jpeg',
115 'jpg' => 'image/jpeg',
116 'gif' => 'image/gif',
117 'bmp' => 'image/bmp',
118 'ico' => 'image/x-icon',
119 'tiff' => 'image/tiff',
120 'tif' => 'image/tiff',
121 'svg' => 'image/svg+xml',
122 'svgz' => 'image/svg+xml',
123 'djvu' => 'image/vnd.djvu',
124 'djv' => 'image/vnd.djvu',
126 'zip' => 'application/zip',
127 'rar' => 'application/x-rar-compressed',
128 'tar' => 'application/x-tar',
129 'gz' => 'application/x-gzip',
130 'tgz' => 'application/x-gzip',
131 'bz2' => 'application/x-bzip2',
133 'mp2' => 'audio/mpeg',
134 'mp3' => 'audio/mpeg',
135 'qt' => 'video/quicktime',
136 'mov' => 'video/quicktime',
137 'mpeg' => 'video/mpeg',
138 'mpg' => 'video/mpeg',
139 'mpe' => 'video/mpeg',
140 'wav' => 'audio/wav',
141 'aiff' => 'audio/aiff',
142 'aif' => 'audio/aiff',
143 'avi' => 'video/msvideo',
144 'wmv' => 'video/x-ms-wmv',
145 'ogg' => 'application/ogg',
146 'flv' => 'video/x-flv',
147 'dvi' => 'application/x-dvi',
148 'au' => 'audio/basic',
149 'snd' => 'audio/basic',
150 'mid' => 'audio/midi',
151 'midi' => 'audio/midi',
152 'm3u' => 'audio/x-mpegurl',
153 'm4u' => 'video/vnd.mpegurl',
154 'ram' => 'audio/x-pn-realaudio',
155 'ra' => 'audio/x-pn-realaudio',
156 'rm' => 'application/vnd.rn-realmedia',
158 'pdf' => 'application/pdf',
159 'psd' => 'image/vnd.adobe.photoshop',
160 'ai' => 'application/postscript',
161 'eps' => 'application/postscript',
162 'ps' => 'application/postscript',
163 'swf' => 'application/x-shockwave-flash',
165 'doc' => 'application/msword',
166 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
167 'xls' => 'application/vnd.ms-excel',
168 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
169 'ppt' => 'application/vnd.ms-powerpoint',
170 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
171 'pps' => 'application/vnd.ms-powerpoint',
173 'odt' => 'application/vnd.oasis.opendocument.text',
174 'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
175 'odc' => 'application/vnd.oasis.opendocument.chart',
176 'odb' => 'application/vnd.oasis.opendocument.database',
177 'odg' => 'application/vnd.oasis.opendocument.graphics',
178 'odp' => 'application/vnd.oasis.opendocument.presentation',
184 * @param string $dest File destination directory
185 * @param array $extensions Array of permitted extensions
186 * @param array $mimes Array of permitted mime types
187 * @param int $maxlenght Maximum lenght for each file
191 protected function init(
197 if ($dest !== null && substr($dest, -1) !== '/') {
201 $this->dest_dir
= $dest;
202 if ($extensions !== null) {
203 $this->allowed_extensions
= $extensions;
205 if ($mimes !== null) {
206 $this->allowed_mimes
= $mimes;
208 if ($maxlenght !== null) {
209 $this->maxlenght
= $maxlenght;
211 $this->maxlenght
= self
::MAX_FILE_SIZE
;
216 * Copy existing file to new Location
218 * @param string $dest Destination directory
222 public function copyTo($dest)
225 $this->dest_dir
. $this->name
,
229 $this->dest_dir
= $dest;
235 * Stores an file on the disk
237 * @param object $file the uploaded file
238 * @param boolean $ajax If the file cames from an ajax call (dnd)
240 * @return true|false|int result of the storage process
242 public function store($file, $ajax = false)
244 $class = get_class($this);
246 $this->name
= $file['name'];
247 $tmpfile = $file['tmp_name'];
249 //First, does the file have a valid name?
250 $reg = "/^([^" . implode('', $this->bad_chars
) . "]+)\.";
251 if (count($this->allowed_extensions
) > 0) {
252 $reg .= "(" . implode('|', $this->allowed_extensions
) . ")";
257 if (preg_match($reg, $this->name
, $matches)) {
259 '[' . $class . '] Filename and extension are OK, proceed.',
263 $erreg = "/^([^" . implode('', $this->bad_chars
) . "]+)\.(.*)/i";
264 $m = preg_match($erreg, $this->name
, $errmatches);
266 $err_msg = '[' . $class . '] ';
268 //ok, we got a good filename and an extension. Extension is bad :)
269 $err_msg .= 'Invalid extension for file ' . $this->name
. '.';
270 $ret = self
::INVALID_EXTENSION
;
272 $err_msg = 'Invalid filename `' . $this->name
. '` (Tip: ';
273 $err_msg .= preg_replace(
275 htmlentities($this->getBadChars()),
276 "file name should not contain any of: %s). "
278 $ret = self
::INVALID_FILENAME
;
288 //Second, let's check file size
289 if ($file['size'] > ($this->maxlenght
* 1024)) {
291 '[' . $class . '] File is too big (' . ($file['size'] * 1024) .
292 'Ko for maximum authorized ' . ($this->maxlenght
* 1024) .
296 return self
::FILE_TOO_BIG
;
298 Analog
::log('[' . $class . '] Filesize is OK, proceed', Analog
::DEBUG
);
301 $mime = $this->getMimeType($tmpfile);
304 count($this->allowed_mimes
) > 0
305 && !in_array($mime, $this->allowed_mimes
)
308 '[' . $class . '] Mimetype `' . $mime . '` not allowed',
311 return self
::MIME_NOT_ALLOWED
;
314 '[' . $class . '] Mimetype is allowed, proceed',
319 $new_file = $this->dest_dir
. $this->name
;
321 if (file_exists($new_file)) {
323 '[' . $class . '] File `' . $new_file . '` already exists',
326 return self
::NEW_FILE_EXISTS
;
329 if ($ajax === true) {
330 $in_place = rename($tmpfile, $new_file);
332 $in_place = move_uploaded_file($tmpfile, $new_file);
335 if ($in_place === false) {
336 return self
::CANT_WRITE
;
342 * Get destination dir
346 public function getDestDir()
348 return $this->dest_dir
;
352 * Set destination directory
354 * @param string $dir Directory
358 public function setDestDir($dir)
360 $this->dest_dir
= $dir;
368 public function getFileName()
376 * @param string $name file name
380 public function setFileName($name)
386 * Returns unauthorized characters litteral values quoted, comma separated values
388 * @return string comma separated disallowed characters
390 public function getBadChars()
392 return '`' . implode('`, `', array_keys($this->bad_chars
)) . '`';
396 * Returns allowed extensions
398 * @return string comma separated allowed extensiosn
400 public function getAllowedExts()
402 return implode(', ', $this->allowed_extensions
);
406 * Return the array of allowed mime types
410 public function getAllowedMimeTypes()
412 return $this->allowed_mimes
;
418 * @param string $file File
422 public static function getMimeType($file)
425 $class = get_called_class();
427 if (function_exists('finfo_open')) {
429 '[' . $class . '] Function File Info exist ',
432 $finfo = finfo_open(FILEINFO_MIME_TYPE
);
433 $mime = finfo_file($finfo, $file);
435 } elseif (function_exists('mime_content_type')) {
437 '[' . $class . '] Function mime_content_type exist ',
440 $mime = mime_content_type($file);
443 '[' . $class . '] Search from extension ',
446 $exploded = explode('.', $file);
447 $ext = strtolower(array_pop($exploded));
449 '[' . $class . '] Extension : ' . $ext,
452 if (array_key_exists($ext, self
::$mime_types)) {
453 $mime = self
::$mime_types[$ext];
455 $mime = 'application/octet-stream';
460 '[' . $class . '] Found mimetype : ' . $mime . ' for file ' . $file,
467 * Return textual error message
469 * @param int $code The error code
471 * @return string Localized message
473 protected function getErrorMessageFromCode($code)
475 $error = _T("An error occurred.");
478 case self
::INVALID_FILENAME
:
479 $error = _T("File name is invalid, it should not contain any special character or space.");
481 case self
::INVALID_EXTENSION
:
482 $error = preg_replace(
484 $this->getAllowedExts(),
485 _T("File extension is not allowed, only %s files are.")
488 case self
::FILE_TOO_BIG
:
489 $error = preg_replace(
492 _T("File is too big. Maximum allowed size is %dKo")
495 case self
::MIME_NOT_ALLOWED
:
496 /** FIXME: should be more descriptive */
497 $error = _T("Mime-Type not allowed");
499 case self
::NEW_FILE_EXISTS
:
500 $error = _T("A file with that name already exists!");
502 case self
::INVALID_FILE
:
503 $error = _T("File does not comply with requirements.");
505 case self
::CANT_WRITE
:
506 $error = _T("Unable to write file or temporary file");
514 * Return textual error message
516 * @param int $code The error code
518 * @return string Localized message
520 public function getErrorMessage($code)
522 return $this->getErrorMessageFromCode($code);
526 * Return textual error message send by PHP after upload attempt
528 * @param int $error_code The error code
530 * @return string Localized message
532 public function getPhpErrorMessage($error_code)
534 switch ($error_code) {
535 case UPLOAD_ERR_INI_SIZE
:
536 return _T("The uploaded file exceeds the upload_max_filesize directive in php.ini");
537 case UPLOAD_ERR_FORM_SIZE
:
538 return _T("The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form");
539 case UPLOAD_ERR_PARTIAL
:
540 return _T("The uploaded file was only partially uploaded");
541 case UPLOAD_ERR_NO_FILE
:
542 return _T("No file was uploaded");
543 case UPLOAD_ERR_NO_TMP_DIR
:
544 return _T("Missing a temporary folder");
545 case UPLOAD_ERR_CANT_WRITE
:
546 return _T("Failed to write file to disk");
547 case UPLOAD_ERR_EXTENSION
:
548 return _T("File upload stopped by extension");
550 return _T("Unknown upload error");