#686060 by Crell, David_Rothstein, dww, yoroy, carlos8f, et al: Fixed Explain that the Update manager only works if you have FTP or SSH access to your server
parent
bfcdaf0607
commit
81f6ecd362
|
@ -194,7 +194,12 @@ function authorize_filetransfer_form_validate($form, &$form_state) {
|
|||
$filetransfer->connect();
|
||||
}
|
||||
catch (Exception $e) {
|
||||
form_set_error('connection_settings', $e->getMessage());
|
||||
// The format of this error message is similar to that used on the
|
||||
// database connection form in the installer.
|
||||
form_set_error('connection_settings', t('Failed to connect to the server. The server reports the following message: !message For more help installing or updating code on your server, see the <a href="@handbook_url">handbook</a>.', array(
|
||||
'!message' => '<p class="error">' . $e->getMessage() . '</p>',
|
||||
'@handbook_url' => 'http://drupal.org/documentation/install/modules-themes',
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,3 +112,40 @@ function update_test_archiver_info() {
|
|||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_filetransfer_info().
|
||||
*/
|
||||
function update_test_filetransfer_info() {
|
||||
// Define a mock file transfer method, to ensure that there will always be
|
||||
// at least one method available in the user interface (regardless of the
|
||||
// environment in which the update manager tests are run).
|
||||
return array(
|
||||
'system_test' => array(
|
||||
'title' => t('Update Test FileTransfer'),
|
||||
// This should be in an .inc file, but for testing purposes, it is OK to
|
||||
// leave it in the main module file.
|
||||
'file' => 'update_test.module',
|
||||
'class' => 'UpdateTestFileTransfer',
|
||||
'weight' => -20,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock FileTransfer object to test the settings form functionality.
|
||||
*/
|
||||
class UpdateTestFileTransfer {
|
||||
public static function factory() {
|
||||
return new UpdateTestFileTransfer;
|
||||
}
|
||||
|
||||
public function getSettingsForm() {
|
||||
$form = array();
|
||||
$form['udpate_test_username'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Update Test Username'),
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,10 @@
|
|||
* The form array for selecting which projects to update.
|
||||
*/
|
||||
function update_manager_update_form($form, $form_state = array(), $context) {
|
||||
if (!_update_manager_check_backends($form, 'update')) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$form['#theme'] = 'update_manager_update_form';
|
||||
|
||||
$available = update_get_available(TRUE);
|
||||
|
@ -354,6 +358,10 @@ function update_manager_download_batch_finished($success, $results) {
|
|||
* file transfer credentials and attempt to complete the update.
|
||||
*/
|
||||
function update_manager_update_ready_form($form, &$form_state) {
|
||||
if (!_update_manager_check_backends($form, 'update')) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$form['backup'] = array(
|
||||
'#prefix' => '<strong>',
|
||||
'#markup' => t('Back up your database and site before you continue. <a href="@backup_url">Learn how</a>.', array('@backup_url' => url('http://drupal.org/node/22281'))),
|
||||
|
@ -461,11 +469,18 @@ function update_manager_update_ready_form_submit($form, &$form_state) {
|
|||
* The form array for selecting which project to install.
|
||||
*/
|
||||
function update_manager_install_form($form, &$form_state, $context) {
|
||||
$form = array();
|
||||
if (!_update_manager_check_backends($form, 'install')) {
|
||||
return $form;
|
||||
}
|
||||
|
||||
$form['help_text'] = array(
|
||||
'#prefix' => '<p>',
|
||||
'#markup' => t('To install a new module or theme, either enter the URL of an archive file you wish to install, or upload the archive file that you have downloaded. You can find <a href="@module_url">modules</a> and <a href="@theme_url">themes</a> at <a href="@drupal_org_url">http://drupal.org</a>.<br/>The following archive extensions are supported: %extensions.', array('@module_url' => 'http://drupal.org/project/modules', '@theme_url' => 'http://drupal.org/project/themes', '@drupal_org_url' => 'http://drupal.org', '%extensions' => archiver_get_extensions())),
|
||||
'#markup' => t('You can find <a href="@module_url">modules</a> and <a href="@theme_url">themes</a> on <a href="@drupal_org_url">drupal.org</a>. The following file extensions are supported: %extensions.', array(
|
||||
'@module_url' => 'http://drupal.org/project/modules',
|
||||
'@theme_url' => 'http://drupal.org/project/themes',
|
||||
'@drupal_org_url' => 'http://drupal.org',
|
||||
'%extensions' => archiver_get_extensions(),
|
||||
)),
|
||||
'#suffix' => '</p>',
|
||||
);
|
||||
|
||||
|
@ -496,6 +511,73 @@ function update_manager_install_form($form, &$form_state, $context) {
|
|||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for file transfer backends and prepares a form fragment about them.
|
||||
*
|
||||
* @param array $form
|
||||
* Reference to the form array we're building.
|
||||
* @param string $operation
|
||||
* The Update manager operation we're in the middle of. Can be either
|
||||
* 'update' or 'install'. Use to provide operation-specific interface text.
|
||||
*
|
||||
* @return
|
||||
* TRUE if the Update manager should continue to the next step in the
|
||||
* workflow, or FALSE if we've hit a fatal configuration and must halt the
|
||||
* workflow.
|
||||
*/
|
||||
function _update_manager_check_backends(&$form, $operation) {
|
||||
// If file transfers will be performed locally, we do not need to display any
|
||||
// warnings or notices to the user and should automatically continue the
|
||||
// workflow, since we won't be using a FileTransfer backend that requires
|
||||
// user input or a specific server configuration.
|
||||
if (update_manager_local_transfers_allowed()) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Otherwise, show the available backends.
|
||||
$form['available_backends'] = array(
|
||||
'#prefix' => '<p>',
|
||||
'#suffix' => '</p>',
|
||||
);
|
||||
|
||||
$available_backends = drupal_get_filetransfer_info();
|
||||
if (empty($available_backends)) {
|
||||
if ($operation == 'update') {
|
||||
$form['available_backends']['#markup'] = t('Your server does not support updating modules and themes from this interface. Instead, update modules and themes by uploading the new versions directly to the server, as described in the <a href="@handbook_url">handbook</a>.', array('@handbook_url' => 'http://drupal.org/getting-started/install-contrib'));
|
||||
}
|
||||
else {
|
||||
$form['available_backends']['#markup'] = t('Your server does not support installing modules and themes from this interface. Instead, install modules and themes by uploading them directly to the server, as described in the <a href="@handbook_url">handbook</a>.', array('@handbook_url' => 'http://drupal.org/getting-started/install-contrib'));
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$backend_names = array();
|
||||
foreach ($available_backends as $backend) {
|
||||
$backend_names[] = $backend['title'];
|
||||
}
|
||||
if ($operation == 'update') {
|
||||
$form['available_backends']['#markup'] = format_plural(
|
||||
count($available_backends),
|
||||
'Updating modules and themes requires <strong>@backends access</strong> to your server. See the <a href="@handbook_url">handbook</a> for other update methods.',
|
||||
'Updating modules and themes requires access to your server via one of the following methods: <strong>@backends</strong>. See the <a href="@handbook_url">handbook</a> for other update methods.',
|
||||
array(
|
||||
'@backends' => implode(', ', $backend_names),
|
||||
'@handbook_url' => 'http://drupal.org/getting-started/install-contrib',
|
||||
));
|
||||
}
|
||||
else {
|
||||
$form['available_backends']['#markup'] = format_plural(
|
||||
count($available_backends),
|
||||
'Installing modules and themes requires <strong>@backends access</strong> to your server. See the <a href="@handbook_url">handbook</a> for other installation methods.',
|
||||
'Installing modules and themes requires access to your server via one of the following methods: <strong>@backends</strong>. See the <a href="@handbook_url">handbook</a> for other installation methods.',
|
||||
array(
|
||||
'@backends' => implode(', ', $backend_names),
|
||||
'@handbook_url' => 'http://drupal.org/getting-started/install-contrib',
|
||||
));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the form for installing a new project via the update manager.
|
||||
*/
|
||||
|
@ -811,6 +893,41 @@ function update_manager_batch_project_get($project, $url, &$context) {
|
|||
$context['finished'] = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if file transfers will be performed locally.
|
||||
*
|
||||
* If the server is configured such that webserver-created files have the same
|
||||
* owner as the configuration directory (e.g. sites/default) where new code
|
||||
* will eventually be installed, the Update manager can transfer files entirely
|
||||
* locally, without changing their ownership (in other words, without prompting
|
||||
* the user for FTP, SSH or other credentials).
|
||||
*
|
||||
* This server configuration is an inherent security weakness because it allows
|
||||
* a malicious webserver process to append arbitrary PHP code and then execute
|
||||
* it. However, it is supported here because it is a common configuration on
|
||||
* shared hosting, and there is nothing Drupal can do to prevent it.
|
||||
*
|
||||
* @return
|
||||
* TRUE if local file transfers are allowed on this server, or FALSE if not.
|
||||
*
|
||||
* @see update_manager_update_ready_form_submit()
|
||||
* @see update_manager_install_form_submit()
|
||||
* @see install_check_requirements()
|
||||
*/
|
||||
function update_manager_local_transfers_allowed() {
|
||||
// Compare the owner of a webserver-created temporary file to the owner of
|
||||
// the configuration directory to determine if local transfers will be
|
||||
// allowed.
|
||||
$temporary_file = drupal_tempnam('temporary://', 'update_');
|
||||
$local_transfers_allowed = fileowner($temporary_file) === fileowner(conf_path());
|
||||
|
||||
// Clean up. If this fails, we can ignore it (since this is just a temporary
|
||||
// file anyway).
|
||||
@drupal_unlink($temporary_file);
|
||||
|
||||
return $local_transfers_allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @} End of "defgroup update_manager_file".
|
||||
*/
|
||||
|
|
|
@ -622,9 +622,9 @@ class UpdateTestUploadCase extends UpdateTestHelper {
|
|||
function testFileNameExtensionMerging() {
|
||||
$this->drupalGet('admin/modules/install');
|
||||
// Make sure the bogus extension supported by update_test.module is there.
|
||||
$this->assertPattern('/archive extensions are supported:.*update-test-extension/', t("Found 'update-test-extension' extension"));
|
||||
$this->assertPattern('/file extensions are supported:.*update-test-extension/', t("Found 'update-test-extension' extension"));
|
||||
// Make sure it didn't clobber the first option from core.
|
||||
$this->assertPattern('/archive extensions are supported:.*tar/', t("Found 'tar' extension"));
|
||||
$this->assertPattern('/file extensions are supported:.*tar/', t("Found 'tar' extension"));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue