diff -u includes/authorize.inc includes/authorize.inc --- includes/authorize.inc 28 Oct 2009 00:03:28 -0000 +++ includes/authorize.inc 30 Oct 2009 00:04:51 -0000 @@ -19,12 +19,11 @@ $form['#attached']['js'][] = $base_url . '/misc/authorize.js'; // Get all the available ways to transfer files. - if (empty($_SESSION['authorize_filetransfer_backends'])) { + if (empty($_SESSION['authorize_filetransfer_info'])) { drupal_set_message(t('Unable to continue, no available methods of file transfer'), 'error'); return array(); } - $available_backends = $_SESSION['authorize_filetransfer_backends']; - uasort($available_backends, 'drupal_sort_weight'); + $available_backends = $_SESSION['authorize_filetransfer_info']; // Decide on a default backend. if (isset($form_state['values']['connection_settings']['authorize_filetransfer_default'])) { @@ -128,9 +127,16 @@ function _authorize_filetransfer_connection_settings($backend, array $info) { $defaults = variable_get('authorize_filetransfer_connection_settings_' . $backend, array()); $form = array(); + // Invoke the callback to get the settings form. - if (!empty($info['settings_form']) && function_exists($info['settings_form'])) { - $form = $info['settings_form'](); + if (!empty($info['settings form'])) { + if (!empty($info['settings form file'])) { + $file = $info['settings form path'] . '/' . $info['settings form file']; + require_once $file; + } + if (function_exists($info['settings form'])) { + $form = $info['settings form'](); + } } // Fill in the defaults based on the saved settings, if any. _authorize_filetransfer_connection_settings_set_defaults($form, NULL, $defaults); @@ -281,8 +287,8 @@ */ function authorize_get_filetransfer($backend, $settings = array()) { $filetransfer = FALSE; - if (!empty($_SESSION['authorize_filetransfer_backends'][$backend])) { - $filetransfer = call_user_func_array(array($_SESSION['authorize_filetransfer_backends'][$backend]['class'], 'factory'), array(DRUPAL_ROOT, $settings)); + if (!empty($_SESSION['authorize_filetransfer_info'][$backend])) { + $filetransfer = call_user_func_array(array($_SESSION['authorize_filetransfer_info'][$backend]['class'], 'factory'), array(DRUPAL_ROOT, $settings)); } return $filetransfer; } diff -u modules/system/system.module modules/system/system.module --- modules/system/system.module 27 Oct 2009 21:15:06 -0000 +++ modules/system/system.module 30 Oct 2009 00:42:09 -0000 @@ -1487,7 +1487,7 @@ * * @see authorize.php * @see FileTransfer - * @see hook_filetransfer_backends() + * @see hook_filetransfer_info() */ /** @@ -1518,7 +1518,7 @@ // First, figure out what file transfer backends the site supports, and put // all of those in the SESSION so that authorize.php has access to all of // them via the class autoloader, even without a full bootstrap. - $_SESSION['authorize_filetransfer_backends'] = module_invoke_all('filetransfer_backends'); + $_SESSION['authorize_filetransfer_info'] = drupal_get_filetransfer_info(); // Now, define the callback to invoke. $_SESSION['authorize_operation'] = array( @@ -1543,6 +1543,27 @@ } /** + * Helper function to return a form for configuring a filetransfer backend. + * + * @param string $filetransfer_backend_name + * The name of the backend to return a form for. + * + * @param string $defaults + * An associative array of settings to pre-populate the form with. + */ +function system_get_filetransfer_settings_form($filetransfer_backend_name, $defaults) { + $available_backends = module_invoke_all('filetransfer_backends'); + $form = call_user_func($available_backends[$filetransfer_backend_name]['settings_form']); + + foreach ($form as $name => &$element) { + if (isset($defaults[$name])) { + $element['#default_value'] = $defaults[$name]; + } + } + return $form; +} + +/** * Returns the form to configure the filetransfer class for FTP */ function system_filetransfer_backend_form_ftp() { @@ -1552,9 +1573,9 @@ } /** - * Implement hook_filetransfer_backends(). + * Implement hook_filetransfer_info(). */ -function system_filetransfer_backends() { +function system_filetransfer_info() { $backends = array(); // This is the default, will be available on most systems. @@ -1562,7 +1583,8 @@ $backends['ftp'] = array( 'title' => t('FTP'), 'class' => 'FileTransferFTP', - 'settings_form' => 'system_filetransfer_backend_form_ftp', + 'settings form' => 'system_filetransfer_settings_form_ftp', + 'settings form file' => 'system.filetransfer.inc', 'weight' => 0, ); } @@ -1573,7 +1595,8 @@ $backends['ssh'] = array( 'title' => t('SSH'), 'class' => 'FileTransferSSH', - 'settings_form' => 'system_filetransfer_backend_form_ssh', + 'settings form' => 'system_filetransfer_settings_form_ssh', + 'settings form file' => 'system.filetransfer.inc', 'weight' => 20, ); } @@ -1581,78 +1604,6 @@ } /** - * Helper function to return a form for configuring a filetransfer backend. - * - * @param string $filetransfer_backend_name - * The name of the backend to return a form for. - * - * @param string $defaults - * An associative array of settings to pre-populate the form with. - */ -function system_get_filetransfer_settings_form($filetransfer_backend_name, $defaults) { - $available_backends = module_invoke_all('filetransfer_backends'); - $form = call_user_func($available_backends[$filetransfer_backend_name]['settings_form']); - - foreach ($form as $name => &$element) { - if (isset($defaults[$name])) { - $element['#default_value'] = $defaults[$name]; - } - } - return $form; -} - -/** - * Returns the form to configure the filetransfer class for FTP - */ -function system_filetransfer_backend_form_ftp() { - $form = _system_filetransfer_backend_form_common(); - $form['advanced']['port']['#default_value'] = 21; - return $form; -} - -/** - * Returns the form to configure the filetransfer class for SSH - */ -function system_filetransfer_backend_form_ssh() { - $form = _system_filetransfer_backend_form_common(); - $form['advanced']['port']['#default_value'] = 22; - return $form; -} - -/** - * Helper function because SSH and FTP backends share the same elements - */ -function _system_filetransfer_backend_form_common() { - $form['username'] = array( - '#type' => 'textfield', - '#title' => t('Username'), - ); - $form['password'] = array( - '#type' => 'password', - '#title' => t('Password'), - '#description' => t('Your password is not saved in the database and is only used to establish a connection.'), - ); - $form['advanced'] = array( - '#type' => 'fieldset', - '#title' => t('Advanced settings'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - $form['advanced']['hostname'] = array( - '#type' => 'textfield', - '#title' => t('Host'), - '#default_value' => 'localhost', - '#description' => t('The connection will be created between your web server and the machine hosting the web server files. In the vast majority of cases, this will be the same machine, and "localhost" is correct.'), - ); - $form['advanced']['port'] = array( - '#type' => 'textfield', - '#title' => t('Port'), - '#default_value' => NULL, - ); - return $form; -} - -/** * Implement hook_init(). */ function system_init() { only in patch2: unchanged: --- authorize.php 29 Oct 2009 06:58:56 -0000 1.4 +++ authorize.php 30 Oct 2009 00:04:51 -0000 @@ -124,7 +124,7 @@ if (authorize_access_allowed()) { // Clear the session out. unset($_SESSION['authorize_results']); unset($_SESSION['authorize_operation']); - unset($_SESSION['authorize_filetransfer_backends']); + unset($_SESSION['authorize_filetransfer_info']); if (!empty($results['page_title'])) { drupal_set_title(check_plain($results['page_title'])); @@ -152,7 +152,7 @@ if (authorize_access_allowed()) { $output = _batch_page(); } else { - if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_backends'])) { + if (empty($_SESSION['authorize_operation']) || empty($_SESSION['authorize_filetransfer_info'])) { $output = t('It appears you have reached this page in error.'); } elseif (!$batch = batch_get()) { only in patch2: unchanged: --- includes/common.inc 27 Oct 2009 19:29:12 -0000 1.1031 +++ includes/common.inc 30 Oct 2009 00:07:50 -0000 @@ -6132,3 +6132,40 @@ function drupal_get_updaters() { } return $updaters; } + +/** + * Drupal FileTransfer registry. + * + * @return + * Returns the Drupal FileTransfer class registry. + * + * @see FileTransfer + * @see hook_filetransfer_info() + * @see hook_filetransfer_info_alter() + */ +function drupal_get_filetransfer_info() { + $info = &drupal_static(__FUNCTION__); + if (!isset($info)) { + // Since we have to manually set the 'settings form path' default for each + // module separately, we can't use module_invoke_all(). + $info = array(); + foreach (module_implements('filetransfer_info') as $module) { + $function = $module . '_filetransfer_info'; + if (function_exists($function)) { + $result = $function(); + if (isset($result) && is_array($result)) { + foreach ($result as &$values) { + if (empty($values['settings form path'])) { + $values['settings form path'] = drupal_get_path('module', $module); + } + } + $info = array_merge_recursive($info, $result); + } + } + } + drupal_alter('filetransfer_info', $info); + uasort($info, 'drupal_sort_weight'); + } + return $info; +} + only in patch2: unchanged: --- modules/system/system.api.php 24 Oct 2009 05:28:16 -0000 1.97 +++ modules/system/system.api.php 30 Oct 2009 01:01:31 -0000 @@ -2665,5 +2665,72 @@ function hook_url_outbound_alter(&$path, } /** + * Register information about FileTransfer classes provided by a module. + * + * The FileTransfer class allows transfering files over a specific type of + * connection. Core provides classes for FTP and SSH. Contributed modules are + * free to extend the FileTransfer base class to add other connection types, + * and if these classes are registered via hook_filetransfer_info(), those + * connection types will be available to site administrators using the Update + * manager when they are redirected to the authorize.php script to authorize + * the file operations. + * + * @return array + * Nested array of information about FileTransfer classes. Each key is a + * FileTransfer type (not human readable, used for form elements and + * variable names, etc), and the values are subarrays that define properties + * of that type. The keys in each subarray are: + * - 'title': Required. The human-readable name of the connection type. + * - 'class': Required. The name of the FileTransfer subclass. + * - 'settings form': Required. The name of a callback function that + * generates a Form API array of form elements presented to the user to + * enter their connection credentials. The form will have #tree = TRUE, and + * the nested values for these elements will be passed in to the class's + * factory() method when instantiating a FileTransfer object. + * - 'settings form file': Required. The include file containing the + * settings form callback function. This should be a separate .inc file, + * not just the .module file, so that the minimum possible code is loaded + * when authorize.php is running. + * - 'settings form path': Optional. The directory (relative to the Drupal + * root) where the settings form include file lives. If not defined, + * defaults to the base directory of the module implementing the hook. + * - 'weight': Optional. Integer weight used for sorting connection types on + * the authorize.php form. + * + * @see FileTransfer + * @see authorize.php + * @see drupal_get_filetransfer_info() + */ +function hook_filestransfer_info() { + $info['sftp'] = array( + 'title' => t('SFTP (Secure FTP)'), + 'class' => 'FileTransferSFTP', + 'settings form' => 'sftp_filetransfer_settings_form', + 'settings form file' => 'sftp.filetransfer_settings.inc', + 'weight' => 10, + ); + return $info; +} + +/** + * Alter the FileTransfer class registry. + * + * @param array $filetransfer_info + * Reference to a nested array containing information about the FileTransfer + * class registry. + * + * @see hook_filetransfer_info() + */ +function hook_filetransfer_info_alter(&$filetransfer_info) { + if (variable_get('paranoia', FALSE)) { + // Remove the FTP option entirely. + unset($filetransfer_info['ftp']); + // Make sure the SSH option is listed first. + $filetransfer_info['ssh']['weight'] = -10; + } +} + + +/** * @} End of "addtogroup hooks". */ only in patch2: unchanged: --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ modules/system/system.filetransfer.inc 30 Oct 2009 00:41:39 -0000 @@ -0,0 +1,65 @@ + 'textfield', + '#title' => t('Username'), + ); + $form['password'] = array( + '#type' => 'password', + '#title' => t('Password'), + '#description' => t('Your password is not saved in the database and is only used to establish a connection.'), + ); + $form['advanced'] = array( + '#type' => 'fieldset', + '#title' => t('Advanced settings'), + '#collapsible' => TRUE, + '#collapsed' => TRUE, + ); + $form['advanced']['hostname'] = array( + '#type' => 'textfield', + '#title' => t('Host'), + '#default_value' => 'localhost', + '#description' => t('The connection will be created between your web server and the machine hosting the web server files. In the vast majority of cases, this will be the same machine, and "localhost" is correct.'), + ); + $form['advanced']['port'] = array( + '#type' => 'textfield', + '#title' => t('Port'), + '#default_value' => NULL, + ); + return $form; +}