Chris@0: streamWrapperManager = $stream_wrapper_manager; Chris@0: $this->settings = $settings; Chris@0: $this->logger = $logger; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function moveUploadedFile($filename, $uri) { Chris@0: $result = @move_uploaded_file($filename, $uri); Chris@0: // PHP's move_uploaded_file() does not properly support streams if Chris@0: // open_basedir is enabled so if the move failed, try finding a real path Chris@0: // and retry the move operation. Chris@0: if (!$result) { Chris@0: if ($realpath = $this->realpath($uri)) { Chris@0: $result = move_uploaded_file($filename, $realpath); Chris@0: } Chris@0: else { Chris@0: $result = move_uploaded_file($filename, $uri); Chris@0: } Chris@0: } Chris@0: Chris@0: return $result; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function chmod($uri, $mode = NULL) { Chris@0: if (!isset($mode)) { Chris@0: if (is_dir($uri)) { Chris@0: $mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY); Chris@0: } Chris@0: else { Chris@0: $mode = $this->settings->get('file_chmod_file', static::CHMOD_FILE); Chris@0: } Chris@0: } Chris@0: Chris@0: if (@chmod($uri, $mode)) { Chris@0: return TRUE; Chris@0: } Chris@0: Chris@0: $this->logger->error('The file permissions could not be set on %uri.', ['%uri' => $uri]); Chris@0: return FALSE; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function unlink($uri, $context = NULL) { Chris@0: $scheme = $this->uriScheme($uri); Chris@0: if (!$this->validScheme($scheme) && (substr(PHP_OS, 0, 3) == 'WIN')) { Chris@0: chmod($uri, 0600); Chris@0: } Chris@0: if ($context) { Chris@0: return unlink($uri, $context); Chris@0: } Chris@0: else { Chris@0: return unlink($uri); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function realpath($uri) { Chris@0: // If this URI is a stream, pass it off to the appropriate stream wrapper. Chris@0: // Otherwise, attempt PHP's realpath. This allows use of this method even Chris@0: // for unmanaged files outside of the stream wrapper interface. Chris@0: if ($wrapper = $this->streamWrapperManager->getViaUri($uri)) { Chris@0: return $wrapper->realpath(); Chris@0: } Chris@0: Chris@0: return realpath($uri); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function dirname($uri) { Chris@0: $scheme = $this->uriScheme($uri); Chris@0: Chris@0: if ($this->validScheme($scheme)) { Chris@0: return $this->streamWrapperManager->getViaScheme($scheme)->dirname($uri); Chris@0: } Chris@0: else { Chris@0: return dirname($uri); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function basename($uri, $suffix = NULL) { Chris@0: $separators = '/'; Chris@0: if (DIRECTORY_SEPARATOR != '/') { Chris@0: // For Windows OS add special separator. Chris@0: $separators .= DIRECTORY_SEPARATOR; Chris@0: } Chris@0: // Remove right-most slashes when $uri points to directory. Chris@0: $uri = rtrim($uri, $separators); Chris@0: // Returns the trailing part of the $uri starting after one of the directory Chris@0: // separators. Chris@0: $filename = preg_match('@[^' . preg_quote($separators, '@') . ']+$@', $uri, $matches) ? $matches[0] : ''; Chris@0: // Cuts off a suffix from the filename. Chris@0: if ($suffix) { Chris@0: $filename = preg_replace('@' . preg_quote($suffix, '@') . '$@', '', $filename); Chris@0: } Chris@0: return $filename; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) { Chris@0: if (!isset($mode)) { Chris@0: $mode = $this->settings->get('file_chmod_directory', static::CHMOD_DIRECTORY); Chris@0: } Chris@0: Chris@0: // If the URI has a scheme, don't override the umask - schemes can handle Chris@0: // this issue in their own implementation. Chris@0: if ($this->uriScheme($uri)) { Chris@0: return $this->mkdirCall($uri, $mode, $recursive, $context); Chris@0: } Chris@0: Chris@0: // If recursive, create each missing component of the parent directory Chris@0: // individually and set the mode explicitly to override the umask. Chris@0: if ($recursive) { Chris@0: // Ensure the path is using DIRECTORY_SEPARATOR, and trim off any trailing Chris@0: // slashes because they can throw off the loop when creating the parent Chris@0: // directories. Chris@0: $uri = rtrim(str_replace('/', DIRECTORY_SEPARATOR, $uri), DIRECTORY_SEPARATOR); Chris@0: // Determine the components of the path. Chris@0: $components = explode(DIRECTORY_SEPARATOR, $uri); Chris@0: // If the filepath is absolute the first component will be empty as there Chris@0: // will be nothing before the first slash. Chris@0: if ($components[0] == '') { Chris@0: $recursive_path = DIRECTORY_SEPARATOR; Chris@0: // Get rid of the empty first component. Chris@0: array_shift($components); Chris@0: } Chris@0: else { Chris@0: $recursive_path = ''; Chris@0: } Chris@0: // Don't handle the top-level directory in this loop. Chris@0: array_pop($components); Chris@0: // Create each component if necessary. Chris@0: foreach ($components as $component) { Chris@0: $recursive_path .= $component; Chris@0: Chris@0: if (!file_exists($recursive_path)) { Chris@0: if (!$this->mkdirCall($recursive_path, $mode, FALSE, $context)) { Chris@0: return FALSE; Chris@0: } Chris@0: // Not necessary to use self::chmod() as there is no scheme. Chris@0: if (!chmod($recursive_path, $mode)) { Chris@0: return FALSE; Chris@0: } Chris@0: } Chris@0: Chris@0: $recursive_path .= DIRECTORY_SEPARATOR; Chris@0: } Chris@0: } Chris@0: Chris@0: // Do not check if the top-level directory already exists, as this condition Chris@0: // must cause this function to fail. Chris@0: if (!$this->mkdirCall($uri, $mode, FALSE, $context)) { Chris@0: return FALSE; Chris@0: } Chris@0: // Not necessary to use self::chmod() as there is no scheme. Chris@0: return chmod($uri, $mode); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Helper function. Ensures we don't pass a NULL as a context resource to Chris@0: * mkdir(). Chris@0: * Chris@0: * @see self::mkdir() Chris@0: */ Chris@0: protected function mkdirCall($uri, $mode, $recursive, $context) { Chris@0: if (is_null($context)) { Chris@0: return mkdir($uri, $mode, $recursive); Chris@0: } Chris@0: else { Chris@0: return mkdir($uri, $mode, $recursive, $context); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function rmdir($uri, $context = NULL) { Chris@0: $scheme = $this->uriScheme($uri); Chris@0: if (!$this->validScheme($scheme) && (substr(PHP_OS, 0, 3) == 'WIN')) { Chris@0: chmod($uri, 0700); Chris@0: } Chris@0: if ($context) { Chris@0: return rmdir($uri, $context); Chris@0: } Chris@0: else { Chris@0: return rmdir($uri); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function tempnam($directory, $prefix) { Chris@0: $scheme = $this->uriScheme($directory); Chris@0: Chris@0: if ($this->validScheme($scheme)) { Chris@0: $wrapper = $this->streamWrapperManager->getViaScheme($scheme); Chris@0: Chris@0: if ($filename = tempnam($wrapper->getDirectoryPath(), $prefix)) { Chris@0: return $scheme . '://' . static::basename($filename); Chris@0: } Chris@0: else { Chris@0: return FALSE; Chris@0: } Chris@0: } Chris@0: else { Chris@0: // Handle as a normal tempnam() call. Chris@0: return tempnam($directory, $prefix); Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function uriScheme($uri) { Chris@0: if (preg_match('/^([\w\-]+):\/\/|^(data):/', $uri, $matches)) { Chris@0: // The scheme will always be the last element in the matches array. Chris@0: return array_pop($matches); Chris@0: } Chris@0: Chris@0: return FALSE; Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function validScheme($scheme) { Chris@0: if (!$scheme) { Chris@0: return FALSE; Chris@0: } Chris@0: return class_exists($this->streamWrapperManager->getClass($scheme)); Chris@0: } Chris@0: Chris@0: }