Commit 167e70ba authored by webchick's avatar webchick

Issue #1496480 by mrf, disasm, kbasarab, pfrenssen, cam8001, typhonius,...

Issue #1496480 by mrf, disasm, kbasarab, pfrenssen, cam8001, typhonius, Letharion, ACF, vijaycs85, heyrocker, Berdir, alexpott: Convert file system settings to the new configuration system.
parent 79da95b2
......@@ -315,7 +315,7 @@ function file_uri_target($uri) {
* 'public', 'private' or any other file scheme defined as the default.
*/
function file_default_scheme() {
return variable_get('file_default_scheme', 'public');
return config('system.file')->get('default_scheme');
}
/**
......@@ -520,7 +520,8 @@ function file_prepare_directory(&$directory, $options = FILE_MODIFY_PERMISSIONS)
*/
function file_ensure_htaccess() {
file_save_htaccess('public://', FALSE);
if (variable_get('file_private_path', FALSE)) {
$private_path = config('system.file')->get('path.private');
if (!empty($private_path)) {
file_save_htaccess('private://', TRUE);
}
file_save_htaccess('temporary://', TRUE);
......@@ -789,10 +790,9 @@ function file_unmanaged_move($source, $destination = NULL, $replace = FILE_EXIST
* between 2 and 5 characters in length, internal to the file name, and not
* included in $extensions.
*
* Function behavior is also controlled by the Drupal variable
* 'allow_insecure_uploads'. If 'allow_insecure_uploads' evaluates to TRUE, no
* alterations will be made, if it evaluates to FALSE, the filename is 'munged'.
*
* Function behavior is also controlled by the configuration
* 'system.file:allow_insecure_uploads'. If it evaluates to TRUE, no alterations
* will be made, if it evaluates to FALSE, the filename is 'munged'. *
* @param $filename
* File name to modify.
* @param $extensions
......@@ -801,14 +801,14 @@ function file_unmanaged_move($source, $destination = NULL, $replace = FILE_EXIST
* If TRUE, drupal_set_message() will be called to display a message if the
* file name was changed.
*
* @return
* @return string
* The potentially modified $filename.
*/
function file_munge_filename($filename, $extensions, $alerts = TRUE) {
$original = $filename;
// Allow potentially insecure uploads for very savvy users and admin
if (!variable_get('allow_insecure_uploads', 0)) {
if (!config('system.file')->get('allow_insecure_uploads')) {
// Remove any null bytes. See http://php.net/manual/en/security.filesystem.nullbytes.php
$filename = str_replace(chr(0), '', $filename);
......@@ -1144,7 +1144,7 @@ function file_save_upload($source, $validators = array(), $destination = FALSE,
// rename filename.php.foo and filename.php to filename.php.foo.txt and
// filename.php.txt, respectively). Don't rename if 'allow_insecure_uploads'
// evaluates to TRUE.
if (!variable_get('allow_insecure_uploads', 0) && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
if (!config('system.file')->get('allow_insecure_uploads') && preg_match('/\.(php|pl|py|cgi|asp|js)(\.|$)/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
$file->filemime = 'text/plain';
$file->uri .= '.txt';
$file->filename .= '.txt';
......@@ -1512,13 +1512,13 @@ function file_get_mimetype($uri, $mapping = NULL) {
/**
* Sets the permissions on a file or directory.
*
* This function will use the 'file_chmod_directory' and 'file_chmod_file'
* variables for the default modes for directories and uploaded/generated
* files. By default these will give everyone read access so that users
* accessing the files with a user account without the webserver group (e.g.
* via FTP) can read these files, and give group write permissions so webserver
* group members (e.g. a vhost account) can alter files uploaded and owned by
* the webserver.
* This function will use the system.file:chmod.directory and
* system.file:chmod.file configuration for the default modes for directories
* and uploaded/generated files. By default these will give everyone read access
* so that users accessing the files with a user account without the webserver
* group (e.g. via FTP) can read these files, and give group write permissions
* so webserver group members (e.g. a vhost account) can alter files uploaded
* and owned by the webserver.
*
* PHP's chmod does not support stream wrappers so we use our wrapper
* implementation which interfaces with chmod() by default. Contrib wrappers
......@@ -1530,18 +1530,27 @@ function file_get_mimetype($uri, $mapping = NULL) {
* Integer value for the permissions. Consult PHP chmod() documentation for
* more information.
*
* @return
* @return bool
* TRUE for success, FALSE in the event of an error.
*
* @ingroup php_wrappers
*/
function drupal_chmod($uri, $mode = NULL) {
if (!isset($mode)) {
// Configuration system stores default modes as strings. We use octdec() so
// that the octal permission numbers can be expressed as integers or strings
// and will be converted correctly in both cases.
if (is_dir($uri)) {
$mode = variable_get('file_chmod_directory', 0775);
$mode = octdec(config('system.file')->get('chmod.directory'));
if (!$mode) {
$mode = 0775;
}
}
else {
$mode = variable_get('file_chmod_file', 0664);
$mode = octdec(config('system.file')->get('chmod.file'));
if (!$mode) {
$mode = 0664;
}
}
}
......@@ -1718,7 +1727,11 @@ function drupal_basename($uri, $suffix = NULL) {
*/
function drupal_mkdir($uri, $mode = NULL, $recursive = FALSE, $context = NULL) {
if (!isset($mode)) {
$mode = variable_get('file_chmod_directory', 0775);
// Configuration system stores default mode as strings.
$mode = octdec(config('system.file')->get('chmod.directory'));
if (!$mode) {
$mode = 0775;
}
}
if (!isset($context)) {
......@@ -1801,36 +1814,16 @@ function drupal_tempnam($directory, $prefix) {
}
/**
* Gets the path of system-appropriate temporary directory.
* Gets and sets the path of the configured temporary directory.
*
* @return mixed|null
* A string containing the path to the temporary directory.
*/
function file_directory_temp() {
$temporary_directory = variable_get('file_temporary_path', NULL);
$config = config('system.file');
$temporary_directory = $config->get('path.temporary');
if (empty($temporary_directory)) {
$directories = array();
// Has PHP been set with an upload_tmp_dir?
if (ini_get('upload_tmp_dir')) {
$directories[] = ini_get('upload_tmp_dir');
}
// Operating system specific dirs.
if (substr(PHP_OS, 0, 3) == 'WIN') {
$directories[] = 'c:\\windows\\temp';
$directories[] = 'c:\\winnt\\temp';
}
else {
$directories[] = '/tmp';
}
// PHP may be able to find an alternative tmp directory.
$directories[] = sys_get_temp_dir();
foreach ($directories as $directory) {
if (is_dir($directory) && is_writable($directory)) {
$temporary_directory = $directory;
break;
}
}
$temporary_directory = file_directory_os_temp();
if (empty($temporary_directory)) {
// If no directory has been found default to 'files/tmp'.
......@@ -1843,12 +1836,45 @@ function file_directory_temp() {
$temporary_directory = str_replace('\\', '/', $temporary_directory);
}
// Save the path of the discovered directory.
variable_set('file_temporary_path', $temporary_directory);
$config->set('path.temporary', $temporary_directory)->save();
}
return $temporary_directory;
}
/**
* Discovers a writable system-appropriate temporary directory.
*
* @return mixed
* A string containing the path to the temporary directory.
*/
function file_directory_os_temp() {
$directories = array();
// Has PHP been set with an upload_tmp_dir?
if (ini_get('upload_tmp_dir')) {
$directories[] = ini_get('upload_tmp_dir');
}
// Operating system specific dirs.
if (substr(PHP_OS, 0, 3) == 'WIN') {
$directories[] = 'c:\\windows\\temp';
$directories[] = 'c:\\winnt\\temp';
}
else {
$directories[] = '/tmp';
}
// PHP may be able to find an alternative tmp directory.
$directories[] = sys_get_temp_dir();
foreach ($directories as $directory) {
if (is_dir($directory) && is_writable($directory)) {
return $directory;
}
}
return FALSE;
}
/**
* @} End of "defgroup file".
*/
......@@ -1296,9 +1296,23 @@ function install_find_translations() {
* @see file_scan_directory()
*/
function install_find_translation_files($langcode = NULL) {
$directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
$files = file_scan_directory($directory, '!drupal-\d+\.\d+\.' . (!empty($langcode) ? preg_quote($langcode, '!') : '[^\.]+') . '\.po$!', array('recurse' => FALSE));
return $files;
return file_scan_directory(install_translation_directory(), '!drupal-\d+\.\d+\.' . (!empty($langcode) ? preg_quote($langcode, '!') : '[^\.]+') . '\.po$!', array('recurse' => FALSE));
}
/**
* Get installation translations directory path.
*
* @return string
* A string containing the installation translations directory path.
*/
function install_translation_directory() {
if (isset($GLOBALS['conf']['locale.settings']['translation.path'])) {
$directory = $GLOBALS['conf']['locale.settings']['translation.path'];
}
else {
$directory = conf_path() . '/files/translations';
}
return $directory;
}
/**
......@@ -1862,8 +1876,9 @@ function install_check_translations($install_state) {
$readable = FALSE;
$writable = FALSE;
$files_directory = variable_get('file_public_path', conf_path() . '/files');
$translations_directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
// @todo: Make this configurable.
$files_directory = conf_path() . '/files';
$translations_directory = conf_path() . '/files/translations';
$translations_directory_exists = FALSE;
$online = FALSE;
$server_available = FALSE;
......
......@@ -19,7 +19,7 @@ class PrivateStream extends LocalStream {
* Implements Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath()
*/
public function getDirectoryPath() {
return variable_get('file_private_path', '');
return config('system.file')->get('path.private');
}
/**
......
......@@ -19,7 +19,7 @@ class TemporaryStream extends LocalStream {
* Implements Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath()
*/
public function getDirectoryPath() {
return variable_get('file_temporary_path', file_directory_temp());
return file_directory_temp();
}
/**
......
......@@ -19,7 +19,7 @@ function file_field_info() {
'settings' => array(
'display_field' => 0,
'display_default' => 0,
'uri_scheme' => variable_get('file_default_scheme', 'public'),
'uri_scheme' => file_default_scheme(),
),
'instance_settings' => array(
'file_extensions' => 'txt',
......
......@@ -27,6 +27,6 @@ public static function getInfo() {
function setUp() {
parent::setUp();
variable_set('file_default_scheme', 'dummy-remote');
config('system.file')->set('default_scheme', 'dummy-remote')->save();
}
}
......@@ -180,6 +180,7 @@ function testHandleExtension() {
* Test dangerous file handling.
*/
function testHandleDangerousFile() {
$config = config('system.file');
// Allow the .php extension and make sure it gets renamed to .txt for
// safety. Also check to make sure its MIME type was changed.
$edit = array(
......@@ -201,7 +202,7 @@ function testHandleDangerousFile() {
// Ensure dangerous files are not renamed when insecure uploads is TRUE.
// Turn on insecure uploads.
variable_set('allow_insecure_uploads', 1);
$config->set('allow_insecure_uploads', 1)->save();
// Reset the hook counters.
file_test_reset();
......@@ -215,7 +216,7 @@ function testHandleDangerousFile() {
$this->assertFileHooksCalled(array('validate', 'insert'));
// Turn off insecure uploads.
variable_set('allow_insecure_uploads', 0);
$config->set('allow_insecure_uploads', 0)->save();
}
/**
......@@ -223,7 +224,7 @@ function testHandleDangerousFile() {
*/
function testHandleFileMunge() {
// Ensure insecure uploads are disabled for this test.
variable_set('allow_insecure_uploads', 0);
config('system.file')->set('allow_insecure_uploads', 0)->save();
$this->image = file_move($this->image, $this->image->uri . '.foo.' . $this->image_extension);
// Reset the hook counters to get rid of the 'move' we just called.
......
......@@ -16,7 +16,7 @@
*/
class DummyStreamWrapper extends LocalStream {
function getDirectoryPath() {
return variable_get('stream_public_path', 'sites/default/files');
return 'sites/default/files';
}
/**
......
......@@ -17,7 +17,7 @@ function image_field_info() {
'label' => t('Image'),
'description' => t('This field stores the ID of an image file as an integer value.'),
'settings' => array(
'uri_scheme' => variable_get('file_default_scheme', 'public'),
'uri_scheme' => file_default_scheme(),
'default_image' => 0,
),
'instance_settings' => array(
......
......@@ -92,7 +92,7 @@ function _testImageStyleUrlAndPath($scheme, $clean_url = TRUE) {
// Make the default scheme neither "public" nor "private" to verify the
// functions work for other than the default scheme.
variable_set('file_default_scheme', 'temporary');
config('system.file')->set('default_scheme', 'temporary')->save();
// Create the directories for the styles.
$directory = $scheme . '://styles/' . $this->style_name;
......
......@@ -6,4 +6,4 @@ translation:
overwrite_customized: false
overwrite_not_customized: true
update_interval_days: '0'
path: ''
......@@ -85,7 +85,7 @@ function setUp() {
private function setTranslationsDirectory($path) {
$this->tranlations_directory = $path;
file_prepare_directory($path, FILE_CREATE_DIRECTORY);
variable_set('locale_translate_file_directory', $path);
config('locale.settings')->set('translation.path', $path)->save();
}
/**
......
......@@ -20,8 +20,7 @@ class TranslationsStream extends LocalStream {
* Implements Drupal\Core\StreamWrapper\LocalStream::getDirectoryPath()
*/
function getDirectoryPath() {
return variable_get('locale_translate_file_directory',
conf_path() . '/files/translations');
return config('locale.settings')->get('translation.path');
}
/**
......
......@@ -329,7 +329,7 @@ function locale_translation_batch_fetch_import($project, $langcode, $options, &$
// files should be kept locally, they will be moved to the local
// translations after successfull import. Otherwise the temporary
// file is deleted after being imported.
if ($import_type == LOCALE_TRANSLATION_DOWNLOADED && variable_get('locale_translate_file_directory', conf_path() . '/files/translations') && isset($source_result->files[LOCALE_TRANSLATION_LOCAL])) {
if ($import_type == LOCALE_TRANSLATION_DOWNLOADED && config('locale.settings')->get('translation.path') && isset($source_result->files[LOCALE_TRANSLATION_LOCAL])) {
if (file_unmanaged_move($file->uri, $source_result->files[LOCALE_TRANSLATION_LOCAL]->uri, FILE_EXISTS_REPLACE)) {
// The downloaded file is now moved to the local file location.
// From this point forward we can treat it as if we imported a
......
......@@ -346,19 +346,19 @@ function locale_translate_get_interface_translation_files($projects = array(), $
// containing a project name and language code: {project}.{langcode}.po or
// {project}-{version}.{langcode}.po.
// Only files of known projects and languages will be returned.
if ($directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations')) {
$result = file_scan_directory($directory, '![a-z_]+(\-[0-9a-z\.\-\+]+|)\.[^\./]+\.po$!', array('recurse' => FALSE));
foreach ($result as $filepath => $file) {
// Update the file object with project name and version from the file name.
$file = locale_translate_file_attach_properties($file);
if (in_array($file->project, $projects)) {
if (in_array($file->langcode, $langcodes)) {
$files[$file->uri] = $file;
}
$directory = config('locale.settings')->get('translation.path');
$result = file_scan_directory($directory, '![a-z_]+(\-[0-9a-z\.\-\+]+|)\.[^\./]+\.po$!', array('recurse' => FALSE));
foreach ($result as $file) {
// Update the file object with project name and version from the file name.
$file = locale_translate_file_attach_properties($file);
if (in_array($file->project, $projects)) {
if (in_array($file->langcode, $langcodes)) {
$files[$file->uri] = $file;
}
}
}
return $files;
}
......
......@@ -10,7 +10,10 @@
*/
function locale_install() {
// Create the interface translations directory and ensure it's writable.
$directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
if (!$directory = config('locale.settings')->get('translation.path')) {
$directory = conf_path() . '/files/translations';
config('locale.settings')->set('translation.path', $directory)->save();
}
file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
}
......@@ -969,6 +972,17 @@ function locale_update_8016() {
}
}
/**
* Moves locale translation directory settings from variable to config.
*
* @ingroup config_upgrade
*/
function locale_update_8017() {
update_variables_to_config('locale.settings', array(
'locale_translate_file_directory' => 'translation.path',
));
}
/**
* @} End of "addtogroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.
......
......@@ -808,10 +808,10 @@ function locale_translate_english() {
* Add interface translation directory setting to directories configuration.
*/
function locale_form_system_file_system_settings_alter(&$form, $form_state) {
$form['locale_translate_file_directory'] = array(
$form['translation_path'] = array(
'#type' => 'textfield',
'#title' => t('Interface translations directory'),
'#default_value' => variable_get('locale_translate_file_directory', conf_path() . '/files/translations'),
'#default_value' => config('locale.settings')->get('translation.path'),
'#maxlength' => 255,
'#description' => t('A local file system path where interface translation files will be stored.'),
'#after_build' => array('system_check_directory'),
......@@ -831,9 +831,13 @@ function locale_form_system_file_system_settings_alter(&$form, $form_state) {
* should be ignored. The old translation status is no longer valid.
*/
function locale_system_file_system_settings_submit(&$form, $form_state) {
if ($form['locale_translate_file_directory']['#default_value'] != $form_state['values']['locale_translate_file_directory']) {
if ($form['translation_path']['#default_value'] != $form_state['values']['translation_path']) {
locale_translation_clear_status();
}
config('locale.settings')
->set('translation.path', $form_state['values']['translation_path'])
->save();
}
/**
......
......@@ -508,7 +508,7 @@ function locale_translate_settings($form, &$form_state) {
'#default_value' => $config->get('translation.check_disabled_modules'),
);
if ($directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations')) {
if ($directory =config('locale.settings')->get('translation.path')) {
$description = t('Translation files are stored locally in the %path directory. You can change this directory on the <a href="@url">File system</a> configuration page.', array('%path' => $directory, '@url' => url('admin/config/media/file-system')));
}
else {
......
......@@ -256,7 +256,7 @@ function locale_translation_source_build($project, $langcode, $filename = NULL)
'filename' => locale_translation_build_server_pattern($source, basename($source->server_pattern)),
'uri' => locale_translation_build_server_pattern($source, $source->server_pattern),
);
if (variable_get('locale_translate_file_directory', conf_path() . '/files/translations')) {
if (config('locale.settings')->get('translation.path')) {
$files[LOCALE_TRANSLATION_LOCAL] = (object) array(
'project' => $project->name,
'langcode' => $langcode,
......
......@@ -46,7 +46,6 @@ function locale_test_locale_translation_projects_alter(&$projects) {
// Completely replace the project data with a set of test projects.
$base_url = url();
$files_url = variable_get('file_public_path', conf_path() . '/files');
$projects = array (
'drupal' => array (
'name' => 'drupal',
......
......@@ -143,6 +143,15 @@ abstract class TestBase {
*/
protected $originalSettings;
/**
* The public file directory for the test environment.
*
* This is set in TestBase::prepareEnvironment().
*
* @var string
*/
protected $public_files_directory;
/**
* Whether to die in case any test assertion fails.
*
......
......@@ -788,22 +788,25 @@ protected function setUp() {
// Reset the static batch to remove Simpletest's batch operations.
$batch = &batch_get();
$batch = array();
$variables = array(
'file_public_path' => $this->public_files_directory,
'file_private_path' => $this->private_files_directory,
'file_temporary_path' => $this->temp_files_directory,
'locale_translate_file_directory' => $this->translation_files_directory,
$variable_groups = array(
'system.file' => array(
'path.private' => $this->private_files_directory,
'path.temporary' => $this->temp_files_directory,
),
'locale.settings' => array(
'translation.path' => $this->translation_files_directory,
),
);
foreach ($variables as $name => $value) {
$GLOBALS['conf'][$name] = $value;
foreach ($variable_groups as $config_base => $variables) {
foreach ($variables as $name => $value) {
NestedArray::setValue($GLOBALS['conf'], array_merge(array($config_base), explode('.', $name)), $value);
}
}
$GLOBALS['conf']['file_public_path'] = $this->public_files_directory;
// Execute the non-interactive installer.
require_once DRUPAL_ROOT . '/core/includes/install.core.inc';
install_drupal($settings);
$this->rebuildContainer();
foreach ($variables as $name => $value) {
variable_set($name, $value);
}
// Restore the original Simpletest batch.
$batch = &batch_get();
......@@ -838,6 +841,17 @@ protected function setUp() {
// Reset/rebuild all data structures after enabling the modules.
$this->resetAll();
// Now make sure that the file path configurations are saved. This is done
// after we install the modules to override default values.
foreach ($variable_groups as $config_base => $variables) {
$config = config($config_base);
foreach ($variables as $name => $value) {
$config->set($name, $value);
}
$config->save();
}
variable_set('file_public_path', $this->public_files_directory);
// Use the test mail class instead of the default mail handler class.
variable_set('mail_system', array('default-system' => 'Drupal\Core\Mail\VariableLog'));
......
allow_insecure_uploads: '0'
# chmod variables should be a string in PHP Octal Notation.
chmod:
directory: '0775'
file: '0664'
default_scheme: 'public'
path:
private: '0'
temporary: ''
......@@ -24,7 +24,10 @@ public static function getInfo() {
function setUp() {
parent::setUp();
variable_set('locale_translate_file_directory', drupal_get_path('module', 'simpletest') . '/files/translations');
// The database is not available during this part of install. Use global
// $conf to override the installation translations directory path.
global $conf;
$conf['locale.settings']['translation.path'] = drupal_get_path('module', 'simpletest') . '/files/translations';
}
/**
......
......@@ -32,7 +32,7 @@ function setUp() {
$conf['php_storage']['service_container']= array(
'bin' => 'service_container',
'class' => 'Drupal\Component\PhpStorage\MTimeProtectedFileStorage',
'directory' => DRUPAL_ROOT . '/' . variable_get('file_public_path', conf_path() . '/files') . '/php',
'directory' => DRUPAL_ROOT . '/' . $this->public_files_directory . '/php',
'secret' => $GLOBALS['drupal_hash_salt'],
);
// Use a non-persistent cache to avoid queries to non-existing tables.
......
......@@ -51,7 +51,7 @@ function testFileCheckDirectoryHandling() {
}
// Test that the directory has the correct permissions.
$this->assertDirectoryPermissions($directory, variable_get('file_chmod_directory', 0775));
$this->assertDirectoryPermissions($directory, octdec(config('system.file')->get('chmod.directory')));
// Remove .htaccess file to then test that it gets re-created.
@drupal_unlink(file_default_scheme() . '://.htaccess');
......@@ -122,10 +122,10 @@ function testFileDestination() {
*/
function testFileDirectoryTemp() {
// Start with an empty variable to ensure we have a clean slate.
variable_set('file_temporary_path', '');
$config = config('system.file');
$config->set('path.temporary', '')->save();
$tmp_directory = file_directory_temp();
$this->assertEqual(empty($tmp_directory), FALSE, 'file_directory_temp() returned a non-empty value.');
$setting = variable_get('file_temporary_path', '');
$this->assertEqual($setting, $tmp_directory, "The 'file_temporary_path' variable has the same value that file_directory_temp() returned.");
$this->assertEqual($config->get('path.temporary'), $tmp_directory);
}
}
......@@ -81,6 +81,11 @@ function assertSameFile($file1, $file2) {
* Optional message.
*/
function assertFilePermissions($filepath, $expected_mode, $message = NULL) {
// Configuration system stores default modes as strings.
if (is_string($expected_mode)) {
// Convert string to octal.
$expected_mode = octdec($expected_mode);
}
// Clear out PHP's file stat cache to be sure we see the current value.
clearstatcache(TRUE, $filepath);
......@@ -116,6 +121,11 @@ function assertFilePermissions($filepath, $expected_mode, $message = NULL) {
* Optional message.
*/
function assertDirectoryPermissions($directory, $expected_mode, $message = NULL) {