Open Monograph Press  3.3.0
FileManager.inc.php
1 <?php
2 
23 define('FILE_MODE_MASK', 0666);
24 define('DIRECTORY_MODE_MASK', 0777);
25 
26 define('DOCUMENT_TYPE_DEFAULT', 'default');
27 define('DOCUMENT_TYPE_EXCEL', 'excel');
28 define('DOCUMENT_TYPE_HTML', 'html');
29 define('DOCUMENT_TYPE_IMAGE', 'image');
30 define('DOCUMENT_TYPE_PDF', 'pdf');
31 define('DOCUMENT_TYPE_WORD', 'word');
32 define('DOCUMENT_TYPE_EPUB', 'epub');
33 define('DOCUMENT_TYPE_ZIP', 'zip');
34 
35 class FileManager {
39  function __construct() {
40  }
41 
47  function uploadedFileExists($fileName) {
48  if (isset($_FILES[$fileName]) && isset($_FILES[$fileName]['tmp_name'])
49  && is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
50  return true;
51  }
52  return false;
53  }
54 
60  function uploadError($fileName) {
61  return (isset($_FILES[$fileName]) && $_FILES[$fileName]['error'] != UPLOAD_ERR_OK);
62  }
63 
70  function getUploadErrorCode($fileName) {
71  return $_FILES[$fileName]['error'];
72  }
73 
80  return key($_FILES);
81  }
82 
88  function getUploadedFilePath($fileName) {
89  if (isset($_FILES[$fileName]['tmp_name']) && is_uploaded_file($_FILES[$fileName]['tmp_name'])) {
90  return $_FILES[$fileName]['tmp_name'];
91  }
92  return false;
93  }
94 
100  function getUploadedFileName($fileName) {
101  if (isset($_FILES[$fileName]['name'])) {
102  return $_FILES[$fileName]['name'];
103  }
104  return false;
105  }
106 
112  function getUploadedFileType($fileName) {
113  if (isset($_FILES[$fileName])) {
114  // The result of "explode" can't be passed directly to "array_pop" in PHP 7.
115  $exploded = explode('.',$_FILES[$fileName]['name']);
116 
118  $_FILES[$fileName]['tmp_name'], // Location on server
119  array_pop($exploded) // Extension on client machine
120  );
121 
122  if (!empty($type)) return $type;
123  return $_FILES[$fileName]['type'];
124  }
125  return false;
126  }
127 
134  function uploadFile($fileName, $destFileName) {
135  $destDir = dirname($destFileName);
136  if (!$this->fileExists($destDir, 'dir')) {
137  // Try to create the destination directory
138  $this->mkdirtree($destDir);
139  }
140  if (!isset($_FILES[$fileName])) return false;
141  if (move_uploaded_file($_FILES[$fileName]['tmp_name'], $destFileName))
142  return $this->setMode($destFileName, FILE_MODE_MASK);
143  return false;
144  }
145 
152  function writeFile($dest, &$contents) {
153  $success = true;
154  $destDir = dirname($dest);
155  if (!$this->fileExists($destDir, 'dir')) {
156  // Try to create the destination directory
157  $this->mkdirtree($destDir);
158  }
159  if (($f = fopen($dest, 'wb'))===false) $success = false;
160  if ($success && fwrite($f, $contents)===false) $success = false;
161  @fclose($f);
162 
163  if ($success)
164  return $this->setMode($dest, FILE_MODE_MASK);
165  return false;
166  }
167 
174  function copyFile($source, $dest) {
175  $destDir = dirname($dest);
176  if (!$this->fileExists($destDir, 'dir')) {
177  // Try to create the destination directory
178  $this->mkdirtree($destDir);
179  }
180  if (copy($source, $dest))
181  return $this->setMode($dest, FILE_MODE_MASK);
182  return false;
183  }
184 
192  function copyDir($source, $dest) {
193  if (is_dir($source)) {
194  $this->mkdir($dest);
195  $destDir = dir($source);
196 
197  while (($entry = $destDir->read()) !== false) {
198  if ($entry == '.' || $entry == '..') {
199  continue;
200  }
201 
202  $Entry = $source . DIRECTORY_SEPARATOR . $entry;
203  if (is_dir($Entry) ) {
204  $this->copyDir($Entry, $dest . DIRECTORY_SEPARATOR . $entry );
205  continue;
206  }
207  $this->copyFile($Entry, $dest . DIRECTORY_SEPARATOR . $entry );
208  }
209 
210  $destDir->close();
211  } else {
212  $this->copyFile($source, $dest);
213  }
214 
215  if ($this->fileExists($dest, 'dir')) {
216  return true;
217  } else return false;
218  }
219 
220 
227  function readFileFromPath($filePath, $output = false) {
228  if (is_readable($filePath)) {
229  $f = fopen($filePath, 'rb');
230  if (!$f) return false;
231  $data = '';
232  while (!feof($f)) {
233  $data .= fread($f, 4096);
234  if ($output) {
235  echo $data;
236  $data = '';
237  }
238  }
239  fclose($f);
240 
241  if ($output) return true;
242  return $data;
243  }
244  return false;
245  }
246 
256  function downloadByPath($filePath, $mediaType = null, $inline = false, $fileName = null) {
257  $result = null;
258  if (HookRegistry::call('FileManager::downloadFile', array(&$filePath, &$mediaType, &$inline, &$result, &$fileName))) return $result;
259  if (is_readable($filePath)) {
260  if ($mediaType === null) {
261  // If the media type wasn't specified, try to detect.
262  $mediaType = PKPString::mime_content_type($filePath);
263  if (empty($mediaType)) $mediaType = 'application/octet-stream';
264  }
265  if ($fileName === null) {
266  // If the filename wasn't specified, use the server-side.
267  $fileName = basename($filePath);
268  }
269 
270  // Stream the file to the end user.
271  header("Content-Type: $mediaType");
272  header('Content-Length: ' . filesize($filePath));
273  header('Accept-Ranges: none');
274  header('Content-Disposition: ' . ($inline ? 'inline' : 'attachment') . "; filename=\"$fileName\"");
275  header('Cache-Control: private'); // Workarounds for IE weirdness
276  header('Pragma: public');
277  $this->readFileFromPath($filePath, true);
278  $returner = true;
279  } else {
280  $returner = false;
281  }
282  HookRegistry::call('FileManager::downloadFileFinished', array(&$returner));
283  return $returner;
284  }
285 
291  function deleteByPath($filePath) {
292  if ($this->fileExists($filePath)) {
293  $result = null;
294  if (HookRegistry::call('FileManager::deleteFile', array($filePath, &$result))) return $result;
295  return unlink($filePath);
296  }
297  return false;
298  }
299 
306  function mkdir($dirPath, $perms = null) {
307  if ($perms !== null) {
308  return mkdir($dirPath, $perms);
309  } else {
310  if (mkdir($dirPath))
311  return $this->setMode($dirPath, DIRECTORY_MODE_MASK);
312  return false;
313  }
314  }
315 
321  function rmdir($dirPath) {
322  return rmdir($dirPath);
323  }
324 
330  function rmtree($file) {
331  if (file_exists($file)) {
332  if (is_dir($file)) {
333  $handle = opendir($file);
334  while (($filename = readdir($handle)) !== false) {
335  if ($filename != '.' && $filename != '..') {
336  if (!$this->rmtree($file . '/' . $filename)) return false;
337  }
338  }
339  closedir($handle);
340  if (!rmdir($file)) return false;
341 
342  } else {
343  if (!unlink($file)) return false;
344  }
345  }
346  return true;
347  }
348 
355  function mkdirtree($dirPath, $perms = null) {
356  if (!file_exists($dirPath)) {
357  //Avoid infinite recursion when file_exists reports false for root directory
358  if ($dirPath == dirname($dirPath)) {
359  fatalError('There are no readable files in this directory tree. Are safe mode or open_basedir active?');
360  return false;
361  } else if ($this->mkdirtree(dirname($dirPath), $perms)) {
362  return $this->mkdir($dirPath, $perms);
363  } else {
364  return false;
365  }
366  }
367  return true;
368  }
369 
375  function fileExists($filePath, $type = 'file') {
376  switch ($type) {
377  case 'file':
378  return file_exists($filePath);
379  case 'dir':
380  return file_exists($filePath) && is_dir($filePath);
381  default:
382  return false;
383  }
384  }
385 
391  function getDocumentType($type) {
392  if ($this->getImageExtension($type))
393  return DOCUMENT_TYPE_IMAGE;
394 
395  switch ($type) {
396  case 'application/pdf':
397  case 'application/x-pdf':
398  case 'text/pdf':
399  case 'text/x-pdf':
400  return DOCUMENT_TYPE_PDF;
401  case 'application/msword':
402  case 'application/word':
403  return DOCUMENT_TYPE_WORD;
404  case 'application/excel':
405  return DOCUMENT_TYPE_EXCEL;
406  case 'text/html':
407  return DOCUMENT_TYPE_HTML;
408  case 'application/zip':
409  case 'application/x-zip':
410  case 'application/x-zip-compressed':
411  case 'application/x-compress':
412  case 'application/x-compressed':
413  case 'multipart/x-zip':
414  return DOCUMENT_TYPE_ZIP;
415  case 'application/epub':
416  case 'application/epub+zip':
417  return DOCUMENT_TYPE_EPUB;
418  default:
419  return DOCUMENT_TYPE_DEFAULT;
420  }
421  }
422 
428  function getDocumentExtension($type) {
429  switch ($type) {
430  case 'application/pdf':
431  return '.pdf';
432  case 'application/word':
433  return '.doc';
434  case 'text/css':
435  return '.css';
436  case 'text/html':
437  return '.html';
438  case 'application/epub+zip':
439  return '.epub';
440  default:
441  return false;
442  }
443  }
444 
450  function getImageExtension($type) {
451  switch ($type) {
452  case 'image/gif':
453  return '.gif';
454  case 'image/jpeg':
455  case 'image/pjpeg':
456  return '.jpg';
457  case 'image/png':
458  case 'image/x-png':
459  return '.png';
460  case 'image/vnd.microsoft.icon':
461  case 'image/x-icon':
462  case 'image/x-ico':
463  case 'image/ico':
464  return '.ico';
465  case 'image/svg+xml':
466  case 'image/svg':
467  return '.svg';
468  case 'application/x-shockwave-flash':
469  return '.swf';
470  case 'video/x-flv':
471  case 'application/x-flash-video':
472  case 'flv-application/octet-stream':
473  return '.flv';
474  case 'audio/mpeg':
475  return '.mp3';
476  case 'audio/x-aiff':
477  return '.aiff';
478  case 'audio/x-wav':
479  return '.wav';
480  case 'video/mpeg':
481  return '.mpg';
482  case 'video/quicktime':
483  return '.mov';
484  case 'video/mp4':
485  return '.mp4';
486  case 'text/javascript':
487  return '.js';
488  default:
489  return false;
490  }
491  }
492 
498  function getExtension($fileName) {
499  $extension = '';
500  $fileParts = explode('.', $fileName);
501  if (is_array($fileParts)) {
502  $extension = $fileParts[count($fileParts) - 1];
503  }
504  return $extension;
505  }
506 
510  function truncateFileName($fileName, $length = 127) {
511  if (PKPString::strlen($fileName) <= $length) return $fileName;
512  $ext = $this->getExtension($fileName);
513  $truncated = PKPString::substr($fileName, 0, $length - 1 - PKPString::strlen($ext)) . '.' . $ext;
514  return PKPString::substr($truncated, 0, $length);
515  }
516 
522  function getNiceFileSize($size) {
523  $niceFileSizeUnits = array('B', 'KB', 'MB', 'GB');
524  for($i = 0; $i < 4 && $size > 1024; $i++) {
525  $size >>= 10;
526  }
527  return $size . $niceFileSizeUnits[$i];
528  }
529 
536  function setMode($path, $mask) {
537  $umask = Config::getVar('files', 'umask');
538  if (!$umask)
539  return true;
540  return chmod($path, $mask & ~$umask);
541  }
542 
548  function parseFileExtension($fileName) {
549  $fileParts = explode('.', $fileName);
550  if (is_array($fileParts)) {
551  $fileExtension = $fileParts[count($fileParts) - 1];
552  }
553 
554  // FIXME Check for evil
555  if (!isset($fileExtension) || stristr($fileExtension, 'php') || strlen($fileExtension) > 6 || !preg_match('/^\w+$/', $fileExtension)) {
556  $fileExtension = 'txt';
557  }
558 
559  // consider .tar.gz extension
560  if (strtolower(substr($fileName, -7)) == '.tar.gz') {
561  $fileExtension = substr($fileName, -6);
562  }
563 
564  return $fileExtension;
565  }
566 
572  function decompressFile($filePath) {
573  return $this->_executeGzip($filePath, true);
574  }
575 
581  function compressFile($filePath) {
582  return $this->_executeGzip($filePath, false);
583  }
584 
585 
586  //
587  // Private helper methods.
588  //
596  private function _executeGzip($filePath, $decompress = false) {
597  PKPLocale::requireComponents(LOCALE_COMPONENT_PKP_ADMIN);
598  $gzipPath = Config::getVar('cli', 'gzip');
599  if (!is_executable($gzipPath)) {
600  throw new Exception(__('admin.error.executingUtil', array('utilPath' => $gzipPath, 'utilVar' => 'gzip')));
601  }
602  $gzipCmd = escapeshellarg($gzipPath);
603  if ($decompress) $gzipCmd .= ' -d';
604  // Make sure any output message will mention the file path.
605  $output = array($filePath);
606  $returnValue = 0;
607  $gzipCmd .= ' ' . escapeshellarg($filePath);
608  if (!Core::isWindows()) {
609  // Get the output, redirecting stderr to stdout.
610  $gzipCmd .= ' 2>&1';
611  }
612  exec($gzipCmd, $output, $returnValue);
613  if ($returnValue > 0) {
614  throw new Exception(__('admin.error.utilExecutionProblem', array('utilPath' => $gzipPath, 'output' => implode(PHP_EOL, $output))));
615  }
616  if ($decompress) {
617  return substr($filePath, 0, -3);
618  } else {
619  return $filePath . '.gz';
620  }
621  }
622 }
FileManager\getDocumentType
getDocumentType($type)
Definition: FileManager.inc.php:391
FileManager\downloadByPath
downloadByPath($filePath, $mediaType=null, $inline=false, $fileName=null)
Definition: FileManager.inc.php:256
FileManager\getNiceFileSize
getNiceFileSize($size)
Definition: FileManager.inc.php:522
FileManager\rmtree
rmtree($file)
Definition: FileManager.inc.php:330
FileManager\compressFile
compressFile($filePath)
Definition: FileManager.inc.php:581
Core\isWindows
static isWindows()
Definition: Core.inc.php:80
FileManager\deleteByPath
deleteByPath($filePath)
Definition: FileManager.inc.php:291
PKPString\substr
static substr($string, $start, $length=null)
Definition: PKPString.inc.php:160
FileManager\getDocumentExtension
getDocumentExtension($type)
Definition: FileManager.inc.php:428
FileManager\copyFile
copyFile($source, $dest)
Definition: FileManager.inc.php:174
FileManager\fileExists
fileExists($filePath, $type='file')
Definition: FileManager.inc.php:375
FileManager\getFirstUploadedPostName
getFirstUploadedPostName()
Definition: FileManager.inc.php:79
FileManager\readFileFromPath
readFileFromPath($filePath, $output=false)
Definition: FileManager.inc.php:227
FileManager\writeFile
writeFile($dest, &$contents)
Definition: FileManager.inc.php:152
FileManager\mkdir
mkdir($dirPath, $perms=null)
Definition: FileManager.inc.php:306
FileManager\uploadError
uploadError($fileName)
Definition: FileManager.inc.php:60
FileManager\rmdir
rmdir($dirPath)
Definition: FileManager.inc.php:321
FileManager\truncateFileName
truncateFileName($fileName, $length=127)
Definition: FileManager.inc.php:510
FileManager\getExtension
getExtension($fileName)
Definition: FileManager.inc.php:498
PKPString\strlen
static strlen($string)
Definition: PKPString.inc.php:128
FileManager\mkdirtree
mkdirtree($dirPath, $perms=null)
Definition: FileManager.inc.php:355
FileManager\getUploadedFileType
getUploadedFileType($fileName)
Definition: FileManager.inc.php:112
FileManager\decompressFile
decompressFile($filePath)
Definition: FileManager.inc.php:572
Config\getVar
static getVar($section, $key, $default=null)
Definition: Config.inc.php:35
PKPString\mime_content_type
static mime_content_type($filename, $suggestedExtension='')
Definition: PKPString.inc.php:312
FileManager\getImageExtension
getImageExtension($type)
Definition: FileManager.inc.php:450
FileManager\getUploadedFilePath
getUploadedFilePath($fileName)
Definition: FileManager.inc.php:88
FileManager\getUploadErrorCode
getUploadErrorCode($fileName)
Definition: FileManager.inc.php:70
FileManager\parseFileExtension
parseFileExtension($fileName)
Definition: FileManager.inc.php:548
FileManager\setMode
setMode($path, $mask)
Definition: FileManager.inc.php:536
FileManager\__construct
__construct()
Definition: FileManager.inc.php:39
FileManager\uploadFile
uploadFile($fileName, $destFileName)
Definition: FileManager.inc.php:134
fatalError
if(!function_exists('import')) fatalError($reason)
Definition: functions.inc.php:32
FileManager
Class defining basic operations for file management.
Definition: FileManager.inc.php:35
FileManager\getUploadedFileName
getUploadedFileName($fileName)
Definition: FileManager.inc.php:100
FileManager\uploadedFileExists
uploadedFileExists($fileName)
Definition: FileManager.inc.php:47
HookRegistry\call
static call($hookName, $args=null)
Definition: HookRegistry.inc.php:86
PKPLocale\requireComponents
static requireComponents()
Definition: PKPLocale.inc.php:374
FileManager\copyDir
copyDir($source, $dest)
Definition: FileManager.inc.php:192