From 55890b471a151c5c8e889723b9727061dccc050c Mon Sep 17 00:00:00 2001
From: Nathaniel Catchpole <catch@35733.no-reply.drupal.org>
Date: Wed, 5 Feb 2014 10:28:48 +0000
Subject: [PATCH] Issue #2110863 by sun, cpj: Support open_basedir.

---
 core/includes/file.inc                        |  3 ++
 core/install.php                              |  6 ---
 .../Component/PhpStorage/FileStorage.php      | 51 ++++++++++++-------
 core/lib/Drupal/Core/DrupalKernel.php         |  2 +-
 4 files changed, 37 insertions(+), 25 deletions(-)

diff --git a/core/includes/file.inc b/core/includes/file.inc
index e1219b3fdf2c..83e6dc9df218 100644
--- a/core/includes/file.inc
+++ b/core/includes/file.inc
@@ -1497,6 +1497,9 @@ function drupal_basename($uri, $suffix = NULL) {
  * @see mkdir()
  * @see http://drupal.org/node/515192
  * @ingroup php_wrappers
+ *
+ * @todo Update with open_basedir compatible recursion logic from
+ *   \Drupal\Component\PhpStorage\FileStorage::ensureDirectory().
  */
 function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
   if (!isset($mode)) {
diff --git a/core/install.php b/core/install.php
index b12947a618d4..7152fd812b02 100644
--- a/core/install.php
+++ b/core/install.php
@@ -36,12 +36,6 @@
   exit;
 }
 
-// Exit early if the PHP option open_basedir is enabled to avoid fatal errors.
-if (ini_get('open_basedir')) {
-  print 'Your PHP installation has open_basedir enabled. Drupal currently requires the open_basedir option to be turned off. See the <a href="http://www.php.net/manual/en/ini.core.php#ini.open-basedir">PHP manual</a> for details of how to do this. This issue is currently <a href="https://drupal.org/node/2110863">under discussion at drupal.org</a>.';
-  exit;
-}
-
 // Start the installer.
 require_once __DIR__ . '/includes/install.core.inc';
 install_drupal();
diff --git a/core/lib/Drupal/Component/PhpStorage/FileStorage.php b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
index dbfa12d0344c..e6b4f0f84905 100644
--- a/core/lib/Drupal/Component/PhpStorage/FileStorage.php
+++ b/core/lib/Drupal/Component/PhpStorage/FileStorage.php
@@ -58,31 +58,46 @@ public function save($name, $code) {
   }
 
   /**
-   * Ensures the root directory exists and has the right permissions.
+   * Ensures the requested directory exists and has the right permissions.
+   *
+   * For compatibility with open_basedir, the requested directory is created
+   * using a recursion logic that is based on the relative directory path/tree:
+   * It works from the end of the path recursively back towards the root
+   * directory, until an existing parent directory is found. From there, the
+   * subdirectories are created.
    *
    * @param string $directory
    *   The directory path.
-   *
    * @param int $mode
    *   The mode, permissions, the directory should have.
+   * @param bool $is_backwards_recursive
+   *   Internal use only.
+   *
+   * @return bool
+   *   TRUE if the directory exists or has been created, FALSE otherwise.
    */
-  protected function ensureDirectory($directory, $mode = 0777) {
-    if (!file_exists($directory)) {
-      // mkdir() obeys umask() so we need to mkdir() and chmod() manually.
-      $parts = explode('/', $directory);
-      $path = '';
-      $delimiter = '';
-      do {
-        $part = array_shift($parts);
-        $path .= $delimiter . $part;
-        $delimiter = '/';
-        // For absolute paths the first part will be empty.
-        if ($part && !file_exists($path)) {
-          mkdir($path);
-          chmod($path, $mode);
-        }
-      } while ($parts);
+  protected function ensureDirectory($directory, $mode = 0777, $is_backwards_recursive = FALSE) {
+    // If the directory exists already, there's nothing to do.
+    if (is_dir($directory)) {
+      return TRUE;
+    }
+    // Otherwise, try to create the directory and ensure to set its permissions,
+    // because mkdir() obeys the umask of the current process.
+    if (is_dir($parent = dirname($directory))) {
+      // If the parent directory exists, then the backwards recursion must end,
+      // regardless of whether the subdirectory could be created.
+      if ($status = mkdir($directory)) {
+        // Only try to chmod() if the subdirectory could be created.
+        $status = chmod($directory, $mode);
+      }
+      return $is_backwards_recursive ? TRUE : $status;
     }
+    // If the parent directory and the requested directory does not exist and
+    // could not be created above, walk the requested directory path back up
+    // until an existing directory is hit, and from there, recursively create
+    // the sub-directories. Only if that recursion succeeds, create the final,
+    // originally requested subdirectory.
+    return $this->ensureDirectory($parent, $mode, TRUE) && mkdir($directory) && chmod($directory, $mode);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
index 46a7fee6b4d3..85fa7f817ee5 100644
--- a/core/lib/Drupal/Core/DrupalKernel.php
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -510,7 +510,7 @@ protected function buildContainer() {
     foreach (array('Core', 'Component') as $parent_directory) {
       $path = DRUPAL_ROOT . '/core/lib/Drupal/' . $parent_directory;
       foreach (new \DirectoryIterator($path) as $component) {
-        if (!$component->isDot() && is_dir($component->getPathname() . '/Plugin')) {
+        if (!$component->isDot() && $component->isDir() && is_dir($component->getPathname() . '/Plugin')) {
           $namespaces['Drupal\\' . $parent_directory . '\\' . $component->getFilename()] = DRUPAL_ROOT . '/core/lib';
         }
       }
-- 
GitLab