From 15f289a8f0ab4cc2e1253731ca5af5987b3af0d6 Mon Sep 17 00:00:00 2001 From: Dries Buytaert <dries@buytaert.net> Date: Fri, 26 Dec 2003 23:03:21 +0000 Subject: [PATCH] - Added file handling. Work by Kjartan. --- includes/common.inc | 1 + includes/file.inc | 357 +++++++++++++++++++++++++++++++++ modules/profile.module | 75 ++++--- modules/profile/profile.module | 75 ++++--- modules/system.module | 37 ++-- modules/system/system.module | 37 ++-- 6 files changed, 454 insertions(+), 128 deletions(-) create mode 100644 includes/file.inc diff --git a/includes/common.inc b/includes/common.inc index e3bbbf841f5b..fd92d3664a8d 100644 --- a/includes/common.inc +++ b/includes/common.inc @@ -935,6 +935,7 @@ function drupal_page_footer() { include_once "includes/menu.inc"; include_once "includes/xmlrpc.inc"; include_once "includes/tablesort.inc"; +include_once "includes/file.inc"; // set error handler: set_error_handler("error_handler"); diff --git a/includes/file.inc b/includes/file.inc new file mode 100644 index 000000000000..2e8cd7b44683 --- /dev/null +++ b/includes/file.inc @@ -0,0 +1,357 @@ +<?php +/** @file + * $Id$ + * + * Common file handling functions + * + * @par Example: + * @code + * function module_validate($node) { + * if (!$node->file = file_save_upload('file')) { + * $error['file'] = t('File required.'); + * } + * } + * + * function module_insert($node) { + * if ($node->file) { + * file_save($node->file); + * } + * } + * @endcode + * + */ + +define('FILE_DOWNLOADS_PUBLIC', 1); +define('FILE_DOWNLOADS_PRIVATE', 2); +define('FILE_SEPARATOR', PHP_OS == 'WINNT' ? '\\' : '/'); + +/** + * Create the download path to a file. + */ +function file_create_url($path) { + switch (variable_get('file_downloads', FILE_DOWNLOADS_PRIVATE)) { + case FILE_DOWNLOADS_PUBLIC: + case FILE_DOWNLOADS_PRIVATE: + global $base_url; + if (strpos($path, variable_get('file_directory_path', 'files')) !== false) { + $path = trim(substr($path, strlen(variable_get('file_directory_path', 'files'))), '\\/'); + } + return $base_url .'/'. variable_get('file_directory_path', 'files') .'/'. str_replace('\\', '/', $path); + case FILE_DOWNLOADS_PRIVATE: + return url('system/files', 'file='. $path); + } +} + +/** + * Make sure the destination is a complete path, if it is not prepend the + * file system directory. + */ +function file_create_path($dest = 0) { + if (!$dest) { + return variable_get('file_directory_path', 'files'); + } + + $regex = (PHP_OS == 'WINNT' ? '.?:\\\\' : '/'); + if (!file_check_location($dest, variable_get('file_directory_path', 'files')) && !preg_match("|^$regex|", $dest)) { + return variable_get('file_directory_path', 'files') . FILE_SEPARATOR . trim($dest, '\\/'); + } + else { + return $dest; + } +} + +/** + * Check that directory exists and is writable. + * + * @param $directory Path to extract and verify directory for. + * @return False when directory not found, or true when directory exists. + */ +function file_check_directory(&$directory) { + $directory = rtrim($directory, '/\\'); + return is_dir($directory) && is_writable($directory); +} + +/** + * Checks path to see if it is a directory, or a dir/file. + * + * @param $path + */ +function file_check_path(&$path) { + // Check if path is a directory. + if (file_check_directory($path)) { + return ''; + } + + // Check if path is a possible dir/file. + $filename = basename($path); + $path = dirname($path); + if (file_check_directory($path)) { + return $filename; + } + + return false; +} + +/** + * Check if $source is a valid file upload. + * + * @param $source + */ +function file_check_upload($source) { + if ($_FILES["edit"]["name"][$source] && is_uploaded_file($_FILES["edit"]["tmp_name"][$source])) { + $file->name = trim(basename($_FILES["edit"]["name"][$source]), '.'); + $file->type = $_FILES["edit"]["type"][$source]; + $file->path = $_FILES["edit"]["tmp_name"][$source]; + $file->error = $_FILES["edit"]["error"][$source]; + $file->size = $_FILES["edit"]["size"][$source]; + return $file; + } +} + +/** + * Check if a file is really located inside $directory. Should be used to make + * sure a file specified is really located within the directory to prevent + * exploits. + * + * @code + * // Returns false: + * file_check_location('/www/example.com/files/../../../etc/passwd', '/www/example.com/files'); + * @endcode + * + * @param $source A string set to the file to check. + * @param $directory A string where the file should be located. + * @return 0 for invalid path or the real path of the source. + */ +function file_check_location($source, $directory = 0) { + $source = realpath($source); + if ($directory && strpos($source, $directory) !== 0) { + return 0; + } + return $source; +} + +/** + * Saves a file to a new location. This is a powerful function that in many ways + * performs like an advanced version of copy(). + * - Checks if $source and $dest are valid and readable/writable. + * - Performs a file copy if $source is not equal to $dest. + * - If file already exists in $dest it will append a number to the end of the + * filename, but before the file extension. It will increment the number until + * it finds a filename that is not already in use. + * + * @param $source A string specifying the file location of the original file. + * This parameter will contain the resulting destination filename in case of + * success. + * @param $dest A string containing the directory $source should be copied to. + * @param $replace A boolean that when true will overwrite any existing files, + * but when false append a _X to the filename. + * @return True for success, false for failure. + */ +function file_copy(&$source, $dest = 0, $replace = 0) { + $dest = file_create_path($dest); + + $directory = $dest; + $basename = file_check_path($directory); + + // Make sure we at least have a valid directory. + if ($basename === false) { + drupal_set_message(t('file copy failed: no directory configured, or it could not be accessed.'), 'error'); + return 0; + } + + // Process a file upload object. + if (is_object($source)) { + $file = $source; + $source = $file->path; + if (!$basename) { + $basename = $file->name; + } + } + + $source = realpath($source); + if (!file_exists($source)) { + drupal_set_message(t('file copy failed: source file does not exist.'), 'error'); + return 0; + } + + // If destination file is not specified then use filename of source file. + $basename = $basename ? $basename : basename($source); + $dest = $directory . FILE_SEPARATOR . $basename; + + if (file_exists($dest) && !$replace) { + // Destination file already exists and we can't replace is so we try and + // and find a new filename. + list($name, $ext) = explode('.', $basename, 2); + $ext = $ext ? ".$ext" : ''; + $counter = 0; + do { + $dest = $directory . FILE_SEPARATOR . $name .'_'. $counter++ . $ext; + $counter++; + } while (file_exists($dest)); + } + + if (!copy($source, $dest)) { + drupal_set_message(t('file copy failed.'), 'error'); + return 0; + } + + if (is_object($file)) { + $file->name = $basename; + $file->path = $dest; + $source = $file; + } + else { + $source = $dest; + } + return 1; // Everything went ok. +} + +function file_move(&$source, $dest = 0, $replace = 0) { + $path = is_object($source) ? $source->path : $source; + if (file_copy($source, $dest, $replace)) { + if (unlink($path)) { + return 1; + } + drupal_set_message(t('removing original file failed.'), 'error'); + } + return 0; +} + +function file_delete($source) { + unlink(file_create_path($source)); +} + +/** + * Saves a file upload to a new location. The source file is validated as a + * proper upload and handled as such. + * + * @param $source A string specifying the name of the upload field to save. + * This parameter will contain the resulting destination filename in case of + * success. + * @param $dest A string containing the directory $source should be copied to, + * will use the temporary directory in case no other value is set. + * @param $dest A boolean, set to true if the destination should be replaced + * when in use, but when false append a _X to the filename. + * @return An object containing file info or 0 in case of error. + */ +function file_save_upload($source, $dest = 0, $replace = 0) { + // Make sure $source exists in $_FILES. + if ($file = file_check_upload($source)) { + if ($dest === 0) { + $dest = variable_get('file_directory_temp', ini_get('upload_tmp_dir')); + $temporary = 1; + if (file_exists($_SESSION['file_uploads'][$source]->path)) { + // If this file was uploaded by this user before replace the temporary copy. + $replace = 1; + } + } + + if (!valid_input_data($file)) { + watchdog('error', t('Possible exploit abuse: invalid data.')); + drupal_set_message(t("file upload failed: invalid data."), 'error'); + return 0; + } + + // Check for file upload errors. + switch ($file->error) { + case UPLOAD_ERR_PARTIAL: + case UPLOAD_ERR_NO_FILE: + drupal_set_message(t("file upload failed: incomplete upload."), 'error'); + return 0; + case UPLOAD_ERR_INI_SIZE: + case UPLOAD_ERR_FORM_SIZE: + drupal_set_message(t("file upload failed: file size too big."), 'error'); + return 0; + } + + unset($_SESSION['file_uploads'][$source]); + if (file_move($file, $dest, $replace)) { + if ($temporary) { + $_SESSION['file_uploads'][$source] = $file; + } + return $file; + } + return 0; + } + else { + // In case if previews return previous file object. + if (file_exists($_SESSION['file_uploads'][$source]->path)) { + return $_SESSION['file_uploads'][$source]; + } + } + return 0; +} + +/** + * Transfer file using http to client. Pipes a file through Drupal to the + * client. + * + * @param $source File to transfer. + * @param $headers An array of http headers to send along with file. + */ +function file_transfer($source, $headers) { + ob_end_clean(); + + foreach ($headers as $header) { + header($header); + } + + $source = file_create_path($source); + + // Transfer file in 1024 byte chunks to save memory usage. + $fd = fopen($source, 'rb'); + while (!feof($fd)) { + print fgets($fd); + } + fclose($fd); + exit(); +} + +/** + * Call modules to find out if a file is accessible for a given user. + */ +function file_download() { + $file = $_GET['file']; + if (file_exists(file_create_path($file))) { + $list = module_list(); + foreach ($list as $module) { + $headers = module_invoke($module, 'file_download', $file); + if ($headers === -1) { + print theme('page', message_access()); + } + elseif (is_array($headers)) { + file_transfer($file, $headers); + } + } + } + //drupal_not_found(); +} + +/** + * Finds all files that match a given mask in a given directory. Searches + * recursively. + */ +function file_scan_directory($dir, $mask, $nomask = array('.', '..', 'CVS'), $callback = 0) { + $files = array(); + if (is_dir($dir) && $handle = opendir($dir)) { + while ($file = readdir($handle)) { + if (!in_array($file, $nomask)) { + if (is_dir("$dir/$file")) { + $files = array_merge($files, file_scan_directory("$dir/$file", $mask, $nomask, $callback)); + } + elseif (ereg($mask, $file)) { + $name = basename($file); + $files["$dir/$file"]->filename = "$dir/$file"; + $files["$dir/$file"]->name = substr($name, 0, strrpos($name, '.')); + if ($callback) { + $callback("$dir/$file"); + } + } + } + } + closedir($handle); + } + return $files; +} + +?> diff --git a/modules/profile.module b/modules/profile.module index 1123ba4c7a48..38f44212c410 100644 --- a/modules/profile.module +++ b/modules/profile.module @@ -57,6 +57,10 @@ function profile_settings() { _profile_init(); } + if (!file_check_directory(file_create_path(variable_get('profile_avatar_path', 'avatars')))) { + $error['profile_avatar_path'] = theme('error', t('Directory does not exist, or is not writable.')); + } + $profile_public_fields = variable_get("profile_public_fields", array()); $profile_private_fields = variable_get("profile_private_fields", array()); $profile_required_fields = variable_get("profile_required_fields", array()); @@ -74,7 +78,7 @@ function profile_settings() { } $output .= theme("table", $header, $row); - $output .= form_textfield(t("Avatar image path"), "profile_avatar_path", variable_get("profile_avatar_path", "misc/avatars/"), 30, 255, t("Path for avatar directory; it must be writable and visible from the web.")); + $output .= form_textfield(t("Avatar image path"), "profile_avatar_path", variable_get("profile_avatar_path", "avatars"), 30, 255, t("Subdirectory in the directory '%dir' where avatars will be stored.", array('%dir' => variable_get('file_directory_path', 'files') . FILE_SEPARATOR)) . $error['profile_avatar_path']); $output .= form_textfield(t("Avatar maximum dimensions"), "profile_avatar_dimensions", variable_get("profile_avatar_dimensions", "85x85"), 10, 10, t("Maximum dimensions for avatars.")); $output .= form_textfield(t("Avatar maximum file size"), "profile_avatar_file_size", variable_get("profile_avatar_file_size", "30"), 10, 10, t("Maximum file size for avatars, in kB.")); @@ -133,11 +137,8 @@ function _profile_form($edit, $mode) { } if (in_array("avatar", $reg_fields)) { - if ($edit["profile_avatar"] && $edit["uid"]) { - $file = profile_avatar_path($edit["uid"], $edit["profile_avatar"]); - if ($file) { - $output .= "<img src=\"$file\" alt=\"\" title=\"\" /><br />"; - } + if ($edit["profile_avatar"] && file_exists($edit["profile_avatar"])) { + $output .= form_item(t("Avatar"), '<img src="'. file_create_url($edit["profile_avatar"]) .'" alt="" title="" />'); } $output .= form_file($profile_fields["avatar"][1], "profile_avatar", 64, $profile_fields["avatar"][2]); } @@ -199,9 +200,8 @@ function _profile_user_view(&$user, $mode) { case "": // special if ($t == "profile_avatar") { - $file = profile_avatar_path($user->uid, $user->profile_avatar); - if (file_exists($file)) { - $output .= form_item(t("Avatar"), "<img src=\"$file\" alt=\"\" title=\"\" />"); + if (file_exists($user->$t)) { + $output .= form_item(t("Avatar"), '<img src="'. file_create_url($user->$t) .'" alt="" title="" />'); } } @@ -218,51 +218,44 @@ function _profile_user_view(&$user, $mode) { return $output; } +function profile_file_download($file) { + if (strpos($file, variable_get("profile_avatar_path", "avatars")) === 0) { + return array("Content-type: $mime"); + } +} + function _profile_validate_avatar(&$edit, $user) { // check that uploaded file is an image, with a maximum file size and maximum height/width unset($edit["profile_avatar"]); - if ($_FILES["edit"]["name"]["profile_avatar"] == "") { + if (!$file = file_check_upload('profile_avatar')) { $edit["profile_avatar"] = $user->profile_avatar; - return ""; + return; } - $image_file = $_FILES["edit"]["tmp_name"]["profile_avatar"]; - if (is_uploaded_file($image_file)) { - $extension = strtolower(strrchr($_FILES["edit"]["name"]["profile_avatar"], ".")); - $size = getimagesize($image_file); - list($maxwidth, $maxheight) = explode("x", variable_get("profile_avatar_dimensions", "85x85")); - if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) { - $error = t("The uploaded file was not an image."); - } - else if (filesize($image_file) > (variable_get("profile_avatar_file_size", "30") * 1000)) { - $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get("profile_avatar_file_size", "30"))); - } - else if ($size[0] > $maxwidth || $size[1] > $maxheight) { - $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get("profile_avatar_dimensions", "85x85"))); - } - else if (!is_dir(variable_get("profile_avatar_path", "misc/avatars/"))) { - $error = t("Failed to upload the avatar image; the '%directory' directory doesn't exist.", array("%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else if (!is_writeable(variable_get("profile_avatar_path", "misc/avatars/"))) { - $error = t("Failed to upload the avatar image; the webserver has no write permission to the '%directory' directory.", array("%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else if (!copy($image_file, variable_get("profile_avatar_path", "misc/avatars/").md5($user->uid).$extension)) { - $error = t("Failed to upload the avatar image; could not copy file '%filename' to directory '%directory'.", array("%filename" => $_FILES["edit"]["name"]["profile_avatar"], "%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else { - $edit["profile_avatar"] = $extension; - } + $extension = strtolower(strrchr($file->name, ".")); + $size = getimagesize($file->path); + list($maxwidth, $maxheight) = explode("x", variable_get("profile_avatar_dimensions", "85x85")); + if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) { + $error = t("The uploaded file was not an image."); + } + else if ($file->size > (variable_get("profile_avatar_file_size", "30") * 1000)) { + $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get("profile_avatar_file_size", "30"))); + } + else if ($size[0] > $maxwidth || $size[1] > $maxheight) { + $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get("profile_avatar_dimensions", "85x85"))); + } + else if ($file = file_save_upload('profile_avatar', variable_get("profile_avatar_path", "avatars") . FILE_SEPARATOR .'avatar-'. $user->uid . $extension, 1)) { + $edit["profile_avatar"] = $file->name; + } + else { + $error = t("Failed to upload the avatar image; the '%directory' directory doesn't exist.", array("%directory" => variable_get("profile_avatar_path", "avatars"))); } return $error ? "$error<br />" : ""; } -function profile_avatar_path($uid, $extension) { - return $extension ? variable_get("profile_avatar_path", "misc/avatars/") . md5($uid) . $extension : ""; -} - function _profile_active_fields($mode) { return variable_get("profile_". $mode ."_fields", array()); } diff --git a/modules/profile/profile.module b/modules/profile/profile.module index 1123ba4c7a48..38f44212c410 100644 --- a/modules/profile/profile.module +++ b/modules/profile/profile.module @@ -57,6 +57,10 @@ function profile_settings() { _profile_init(); } + if (!file_check_directory(file_create_path(variable_get('profile_avatar_path', 'avatars')))) { + $error['profile_avatar_path'] = theme('error', t('Directory does not exist, or is not writable.')); + } + $profile_public_fields = variable_get("profile_public_fields", array()); $profile_private_fields = variable_get("profile_private_fields", array()); $profile_required_fields = variable_get("profile_required_fields", array()); @@ -74,7 +78,7 @@ function profile_settings() { } $output .= theme("table", $header, $row); - $output .= form_textfield(t("Avatar image path"), "profile_avatar_path", variable_get("profile_avatar_path", "misc/avatars/"), 30, 255, t("Path for avatar directory; it must be writable and visible from the web.")); + $output .= form_textfield(t("Avatar image path"), "profile_avatar_path", variable_get("profile_avatar_path", "avatars"), 30, 255, t("Subdirectory in the directory '%dir' where avatars will be stored.", array('%dir' => variable_get('file_directory_path', 'files') . FILE_SEPARATOR)) . $error['profile_avatar_path']); $output .= form_textfield(t("Avatar maximum dimensions"), "profile_avatar_dimensions", variable_get("profile_avatar_dimensions", "85x85"), 10, 10, t("Maximum dimensions for avatars.")); $output .= form_textfield(t("Avatar maximum file size"), "profile_avatar_file_size", variable_get("profile_avatar_file_size", "30"), 10, 10, t("Maximum file size for avatars, in kB.")); @@ -133,11 +137,8 @@ function _profile_form($edit, $mode) { } if (in_array("avatar", $reg_fields)) { - if ($edit["profile_avatar"] && $edit["uid"]) { - $file = profile_avatar_path($edit["uid"], $edit["profile_avatar"]); - if ($file) { - $output .= "<img src=\"$file\" alt=\"\" title=\"\" /><br />"; - } + if ($edit["profile_avatar"] && file_exists($edit["profile_avatar"])) { + $output .= form_item(t("Avatar"), '<img src="'. file_create_url($edit["profile_avatar"]) .'" alt="" title="" />'); } $output .= form_file($profile_fields["avatar"][1], "profile_avatar", 64, $profile_fields["avatar"][2]); } @@ -199,9 +200,8 @@ function _profile_user_view(&$user, $mode) { case "": // special if ($t == "profile_avatar") { - $file = profile_avatar_path($user->uid, $user->profile_avatar); - if (file_exists($file)) { - $output .= form_item(t("Avatar"), "<img src=\"$file\" alt=\"\" title=\"\" />"); + if (file_exists($user->$t)) { + $output .= form_item(t("Avatar"), '<img src="'. file_create_url($user->$t) .'" alt="" title="" />'); } } @@ -218,51 +218,44 @@ function _profile_user_view(&$user, $mode) { return $output; } +function profile_file_download($file) { + if (strpos($file, variable_get("profile_avatar_path", "avatars")) === 0) { + return array("Content-type: $mime"); + } +} + function _profile_validate_avatar(&$edit, $user) { // check that uploaded file is an image, with a maximum file size and maximum height/width unset($edit["profile_avatar"]); - if ($_FILES["edit"]["name"]["profile_avatar"] == "") { + if (!$file = file_check_upload('profile_avatar')) { $edit["profile_avatar"] = $user->profile_avatar; - return ""; + return; } - $image_file = $_FILES["edit"]["tmp_name"]["profile_avatar"]; - if (is_uploaded_file($image_file)) { - $extension = strtolower(strrchr($_FILES["edit"]["name"]["profile_avatar"], ".")); - $size = getimagesize($image_file); - list($maxwidth, $maxheight) = explode("x", variable_get("profile_avatar_dimensions", "85x85")); - if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) { - $error = t("The uploaded file was not an image."); - } - else if (filesize($image_file) > (variable_get("profile_avatar_file_size", "30") * 1000)) { - $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get("profile_avatar_file_size", "30"))); - } - else if ($size[0] > $maxwidth || $size[1] > $maxheight) { - $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get("profile_avatar_dimensions", "85x85"))); - } - else if (!is_dir(variable_get("profile_avatar_path", "misc/avatars/"))) { - $error = t("Failed to upload the avatar image; the '%directory' directory doesn't exist.", array("%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else if (!is_writeable(variable_get("profile_avatar_path", "misc/avatars/"))) { - $error = t("Failed to upload the avatar image; the webserver has no write permission to the '%directory' directory.", array("%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else if (!copy($image_file, variable_get("profile_avatar_path", "misc/avatars/").md5($user->uid).$extension)) { - $error = t("Failed to upload the avatar image; could not copy file '%filename' to directory '%directory'.", array("%filename" => $_FILES["edit"]["name"]["profile_avatar"], "%directory" => variable_get("profile_avatar_path", "misc/avatars/"))); - } - else { - $edit["profile_avatar"] = $extension; - } + $extension = strtolower(strrchr($file->name, ".")); + $size = getimagesize($file->path); + list($maxwidth, $maxheight) = explode("x", variable_get("profile_avatar_dimensions", "85x85")); + if ((!in_array($size[2], array(1, 2, 3))) || (!in_array($extension, array(".gif", ".jpg", ".png", ".jpeg")))) { + $error = t("The uploaded file was not an image."); + } + else if ($file->size > (variable_get("profile_avatar_file_size", "30") * 1000)) { + $error = t("The uploaded image is too large; the maximum file size is %a kB.", array("%a" => variable_get("profile_avatar_file_size", "30"))); + } + else if ($size[0] > $maxwidth || $size[1] > $maxheight) { + $error = t("The uploaded image is too large; the maximum dimensions are %a pixels.", array("%a" => variable_get("profile_avatar_dimensions", "85x85"))); + } + else if ($file = file_save_upload('profile_avatar', variable_get("profile_avatar_path", "avatars") . FILE_SEPARATOR .'avatar-'. $user->uid . $extension, 1)) { + $edit["profile_avatar"] = $file->name; + } + else { + $error = t("Failed to upload the avatar image; the '%directory' directory doesn't exist.", array("%directory" => variable_get("profile_avatar_path", "avatars"))); } return $error ? "$error<br />" : ""; } -function profile_avatar_path($uid, $extension) { - return $extension ? variable_get("profile_avatar_path", "misc/avatars/") . md5($uid) . $extension : ""; -} - function _profile_active_fields($mode) { return variable_get("profile_". $mode ."_fields", array()); } diff --git a/modules/system.module b/modules/system.module index 5ac19cc54e52..af45d64f6abc 100644 --- a/modules/system.module +++ b/modules/system.module @@ -35,8 +35,7 @@ function system_help($section = "admin/help#system") { // Start of system_help_cache $output .= "<p>Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.</p>"; // End of system_help_cache - $output = t($output, array("%base_url" => $base_url, "%cron-link" => "<a href=\"$base_url/cron.php\ -\">$base_url/cron.php</a>", "%lynx" => "<a href=\"http://lynx.browser.org\">lynx</a>", "%wget" => "<a href=\"http://www.gnu.org/software/wget/wget.html\">wget</a>" )); + $output = t($output, array("%base_url" => $base_url, "%cron-link" => "<a href=\"$base_url/cron.php\">$base_url/cron.php</a>", "%lynx" => "<a href=\"http://lynx.browser.org\">lynx</a>", "%wget" => "<a href=\"http://www.gnu.org/software/wget/wget.html\">wget</a>" )); break; case 'admin/system/modules#description': $output = t("Configuration system that lets administrators modify the workings of the site."); @@ -56,6 +55,7 @@ function system_perm() { function system_link($type) { if ($type == "system") { + menu("system/files", t("file download"), "file_download", 0, MENU_HIDE); if (user_access("administer site configuration")) { menu("admin/system", t("configuration"), "system_admin", 3); @@ -126,6 +126,17 @@ function system_view_general() { $output .= form_group(t("Cache settings"), $group); + // file system: + if (!file_check_directory(variable_get('file_directory_path', 'files'))) { + $error['file_directory_path'] = theme('error', t('Directory does not exist, or is not writable.')); + } + if (!file_check_directory(variable_get('file_directory_temp', ini_get('upload_tmp_dir')))) { + $error['file_directory_temp'] = theme('error', t('Directory does not exist, or is not writable.')); + } + $group = form_textfield(t('File system path'), 'file_directory_path', variable_get('file_directory_path', 'files'), 70, 255, t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.') . $error['file_directory_path']); + $group .= form_textfield(t('Temporary directory'), 'file_directory_temp', variable_get('file_directory_temp', (PHP_OS == 'WINNT' ? 'c:\\windows\\temp' : '/tmp')), 70, 255, t('Location where files can be saved temporarily. This directory should not be accessible from the web.') . $error['file_directory_temp']); + $group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are be transferred by Drupal.')), t('This setting can be changed at any time, however, all download URLs will change and there may be unexpected problems so it is not recommended.')); + $output .= form_group(t('File system'), $group); // submission settings: $rate = array(-10000 => t("Disabled"), 1 => t("Maximum 1 every second"), 5 => t("Maximum 1 every 5 seconds"), 15 => t("Maximum 1 every 15 seconds"), 30 => t("Maximum 1 every 30 seconds"), 60 => t("Maximum 1 every minute"), 300 => t("Maximum 1 every 5 minutes"), 900 => t("Maximum 1 every 15 minutes"), 1800 => t("Maximum 1 every 30 minutes"), 3600 => t("Maximum 1 every hour"), 21600 => t("Maximum 1 every 6 hours"), 43200 => t("Maximum 1 every 12 hours")); @@ -254,32 +265,12 @@ function system_view($type, $arg = "") { return form($form); } -function system_dirscan($dir, $mask, $nomask = array(".", "..", "CVS")) { - $files = array(); - if (is_dir($dir) && $handle = opendir($dir)) { - while ($file = readdir($handle)) { - if (!in_array($file, $nomask)) { - if (is_dir("$dir/$file")) { - $files = array_merge($files, system_dirscan("$dir/$file", $mask, $nomask)); - } - elseif (ereg($mask, $file)) { - $name = basename($file); - $files["$dir/$file"]->filename = "$dir/$file"; - $files["$dir/$file"]->name = substr($name, 0, strrpos($name, '.')); - } - } - } - closedir($handle); - } - return $files; -} - function system_listing($type, $directory, $required = array()) { // Make sure we set $type correctly $type = $type != 'theme' ? "module" : "theme"; // Find files in the directory. - $files = system_dirscan($directory, "\.$type$"); + $files = file_scan_directory($directory, "\.$type$"); // Extract current files from database. $result = db_query("SELECT filename, type, status, throttle FROM {system} WHERE type = '%s'", $type); diff --git a/modules/system/system.module b/modules/system/system.module index 5ac19cc54e52..af45d64f6abc 100644 --- a/modules/system/system.module +++ b/modules/system/system.module @@ -35,8 +35,7 @@ function system_help($section = "admin/help#system") { // Start of system_help_cache $output .= "<p>Drupal has a caching mechanism which stores dynamically generated web pages in a database. By caching a web page, Drupal does not have to create the page each time someone wants to view it, instead it takes only one SQL query to display it, reducing response time and the server's load. Only pages requested by \"anonymous\" users are cached.</p>"; // End of system_help_cache - $output = t($output, array("%base_url" => $base_url, "%cron-link" => "<a href=\"$base_url/cron.php\ -\">$base_url/cron.php</a>", "%lynx" => "<a href=\"http://lynx.browser.org\">lynx</a>", "%wget" => "<a href=\"http://www.gnu.org/software/wget/wget.html\">wget</a>" )); + $output = t($output, array("%base_url" => $base_url, "%cron-link" => "<a href=\"$base_url/cron.php\">$base_url/cron.php</a>", "%lynx" => "<a href=\"http://lynx.browser.org\">lynx</a>", "%wget" => "<a href=\"http://www.gnu.org/software/wget/wget.html\">wget</a>" )); break; case 'admin/system/modules#description': $output = t("Configuration system that lets administrators modify the workings of the site."); @@ -56,6 +55,7 @@ function system_perm() { function system_link($type) { if ($type == "system") { + menu("system/files", t("file download"), "file_download", 0, MENU_HIDE); if (user_access("administer site configuration")) { menu("admin/system", t("configuration"), "system_admin", 3); @@ -126,6 +126,17 @@ function system_view_general() { $output .= form_group(t("Cache settings"), $group); + // file system: + if (!file_check_directory(variable_get('file_directory_path', 'files'))) { + $error['file_directory_path'] = theme('error', t('Directory does not exist, or is not writable.')); + } + if (!file_check_directory(variable_get('file_directory_temp', ini_get('upload_tmp_dir')))) { + $error['file_directory_temp'] = theme('error', t('Directory does not exist, or is not writable.')); + } + $group = form_textfield(t('File system path'), 'file_directory_path', variable_get('file_directory_path', 'files'), 70, 255, t('A file system path where the files will be stored. This directory has to exist and be writable by Drupal. If the download method is set to public this directory has to be relative to Drupal installation directory, and be accessible over the web. When download method is set to private this directory should not be accessible over the web. Changing this location after the site has been in use will cause problems so only change this setting on an existing site if you know what you are doing.') . $error['file_directory_path']); + $group .= form_textfield(t('Temporary directory'), 'file_directory_temp', variable_get('file_directory_temp', (PHP_OS == 'WINNT' ? 'c:\\windows\\temp' : '/tmp')), 70, 255, t('Location where files can be saved temporarily. This directory should not be accessible from the web.') . $error['file_directory_temp']); + $group .= form_radios(t('Download method'), 'file_downloads', variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC), array(FILE_DOWNLOADS_PUBLIC => t('Public - files are available using http directly.'), FILE_DOWNLOADS_PRIVATE => t('Private - files are be transferred by Drupal.')), t('This setting can be changed at any time, however, all download URLs will change and there may be unexpected problems so it is not recommended.')); + $output .= form_group(t('File system'), $group); // submission settings: $rate = array(-10000 => t("Disabled"), 1 => t("Maximum 1 every second"), 5 => t("Maximum 1 every 5 seconds"), 15 => t("Maximum 1 every 15 seconds"), 30 => t("Maximum 1 every 30 seconds"), 60 => t("Maximum 1 every minute"), 300 => t("Maximum 1 every 5 minutes"), 900 => t("Maximum 1 every 15 minutes"), 1800 => t("Maximum 1 every 30 minutes"), 3600 => t("Maximum 1 every hour"), 21600 => t("Maximum 1 every 6 hours"), 43200 => t("Maximum 1 every 12 hours")); @@ -254,32 +265,12 @@ function system_view($type, $arg = "") { return form($form); } -function system_dirscan($dir, $mask, $nomask = array(".", "..", "CVS")) { - $files = array(); - if (is_dir($dir) && $handle = opendir($dir)) { - while ($file = readdir($handle)) { - if (!in_array($file, $nomask)) { - if (is_dir("$dir/$file")) { - $files = array_merge($files, system_dirscan("$dir/$file", $mask, $nomask)); - } - elseif (ereg($mask, $file)) { - $name = basename($file); - $files["$dir/$file"]->filename = "$dir/$file"; - $files["$dir/$file"]->name = substr($name, 0, strrpos($name, '.')); - } - } - } - closedir($handle); - } - return $files; -} - function system_listing($type, $directory, $required = array()) { // Make sure we set $type correctly $type = $type != 'theme' ? "module" : "theme"; // Find files in the directory. - $files = system_dirscan($directory, "\.$type$"); + $files = file_scan_directory($directory, "\.$type$"); // Extract current files from database. $result = db_query("SELECT filename, type, status, throttle FROM {system} WHERE type = '%s'", $type); -- GitLab