baseline
[omp.pkp.sfu.ca.git] / lib / pkp / classes / file / FileManager.inc.php
blob5a4da2ec705d679d4cb0baaf8ac466c4e923af3d
1 <?php
3 /**
4 * @defgroup file
5 */
7 /**
8 * @file classes/file/FileManager.inc.php
10 * Copyright (c) 2000-2009 John Willinsky
11 * Distributed under the GNU GPL v2. For full terms see the file docs/COPYING.
13 * @class FileManager
14 * @ingroup file
16 * @brief Class defining basic operations for file management.
19 // $Id: FileManager.inc.php,v 1.10 2009/09/29 23:39:13 asmecher Exp $
22 define('FILE_MODE_MASK', 0666);
23 define('DIRECTORY_MODE_MASK', 0777);
25 class FileManager {
26 /**
27 * Constructor
29 function FileManager() {
32 /**
33 * Return true if an uploaded file exists.
34 * @param $fileName string the name of the file used in the POST form
35 * @return boolean
37 function uploadedFileExists($fileName) {
38 if (isset($_FILES[$fileName]['tmp_name']) && is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
39 return true;
41 return false;
44 /**
45 * Return true iff an error occurred when trying to upload a file.
46 * @param $fileName string the name of the file used in the POST form
47 * @return boolean
49 function uploadError($fileName) {
50 return (isset($_FILES[$fileName]) && $_FILES[$fileName]['error'] != 0);
53 /**
54 * Return the (temporary) path to an uploaded file.
55 * @param $fileName string the name of the file used in the POST form
56 * @return string (boolean false if no such file)
58 function getUploadedFilePath($fileName) {
59 if (isset($_FILES[$fileName]['tmp_name']) && is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
60 return $_FILES[$fileName]['tmp_name'];
62 return false;
65 /**
66 * Return the user-specific (not temporary) filename of an uploaded file.
67 * @param $fileName string the name of the file used in the POST form
68 * @return string (boolean false if no such file)
70 function getUploadedFileName($fileName) {
71 if (isset($_FILES[$fileName]['name'])) {
72 return $_FILES[$fileName]['name'];
74 return false;
77 /**
78 * Return the type of an uploaded file.
79 * @param $fileName string the name of the file used in the POST form
80 * @return string
82 function getUploadedFileType($fileName) {
83 if (isset($_FILES[$fileName])) {
84 $type = String::mime_content_type($_FILES[$fileName]['tmp_name']);
85 if (!empty($type)) return $type;
86 return $_FILES[$fileName]['type'];
88 return false;
91 /**
92 * Upload a file.
93 * @param $fileName string the name of the file used in the POST form
94 * @param $dest string the path where the file is to be saved
95 * @return boolean returns true if successful
97 function uploadFile($fileName, $destFileName) {
98 $destDir = dirname($destFileName);
99 if (!FileManager::fileExists($destDir, 'dir')) {
100 // Try to create the destination directory
101 FileManager::mkdirtree($destDir);
103 if (!isset($_FILES[$fileName])) return false;
104 if (move_uploaded_file($_FILES[$fileName]['tmp_name'], $destFileName))
105 return FileManager::setMode($destFileName, FILE_MODE_MASK);
106 return false;
110 * Write a file.
111 * @param $dest string the path where the file is to be saved
112 * @param $contents string the contents to write to the file
113 * @return boolean returns true if successful
115 function writeFile($dest, &$contents) {
116 $success = true;
117 $destDir = dirname($dest);
118 if (!FileManager::fileExists($destDir, 'dir')) {
119 // Try to create the destination directory
120 FileManager::mkdirtree($destDir);
122 if (($f = fopen($dest, 'wb'))===false) $success = false;
123 if ($success && fwrite($f, $contents)===false) $success = false;
124 @fclose($f);
126 if ($success)
127 return FileManager::setMode($dest, FILE_MODE_MASK);
128 return false;
132 * Copy a file.
133 * @param $source string the source URL for the file
134 * @param $dest string the path where the file is to be saved
135 * @return boolean returns true if successful
137 function copyFile($source, $dest) {
138 $success = true;
139 $destDir = dirname($dest);
140 if (!FileManager::fileExists($destDir, 'dir')) {
141 // Try to create the destination directory
142 FileManager::mkdirtree($destDir);
144 if (copy($source, $dest))
145 return FileManager::setMode($dest, FILE_MODE_MASK);
146 return false;
150 * Read a file's contents.
151 * @param $filePath string the location of the file to be read
152 * @param $output boolean output the file's contents instead of returning a string
153 * @return boolean
155 function &readFile($filePath, $output = false) {
156 if (is_readable($filePath)) {
157 $f = fopen($filePath, 'rb');
158 $data = '';
159 while (!feof($f)) {
160 $data .= fread($f, 4096);
161 if ($output) {
162 echo $data;
163 $data = '';
166 fclose($f);
168 if ($output) {
169 $returner = true;
170 return $returner;
171 } else {
172 return $data;
175 } else {
176 $returner = false;
177 return $returner;
182 * Download a file.
183 * Outputs HTTP headers and file content for download
184 * @param $filePath string the location of the file to be sent
185 * @param $type string the MIME type of the file, optional
186 * @param $inline print file as inline instead of attachment, optional
187 * @return boolean
189 function downloadFile($filePath, $type = null, $inline = false) {
190 $result = null;
191 if (HookRegistry::call('FileManager::downloadFile', array(&$filePath, &$type, &$inline, &$result))) return $result;
192 if (is_readable($filePath)) {
193 if ($type == null) {
194 $type = String::mime_content_type($filePath);
195 if (empty($type)) $type = 'application/octet-stream';
198 Registry::clear(); // Free some memory
200 header("Content-Type: $type");
201 header("Content-Length: ".filesize($filePath));
202 header("Content-Disposition: " . ($inline ? 'inline' : 'attachment') . "; filename=\"" .basename($filePath)."\"");
203 header("Cache-Control: private"); // Workarounds for IE weirdness
204 header("Pragma: public");
206 import('file.FileManager');
207 FileManager::readFile($filePath, true);
209 return true;
211 } else {
212 return false;
217 * View a file inline (variant of downloadFile).
218 * @see FileManager::downloadFile
220 function viewFile($filePath, $type = null) {
221 FileManager::downloadFile($filePath, $type, true);
225 * Delete a file.
226 * @param $filePath string the location of the file to be deleted
227 * @return boolean returns true if successful
229 function deleteFile($filePath) {
230 if (FileManager::fileExists($filePath)) {
231 return unlink($filePath);
232 } else {
233 return false;
238 * Create a new directory.
239 * @param $dirPath string the full path of the directory to be created
240 * @param $perms string the permissions level of the directory (optional)
241 * @return boolean returns true if successful
243 function mkdir($dirPath, $perms = null) {
244 if ($perms !== null) {
245 return mkdir($dirPath, $perms);
246 } else {
247 if (mkdir($dirPath))
248 return FileManager::setMode($dirPath, DIRECTORY_MODE_MASK);
249 return false;
254 * Remove a directory.
255 * @param $dirPath string the full path of the directory to be delete
256 * @return boolean returns true if successful
258 function rmdir($dirPath) {
259 return rmdir($dirPath);
263 * Delete all contents including directory (equivalent to "rm -r")
264 * @param $file string the full path of the directory to be removed
266 function rmtree($file) {
267 if (file_exists($file)) {
268 if (is_dir($file)) {
269 $handle = opendir($file);
270 import('file.FileManager');
271 while (($filename = readdir($handle)) !== false) {
272 if ($filename != '.' && $filename != '..') {
273 FileManager::rmtree($file . '/' . $filename);
276 closedir($handle);
277 rmdir($file);
279 } else {
280 unlink($file);
286 * Create a new directory, including all intermediate directories if required (equivalent to "mkdir -p")
287 * @param $dirPath string the full path of the directory to be created
288 * @param $perms string the permissions level of the directory (optional)
289 * @return boolean returns true if successful
291 function mkdirtree($dirPath, $perms = null) {
292 if (!file_exists($dirPath)) {
293 if (FileManager::mkdirtree(dirname($dirPath), $perms)) {
294 return FileManager::mkdir($dirPath, $perms);
295 } else {
296 return false;
299 return true;
303 * Check if a file path is valid;
304 * @param $filePath string the file/directory to check
305 * @param $type string (file|dir) the type of path
307 function fileExists($filePath, $type = 'file') {
308 switch ($type) {
309 case 'file':
310 return file_exists($filePath);
311 case 'dir':
312 return file_exists($filePath) && is_dir($filePath);
313 default:
314 return false;
319 * Returns file extension associated with the given document type,
320 * or false if the type does not belong to a recognized document type.
321 * @param $type string
323 function getDocumentExtension($type) {
324 switch ($type) {
325 case 'application/pdf':
326 return '.pdf';
327 case 'application/word':
328 return '.doc';
329 case 'text/html':
330 return '.html';
331 default:
332 return false;
337 * Returns file extension associated with the given image type,
338 * or false if the type does not belong to a recognized image type.
339 * @param $type string
341 function getImageExtension($type) {
342 switch ($type) {
343 case 'image/gif':
344 return '.gif';
345 case 'image/jpeg':
346 case 'image/pjpeg':
347 return'.jpg';
348 case 'image/png':
349 case 'image/x-png':
350 return '.png';
351 case 'image/vnd.microsoft.icon':
352 case 'image/x-icon':
353 case 'image/ico':
354 return '.ico';
355 case 'application/x-shockwave-flash':
356 return '.swf';
357 case 'video/x-flv':
358 case 'application/x-flash-video':
359 case 'flv-application/octet-stream':
360 case 'application/octet-stream':
361 return '.flv';
362 case 'audio/mpeg':
363 return '.mp3';
364 case 'audio/x-aiff':
365 return '.aiff';
366 case 'audio/x-wav':
367 return '.wav';
368 case 'video/mpeg':
369 return '.mpg';
370 case 'video/quicktime':
371 return '.mov';
372 case 'video/mp4':
373 return '.mp4';
374 case 'text/javascript':
375 return '.js';
376 default:
377 return false;
382 * Parse file extension from file name.
383 * @param string a valid file name
384 * @return string extension
386 function getExtension($fileName) {
387 $extension = '';
388 $fileParts = explode('.', $fileName);
389 if (is_array($fileParts)) {
390 $extension = $fileParts[count($fileParts) - 1];
392 return $extension;
396 * Truncate a filename to fit in the specified length.
398 function truncateFileName($fileName, $length = 127) {
399 if (String::strlen($fileName) <= $length) return $fileName;
400 $ext = FileManager::getExtension($fileName);
401 $truncated = String::substr($fileName, 0, $length - 1 - String::strlen($ext)) . '.' . $ext;
402 return String::substr($truncated, 0, $length);
406 * Return pretty file size string (in B, KB, MB, or GB units).
407 * @param $size int file size in bytes
408 * @return string
410 function getNiceFileSize($size) {
411 $niceFileSizeUnits = array('B', 'KB', 'MB', 'GB');
412 for($i = 0; $i < 4 && $size > 1024; $i++) {
413 $size >>= 10;
415 return $size . $niceFileSizeUnits[$i];
419 * Set file/directory mode based on the 'umask' config setting.
420 * @param $path string
421 * @param $mask int
422 * @return boolean
424 function setMode($path, $mask) {
425 $umask = Config::getVar('files', 'umask');
426 if (!$umask)
427 return true;
428 return chmod($path, $mask & ~$umask);
432 * Parse the file extension from a filename/path.
433 * @param $fileName string
434 * @return string
436 function parseFileExtension($fileName) {
437 $fileParts = explode('.', $fileName);
438 if (is_array($fileParts)) {
439 $fileExtension = $fileParts[count($fileParts) - 1];
442 // FIXME Check for evil
443 if (!isset($fileExtension) || strstr($fileExtension, 'php') || strlen($fileExtension) > 6 || !preg_match('/^\w+$/', $fileExtension)) {
444 $fileExtension = 'txt';
447 return $fileExtension;