fileExists($destDir, 'dir')) { // Try to create the destination directory $this->mkdirtree($destDir); } if (!isset($_FILES[$fileName])) return false; if (move_uploaded_file($_FILES[$fileName]['tmp_name'], $destFileName)) return $this->setMode($destFileName, FILE_MODE_MASK); return false; } /** * Write a file. * @param $dest string the path where the file is to be saved * @param $contents string the contents to write to the file * @return boolean returns true if successful */ function writeFile($dest, &$contents) { $success = true; $destDir = dirname($dest); if (!$this->fileExists($destDir, 'dir')) { // Try to create the destination directory $this->mkdirtree($destDir); } if (($f = fopen($dest, 'wb'))===false) $success = false; if ($success && fwrite($f, $contents)===false) $success = false; @fclose($f); if ($success) return $this->setMode($dest, FILE_MODE_MASK); return false; } /** * Copy a file. * @param $source string the source URL for the file * @param $dest string the path where the file is to be saved * @return boolean returns true if successful */ function copyFile($source, $dest) { $success = true; $destDir = dirname($dest); if (!$this->fileExists($destDir, 'dir')) { // Try to create the destination directory $this->mkdirtree($destDir); } if (copy($source, $dest)) return $this->setMode($dest, FILE_MODE_MASK); return false; } /** * Copy a directory. * Adapted from code by gimmicklessgpt at gmail dot com, at http://php.net/manual/en/function.copy.php * @param $source string the path to the source directory * @param $dest string the path where the directory is to be saved * @return boolean returns true if successful */ function copyDir($source, $dest) { if (is_dir($source)) { $this->mkdir($dest); $destDir = dir($source); while (($entry = $destDir->read()) !== false) { if ($entry == '.' || $entry == '..') { continue; } $Entry = $source . DIRECTORY_SEPARATOR . $entry; if (is_dir($Entry) ) { $this->copyDir($Entry, $dest . DIRECTORY_SEPARATOR . $entry ); continue; } $this->copyFile($Entry, $dest . DIRECTORY_SEPARATOR . $entry ); } $destDir->close(); } else { $this->copyFile($source, $dest); } if ($this->fileExists($dest, 'dir')) { return true; } else return false; } /** * Read a file's contents. * @param $filePath string the location of the file to be read * @param $output boolean output the file's contents instead of returning a string * @return boolean */ function &readFile($filePath, $output = false) { if (is_readable($filePath)) { $f = fopen($filePath, 'rb'); $data = ''; while (!feof($f)) { $data .= fread($f, 4096); if ($output) { echo $data; $data = ''; } } fclose($f); if ($output) { $returner = true; return $returner; } else { return $data; } } else { $returner = false; return $returner; } } /** * Download a file. * Outputs HTTP headers and file content for download * @param $filePath string the location of the file to be sent * @param $mediaType string the MIME type of the file, optional * @param $inline print file as inline instead of attachment, optional * @return boolean */ function downloadFile($filePath, $mediaType = null, $inline = false, $fileName = null) { $result = null; if (HookRegistry::call('FileManager::downloadFile', array(&$filePath, &$mediaType, &$inline, &$result, &$fileName))) return $result; $postDownloadHookList = array('FileManager::downloadFileFinished', 'UsageEventPlugin::getUsageEvent'); if (is_readable($filePath)) { if ($mediaType === null) { // If the media type wasn't specified, try to detect. $mediaType = String::mime_content_type($filePath); if (empty($mediaType)) $mediaType = 'application/octet-stream'; } if ($fileName === null) { // If the filename wasn't specified, use the server-side. $fileName = basename($filePath); } $postDownloadHooks = null; $hooks = HookRegistry::getHooks(); foreach ($postDownloadHookList as $hookName) { if (isset($hooks[$hookName])) { $postDownloadHooks[$hookName] = $hooks[$hookName]; } } unset($hooks); Registry::clear(); // Stream the file to the end user. header("Content-Type: $mediaType"); header('Content-Length: ' . filesize($filePath)); header('Content-Disposition: ' . ($inline ? 'inline' : 'attachment') . "; filename=\"$fileName\""); header('Cache-Control: private'); // Workarounds for IE weirdness header('Pragma: public'); // Beware of converting to instance call // https://github.com/pkp/pkp-lib/commit/82f4a36db406ecac3eb88875541a74123e455713#commitcomment-1459396 FileManager::readFile($filePath, true); if ($postDownloadHooks) { foreach ($postDownloadHooks as $hookName => $hooks) { HookRegistry::setHooks($hookName, $hooks); } } $returner = true; } else { $returner = false; } HookRegistry::call('FileManager::downloadFileFinished', array(&$returner)); return $returner; } /** * Delete a file. * @param $filePath string the location of the file to be deleted * @return boolean returns true if successful */ function deleteFile($filePath) { if ($this->fileExists($filePath)) { return unlink($filePath); } else { return false; } } /** * Create a new directory. * @param $dirPath string the full path of the directory to be created * @param $perms string the permissions level of the directory (optional) * @return boolean returns true if successful */ function mkdir($dirPath, $perms = null) { if ($perms !== null) { return mkdir($dirPath, $perms); } else { if (mkdir($dirPath)) return $this->setMode($dirPath, DIRECTORY_MODE_MASK); return false; } } /** * Remove a directory. * @param $dirPath string the full path of the directory to be delete * @return boolean returns true if successful */ function rmdir($dirPath) { return rmdir($dirPath); } /** * Delete all contents including directory (equivalent to "rm -r") * @param $file string the full path of the directory to be removed */ function rmtree($file) { if (file_exists($file)) { if (is_dir($file)) { $handle = opendir($file); while (($filename = readdir($handle)) !== false) { if ($filename != '.' && $filename != '..') { $this->rmtree($file . '/' . $filename); } } closedir($handle); rmdir($file); } else { unlink($file); } } } /** * Create a new directory, including all intermediate directories if required (equivalent to "mkdir -p") * @param $dirPath string the full path of the directory to be created * @param $perms string the permissions level of the directory (optional) * @return boolean returns true if successful */ function mkdirtree($dirPath, $perms = null) { if (!file_exists($dirPath)) { if ($this->mkdirtree(dirname($dirPath), $perms)) { return $this->mkdir($dirPath, $perms); } else { return false; } } return true; } /** * Check if a file path is valid; * @param $filePath string the file/directory to check * @param $type string (file|dir) the type of path */ function fileExists($filePath, $type = 'file') { switch ($type) { case 'file': return file_exists($filePath); case 'dir': return file_exists($filePath) && is_dir($filePath); default: return false; } } /** * Returns a file type, based on generic categories defined above * @param $type String * @return string (Enuemrated DOCUMENT_TYPEs) */ function getDocumentType($type) { if ($this->getImageExtension($type)) return DOCUMENT_TYPE_IMAGE; switch ($type) { case 'application/pdf': case 'application/x-pdf': case 'text/pdf': case 'text/x-pdf': return DOCUMENT_TYPE_PDF; case 'application/msword': case 'application/word': return DOCUMENT_TYPE_WORD; case 'application/excel': return DOCUMENT_TYPE_EXCEL; case 'text/html': return DOCUMENT_TYPE_HTML; case 'application/zip': case 'application/x-zip': case 'application/x-zip-compressed': case 'application/x-compress': case 'application/x-compressed': case 'multipart/x-zip': return DOCUMENT_TYPE_ZIP; default: return DOCUMENT_TYPE_DEFAULT; } } /** * Returns file extension associated with the given document type, * or false if the type does not belong to a recognized document type. * @param $type string */ function getDocumentExtension($type) { switch ($type) { case 'application/pdf': return '.pdf'; case 'application/word': return '.doc'; case 'text/html': return '.html'; default: return false; } } /** * Returns file extension associated with the given image type, * or false if the type does not belong to a recognized image type. * @param $type string */ function getImageExtension($type) { switch ($type) { case 'image/gif': return '.gif'; case 'image/jpeg': case 'image/pjpeg': return '.jpg'; case 'image/png': case 'image/x-png': return '.png'; case 'image/vnd.microsoft.icon': case 'image/x-icon': case 'image/x-ico': case 'image/ico': return '.ico'; case 'application/x-shockwave-flash': return '.swf'; case 'video/x-flv': case 'application/x-flash-video': case 'flv-application/octet-stream': return '.flv'; case 'audio/mpeg': return '.mp3'; case 'audio/x-aiff': return '.aiff'; case 'audio/x-wav': return '.wav'; case 'video/mpeg': return '.mpg'; case 'video/quicktime': return '.mov'; case 'video/mp4': return '.mp4'; case 'text/javascript': return '.js'; default: return false; } } /** * Parse file extension from file name. * @param string a valid file name * @return string extension */ function getExtension($fileName) { $extension = ''; $fileParts = explode('.', $fileName); if (is_array($fileParts)) { $extension = $fileParts[count($fileParts) - 1]; } return $extension; } /** * Truncate a filename to fit in the specified length. */ function truncateFileName($fileName, $length = 127) { if (String::strlen($fileName) <= $length) return $fileName; $ext = $this->getExtension($fileName); $truncated = String::substr($fileName, 0, $length - 1 - String::strlen($ext)) . '.' . $ext; return String::substr($truncated, 0, $length); } /** * Return pretty file size string (in B, KB, MB, or GB units). * @param $size int file size in bytes * @return string */ function getNiceFileSize($size) { $niceFileSizeUnits = array('B', 'KB', 'MB', 'GB'); for($i = 0; $i < 4 && $size > 1024; $i++) { $size >>= 10; } return $size . $niceFileSizeUnits[$i]; } /** * Set file/directory mode based on the 'umask' config setting. * @param $path string * @param $mask int * @return boolean */ function setMode($path, $mask) { $umask = Config::getVar('files', 'umask'); if (!$umask) return true; return chmod($path, $mask & ~$umask); } /** * Parse the file extension from a filename/path. * @param $fileName string * @return string */ function parseFileExtension($fileName) { $fileParts = explode('.', $fileName); if (is_array($fileParts)) { $fileExtension = $fileParts[count($fileParts) - 1]; } // FIXME Check for evil if (!isset($fileExtension) || stristr($fileExtension, 'php') || strlen($fileExtension) > 6 || !preg_match('/^\w+$/', $fileExtension)) { $fileExtension = 'txt'; } return $fileExtension; } } ?>