Add a functions file for file utility functions (say that 10 times fast) along with...
authorpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Thu, 20 Nov 2008 21:46:12 +0000 (21:46 +0000)
committerpdontthink <pdontthink@7612ce4b-ef26-0410-bec9-ea0150e637f0>
Thu, 20 Nov 2008 21:46:12 +0000 (21:46 +0000)
git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@13321 7612ce4b-ef26-0410-bec9-ea0150e637f0

functions/files.php [new file with mode: 0644]
functions/global.php
include/init.php

diff --git a/functions/files.php b/functions/files.php
new file mode 100644 (file)
index 0000000..0a297ea
--- /dev/null
@@ -0,0 +1,265 @@
+<?php
+
+/**
+ * files.php
+ *
+ * This file includes various helper functions for working
+ * with the server filesystem.
+ *
+ * @copyright &copy; 2008-2008 The SquirrelMail Project Team
+ * @license http://opensource.org/licenses/gpl-license.php GNU Public License
+ * @version $Id$
+ * @package squirrelmail
+ */
+
+
+/**
+ * Generates a unique file in a specific directory and
+ * returns the file name (without the path).
+ *
+ * @param directory The directory within which to create the file
+ *
+ * @return mixed FALSE when a failure occurs, otherwise a string
+ *               containing the filename of the file only (not
+ *               its full path)
+ *
+ * @since 1.5.2
+ *
+ */
+function sq_create_tempfile($directory)
+{
+
+    // give up after 1000 tries
+    $maximum_tries = 1000;
+
+    // using PHP >= 4.3.2 we can be truly atomic here
+    $filemods = check_php_version(4, 3, 2) ? 'x' : 'w';
+
+    for ($try = 0; $try < $maximum_tries; ++$try) {
+
+        $localfilename = GenerateRandomString(32, '', 7);
+        $full_localfilename = $directory . DIRECTORY_SEPARATOR . $localfilename;
+
+        // filename collision. try again
+        if ( file_exists($full_localfilename) ) {
+            continue;
+        }
+
+        // try to open for (binary) writing
+        $fp = @fopen( $full_localfilename, $filemods);
+
+        if ($fp !== FALSE) {
+            // success! make sure it's not readable, close and return filename
+            chmod($full_localfilename, 0600);
+            fclose($fp);
+            return $localfilename;
+        }
+
+    }
+
+    // we tried as many times as we could but didn't succeed.
+    return FALSE;
+
+}
+
+
+/**
+  * PHP's is_writable() is broken in some versions due to either
+  * safe_mode or because of problems correctly determining the
+  * actual file permissions under Windows.  Under safe_mode or
+  * Windows, we'll try to actually write something in order to
+  * see for sure...
+  *
+  * @param string $path The full path to the file or directory to
+  *                     be tested
+  *
+  * @return boolean Whether or not the file or directory exists
+  *                 and is writable
+  *
+  * @since 1.5.2
+  *
+  **/
+function sq_is_writable($path) {
+
+   global $server_os;
+
+
+   // under *nix with safe_mode off, use the native is_writable()
+   //
+   if ($server_os == '*nix' && !(bool)ini_get('safe_mode'))
+      return is_writable($path);
+
+
+   // if it's a directory, that means we have to create a temporary
+   // file therein
+   //
+   $delete_temp_file = FALSE;
+   if (@is_dir($path) && ($temp_filename = @sq_create_tempfile($path)))
+   {
+      $path .= DIRECTORY_SEPARATOR . $temp_filename;
+      $delete_temp_file = TRUE;
+   }
+
+
+   // try to open the file for writing (without trying to create it)
+   //
+   if (!@is_dir($path) && ($FILE = @fopen($path, 'r+')))
+   {
+      @fclose($FILE);
+
+      // delete temp file if needed
+      //
+      if ($delete_temp_file)
+         @unlink($path);
+
+      return TRUE;
+   }
+
+
+   // delete temp file if needed
+   //
+   if ($delete_temp_file)
+      @unlink($path);
+
+   return FALSE;
+
+}
+
+
+/**
+  * Find files and/or directories in a given directory optionally
+  * limited to only those with the given file extension.  If the
+  * directory is not found or cannot be opened, no error is generated;
+  * only an empty file list is returned.
+FIXME: do we WANT to throw an error or a notice or... or return FALSE?
+  *
+  * @param string $directory_path         The path (relative or absolute)
+  *                                       to the desired directory.
+  * @param mixed  $extension              The file extension filter - either
+  *                                       an array of desired extension(s),
+  *                                       or a comma-separated list of same
+  *                                       (optional; default is to return 
+  *                                       all files (dirs).
+  * @param boolean $return_filenames_only When TRUE, only file/dir names
+  *                                       are returned, otherwise the
+  *                                       $directory_path string is
+  *                                       prepended to each file/dir in
+  *                                       the returned list (optional;
+  *                                       default is filename/dirname only)
+  * @param boolean $include_directories   When TRUE, directories are
+  *                                       included (optional; default
+  *                                       DO include directories).
+  * @param boolean $directories_only      When TRUE, ONLY directories
+  *                                       are included (optional; default
+  *                                       is to include files too).
+  * @param boolean $separate_files_and_directories When TRUE, files and
+  *                                                directories are returned
+  *                                                in separate lists, so
+  *                                                the return value is
+  *                                                formatted as a two-element
+  *                                                array with the two keys
+  *                                                "FILES" and "DIRECTORIES",
+  *                                                where corresponding values
+  *                                                are lists of either all
+  *                                                files or all directories
+  *                                                (optional; default do not
+  *                                                split up return array).
+  * @param boolean $only_sm               When TRUE, a security check will
+  *                                       limit directory access to only
+  *                                       paths within the SquirrelMail 
+  *                                       installation currently being used
+  *                                       (optional; default TRUE)
+  *
+  * @return array The requested file/directory list(s).
+  *
+  * @since 1.5.2
+  *
+  */
+function list_files($directory_path, $extensions='', $return_filenames_only=TRUE,
+                    $include_directories=TRUE, $directories_only=FALSE,
+                    $separate_files_and_directories=FALSE, $only_sm=TRUE) {
+
+    $files = array();
+    $directories = array();
+
+
+    // make sure requested path is under SM_PATH if needed
+    //
+    if ($only_sm) {
+        if (strpos(realpath($directory_path), realpath(SM_PATH)) !== 0) {
+            //plain_error_message(_("Illegal filesystem access was requested"));
+            echo _("Illegal filesystem access was requested");
+            exit;
+        }
+    }
+
+
+    // validate given directory
+    //
+    if (empty($directory_path)
+     || !is_dir($directory_path)
+     || !($DIR = opendir($directory_path))) {
+        return $files;
+    }
+
+
+    // ensure extensions is an array and is properly formatted 
+    //
+    if (!empty($extensions)) {
+        if (!is_array($extensions))
+            $extensions = explode(',', $extensions);
+        $temp_extensions = array();
+        foreach ($extensions as $ext)
+            $temp_extensions[] = '.' . trim(trim($ext), '.');
+        $extensions = $temp_extensions;
+    } else $extensions = array();
+
+
+    $directory_path = rtrim($directory_path, '/');
+
+
+    // parse through the files
+    //
+    while (($file = readdir($DIR)) !== false) {
+
+        if ($file == '.' || $file == '..') continue;
+
+        if (!empty($extensions))
+            foreach ($extensions as $ext)
+                if (strrpos($file, $ext) !== (strlen($file) - strlen($ext)))
+                    continue 2;
+
+        // only use is_dir() if we really need to (be as efficient as possible)
+        //
+        $is_dir = FALSE;
+        if (!$include_directories || $directories_only
+                                  || $separate_files_and_directories) {
+            if (is_dir($directory_path . '/' . $file)) {
+                if (!$include_directories) continue;
+                $is_dir = TRUE;
+                $directories[] = ($return_filenames_only
+                               ? $file
+                               : $directory_path . '/' . $file);
+            }
+            if ($directories_only) continue;
+        }
+
+        if (!$separate_files_and_directories
+         || ($separate_files_and_directories && !$is_dir)) {
+            $files[] = ($return_filenames_only
+                     ? $file
+                     : $directory_path . '/' . $file);
+        }
+
+    }
+    closedir($DIR);
+
+
+    if ($directories_only) return $directories;
+    if ($separate_files_and_directories) return array('FILES' => $files,
+                                                      'DIRECTORIES' => $directories);
+    return $files;
+
+}
+
+
index 2916858..7a77c25 100644 (file)
@@ -624,143 +624,6 @@ function php_self () {
 
 
 /**
-  * Find files and/or directories in a given directory optionally
-  * limited to only those with the given file extension.  If the
-  * directory is not found or cannot be opened, no error is generated;
-  * only an empty file list is returned.
-FIXME: do we WANT to throw an error or a notice or... or return FALSE?
-  *
-  * @param string $directory_path         The path (relative or absolute)
-  *                                       to the desired directory.
-  * @param mixed  $extension              The file extension filter - either
-  *                                       an array of desired extension(s),
-  *                                       or a comma-separated list of same
-  *                                       (optional; default is to return 
-  *                                       all files (dirs).
-  * @param boolean $return_filenames_only When TRUE, only file/dir names
-  *                                       are returned, otherwise the
-  *                                       $directory_path string is
-  *                                       prepended to each file/dir in
-  *                                       the returned list (optional;
-  *                                       default is filename/dirname only)
-  * @param boolean $include_directories   When TRUE, directories are
-  *                                       included (optional; default
-  *                                       DO include directories).
-  * @param boolean $directories_only      When TRUE, ONLY directories
-  *                                       are included (optional; default
-  *                                       is to include files too).
-  * @param boolean $separate_files_and_directories When TRUE, files and
-  *                                                directories are returned
-  *                                                in separate lists, so
-  *                                                the return value is
-  *                                                formatted as a two-element
-  *                                                array with the two keys
-  *                                                "FILES" and "DIRECTORIES",
-  *                                                where corresponding values
-  *                                                are lists of either all
-  *                                                files or all directories
-  *                                                (optional; default do not
-  *                                                split up return array).
-  * @param boolean $only_sm               When TRUE, a security check will
-  *                                       limit directory access to only
-  *                                       paths within the SquirrelMail 
-  *                                       installation currently being used
-  *                                       (optional; default TRUE)
-  *
-  * @return array The requested file/directory list(s).
-  *
-  * @since 1.5.2
-  *
-  */
-function list_files($directory_path, $extensions='', $return_filenames_only=TRUE,
-                    $include_directories=TRUE, $directories_only=FALSE,
-                    $separate_files_and_directories=FALSE, $only_sm=TRUE) {
-
-    $files = array();
-    $directories = array();
-
-
-    // make sure requested path is under SM_PATH if needed
-    //
-    if ($only_sm) {
-        if (strpos(realpath($directory_path), realpath(SM_PATH)) !== 0) {
-            //plain_error_message(_("Illegal filesystem access was requested"));
-            echo _("Illegal filesystem access was requested");
-            exit;
-        }
-    }
-
-
-    // validate given directory
-    //
-    if (empty($directory_path)
-     || !is_dir($directory_path)
-     || !($DIR = opendir($directory_path))) {
-        return $files;
-    }
-
-
-    // ensure extensions is an array and is properly formatted 
-    //
-    if (!empty($extensions)) {
-        if (!is_array($extensions))
-            $extensions = explode(',', $extensions);
-        $temp_extensions = array();
-        foreach ($extensions as $ext)
-            $temp_extensions[] = '.' . trim(trim($ext), '.');
-        $extensions = $temp_extensions;
-    } else $extensions = array();
-
-
-    $directory_path = rtrim($directory_path, '/');
-
-
-    // parse through the files
-    //
-    while (($file = readdir($DIR)) !== false) {
-
-        if ($file == '.' || $file == '..') continue;
-
-        if (!empty($extensions))
-            foreach ($extensions as $ext)
-                if (strrpos($file, $ext) !== (strlen($file) - strlen($ext)))
-                    continue 2;
-
-        // only use is_dir() if we really need to (be as efficient as possible)
-        //
-        $is_dir = FALSE;
-        if (!$include_directories || $directories_only
-                                  || $separate_files_and_directories) {
-            if (is_dir($directory_path . '/' . $file)) {
-                if (!$include_directories) continue;
-                $is_dir = TRUE;
-                $directories[] = ($return_filenames_only
-                               ? $file
-                               : $directory_path . '/' . $file);
-            }
-            if ($directories_only) continue;
-        }
-
-        if (!$separate_files_and_directories
-         || ($separate_files_and_directories && !$is_dir)) {
-            $files[] = ($return_filenames_only
-                     ? $file
-                     : $directory_path . '/' . $file);
-        }
-
-    }
-    closedir($DIR);
-
-
-    if ($directories_only) return $directories;
-    if ($separate_files_and_directories) return array('FILES' => $files,
-                                                      'DIRECTORIES' => $directories);
-    return $files;
-
-}
-
-
-/**
  * Print variable
  *
  * sm_print_r($some_variable, [$some_other_variable [, ...]]);
@@ -856,3 +719,5 @@ function sq_htmlspecialchars($value, $quote_style=ENT_QUOTES) {
     return $value;
 
 }
+
+
index 228999c..a024f8f 100644 (file)
@@ -190,6 +190,7 @@ require(SM_PATH . 'include/constants.php');
 require(SM_PATH . 'functions/global.php');
 require(SM_PATH . 'functions/strings.php');
 require(SM_PATH . 'functions/arrays.php');
+require(SM_PATH . 'functions/files.php');
 
 /* load default configuration */
 require(SM_PATH . 'config/config_default.php');