diff --git a/feeds_ui/feeds_ui.admin.inc b/feeds_ui/feeds_ui.admin.inc index 97ba6e71d3c04c7688afa3e2b522b46ded02d8a1..56c44204b46d872b09db419eee6c2f2e9a68491e 100644 --- a/feeds_ui/feeds_ui.admin.inc +++ b/feeds_ui/feeds_ui.admin.inc @@ -303,6 +303,7 @@ function feeds_ui_edit_page($importer, $active = 'help', $plugin_key = '') { $active_container['body'] = drupal_get_form('feeds_ui_plugin_form', $importer, $active); break; case 'settings': + drupal_add_js(drupal_get_path('module', 'feeds_ui') .'/feeds_ui.js'); if (empty($plugin_key)) { $active_container['title'] = t('Basic settings'); $active_container['body'] = feeds_get_config_form($importer); diff --git a/feeds_ui/feeds_ui.js b/feeds_ui/feeds_ui.js index 9908320fde2bb4aa4f11167b97ba9914a186f48b..17b38d724c63c9b627f5ba157351ddde8774a96a 100644 --- a/feeds_ui/feeds_ui.js +++ b/feeds_ui/feeds_ui.js @@ -87,4 +87,25 @@ Drupal.behaviors.feeds = function() { $('#' + $(this).attr('id')).attr('checked', 1); $('input.form-submit.feeds-ui-hidden-submit').click(); }); + + // Show basic auth u/pw conditionally. + // @todo Generalize dependencies between form elements. + if ($('#edit-basic-auth-2').attr('checked')) { + $('#edit-basic-auth-user-wrapper').show(); + $('#edit-basic-auth-password-wrapper').show(); + } + else { + $('#edit-basic-auth-user-wrapper').hide(); + $('#edit-basic-auth-password-wrapper').hide(); + } + $('#edit-basic-auth-2').click(function() { + if ($(this).attr('checked')) { + $('#edit-basic-auth-user-wrapper').show(100); + $('#edit-basic-auth-password-wrapper').show(100); + } + }); + $('#edit-basic-auth-0,#edit-basic-auth-1').click(function() { + $('#edit-basic-auth-user-wrapper').hide(100); + $('#edit-basic-auth-password-wrapper').hide(100); + }); }; diff --git a/plugins/FeedsHTTPFetcher.inc b/plugins/FeedsHTTPFetcher.inc index 0467ca6466213731ad2b201d983cff664bbe77b5..75925dd289279e06b38f133df7658335993b425e 100644 --- a/plugins/FeedsHTTPFetcher.inc +++ b/plugins/FeedsHTTPFetcher.inc @@ -6,6 +6,10 @@ * Home of the FeedsHTTPFetcher and related classes. */ +define('FEEDS_HTTP_NO_BASIC_AUTH', 0); +define('FEEDS_HTTP_BASIC_AUTH_PER_SOURCE', 1); +define('FEEDS_HTTP_BASIC_AUTH_PER_IMPORTER', 2); + /** * Definition of the import batch object created on the fetching stage by * FeedsHTTPFetcher. @@ -59,7 +63,9 @@ class FeedsHTTPFetcher extends FeedsFetcher { */ public function fetch(FeedsSource $source) { $source_config = $source->getConfigFor($this); - return new FeedsHTTPBatch($source_config['source']); + $url = $source_config['source']; + $url = $this->basicAuth($url, isset($source_config['basic_auth']) ? $source_config['basic_auth'] : array()); + return new FeedsHTTPBatch($url); } /** @@ -85,6 +91,16 @@ class FeedsHTTPFetcher extends FeedsFetcher { '#maxlength' => NULL, '#required' => TRUE, ); + if (isset($this->config['basic_auth']) && $this->config['basic_auth'] == FEEDS_HTTP_BASIC_AUTH_PER_SOURCE) { + $form['basic_auth'] = array( + '#type' => 'fieldset', + '#collapsible' => TRUE, + '#collapsed' => empty($source_config['basic_auth']['basic_auth_user']), + '#title' => t('Authentication'), + '#description' => t('Enter user name and password for authentication. Leave empty if no authentication is required.'), + ); + $form['basic_auth'] += $this->basicAuthForm(isset($source_config['basic_auth']) ? $source_config['basic_auth'] : array()); + } return $form; } @@ -92,7 +108,87 @@ class FeedsHTTPFetcher extends FeedsFetcher { * Override parent::configDefaults(). */ public function configDefaults() { - return array('auto_detect_feeds' => FALSE); + return array( + 'basic_auth' => FEEDS_HTTP_NO_BASIC_AUTH, + 'basic_auth_user' => '', + 'basic_auth_password' => '', + ); + } + + /** + * Override parent::configForm(); + */ + public function configForm() { + $form = array(); + $form['basic_auth'] = array( + '#type' => 'fieldset', + '#title' => t('HTTP Basic Authentication'), + ); + $form['basic_auth']['basic_auth'] = array( + '#type' => 'radios', + '#options' => array( + FEEDS_HTTP_NO_BASIC_AUTH => t('No authentication'), + FEEDS_HTTP_BASIC_AUTH_PER_SOURCE => t('Specify credentials when creating a feed.'), + FEEDS_HTTP_BASIC_AUTH_PER_IMPORTER => t('One set of credentials for all feeds.'), + ), + '#default_value' => $this->config['basic_auth'], + ); + $form['basic_auth'] += $this->basicAuthForm($this->config); + return $form; + } + + /** + * Validate config form. + */ + public function configFormValidate(&$values) { + // Don't accidentally wipe out password. + if (empty($values['basic_auth_password'])) { + $values['basic_auth_password'] = $this->config['basic_auth_password']; + } + if ($values['basic_auth'] != FEEDS_HTTP_BASIC_AUTH_PER_IMPORTER) { + $values['basic_auth_user'] = ''; + $values['basic_auth_password'] = ''; + } + } + + /** + * Basic auth form. + */ + protected function basicAuthForm($config) { + $form = array(); + $form['basic_auth_user'] = array( + '#type' => 'textfield', + '#title' => t('Username'), + '#default_value' => empty($config['basic_auth_user']) ? '' : $config['basic_auth_user'], + ); + $form['basic_auth_password'] = array( + '#type' => 'password', + '#title' => t('Password'), + ); + return $form; + } + + /** + * Encode basic authentication credentials in URL depending on configuration. + */ + protected function basicAuth($url, $source_config = array()) { + if ($this->config['basic_auth'] == FEEDS_HTTP_BASIC_AUTH_PER_SOURCE) { + if (!empty($source_config['basic_auth_user']) && !empty($source_config['basic_auth_password'])) { + return $this->basicAuthEncodeCredentials($url, $source_config['basic_auth_user'], $source_config['basic_auth_password']); + } + } + elseif ($this->config['basic_auth'] == FEEDS_HTTP_BASIC_AUTH_PER_IMPORTER) { + return $this->basicAuthEncodeCredentials($url, $this->config['basic_auth_user'], $this->config['basic_auth_password']); + } + return $url; + } + + /** + * Encode basic authentication credentials into URL. + */ + protected function basicAuthEncodeCredentials($url, $user, $password) { + $parsed = parse_url($url); + return str_replace("{$parsed['scheme']}://", "{$parsed['scheme']}://$user:$password@", $url); } }