Merge pull request #3979 from eileenmcnaughton/CRM-15196
[civicrm-core.git] / CRM / Utils / File.php
index e25740c3889efaebd69938359ff3d11ec6645efa..97b54fa5ff9af320b9c0aa14f71fad8d3f5e2ecc 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.3                                                |
+ | CiviCRM version 4.4                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2013                                |
  +--------------------------------------------------------------------+
@@ -380,11 +380,11 @@ class CRM_Utils_File {
    *
    * @param string $dir  the directory to be secured
    */
-  static function restrictAccess($dir) {
+  static function restrictAccess($dir, $overwrite = FALSE) {
     // note: empty value for $dir can play havoc, since that might result in putting '.htaccess' to root dir
     // of site, causing site to stop functioning.
     // FIXME: we should do more checks here -
-    if (!empty($dir)) {
+    if (!empty($dir) && is_dir($dir)) {
       $htaccess = <<<HTACCESS
 <Files "*">
   Order allow,deny
@@ -393,8 +393,38 @@ class CRM_Utils_File {
 
 HTACCESS;
       $file = $dir . '.htaccess';
-      if (file_put_contents($file, $htaccess) === FALSE) {
-        CRM_Core_Error::movedSiteError($file);
+      if ($overwrite || !file_exists($file)) {
+        if (file_put_contents($file, $htaccess) === FALSE) {
+          CRM_Core_Error::movedSiteError($file);
+        }
+      }
+    }
+  }
+
+  /**
+   * Restrict remote users from browsing the given directory.
+   *
+   * @param $publicDir
+   */
+  static function restrictBrowsing($publicDir) {
+    if (!is_dir($publicDir) || !is_writable($publicDir)) {
+      return;
+    }
+
+    // base dir
+    $nobrowse = realpath($publicDir) . '/index.html';
+    if (!file_exists($nobrowse)) {
+      @file_put_contents($nobrowse, '');
+    }
+
+    // child dirs
+    $dir = new RecursiveDirectoryIterator($publicDir);
+    foreach ($dir as $name => $object) {
+      if (is_dir($name) && $name != '..') {
+        $nobrowse = realpath($name) . '/index.html';
+        if (!file_exists($nobrowse)) {
+          @file_put_contents($nobrowse, '');
+        }
       }
     }
   }
@@ -516,7 +546,9 @@ HTACCESS;
   }
 
   /**
-   * Search directory tree for files which match a glob pattern
+   * Search directory tree for files which match a glob pattern.
+   *
+   * Note: Dot-directories (like "..", ".git", or ".svn") will be ignored.
    *
    * @param $dir string, base dir
    * @param $pattern string, glob pattern, eg "*.txt"
@@ -527,16 +559,20 @@ HTACCESS;
     $result = array();
     while (!empty($todos)) {
       $subdir = array_shift($todos);
-      foreach (glob("$subdir/$pattern") as $match) {
-        if (!is_dir($match)) {
-          $result[] = $match;
+      $matches = glob("$subdir/$pattern");
+      if (is_array($matches)) {
+        foreach ($matches as $match) {
+          if (!is_dir($match)) {
+            $result[] = $match;
+          }
         }
       }
       $dh = opendir($subdir);
       if ($dh) {
         while (FALSE !== ($entry = readdir($dh))) {
           $path = $subdir . DIRECTORY_SEPARATOR . $entry;
-          if ($entry == '.' || $entry == '..' || $entry == '.svn') {
+          if ($entry{0} == '.') {
+            // ignore
           } elseif (is_dir($path)) {
             $todos[] = $path;
           }