summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--INSTALL.txt11
-rw-r--r--includes/common.inc20
-rw-r--r--includes/xmlrpc.inc1
-rw-r--r--modules/aggregator/aggregator.module7
-rw-r--r--modules/openid/openid.module11
-rw-r--r--modules/system/system.install8
-rw-r--r--modules/system/system.module35
-rw-r--r--modules/update/update.fetch.inc3
8 files changed, 90 insertions, 6 deletions
diff --git a/INSTALL.txt b/INSTALL.txt
index 21ae39917..59bc86054 100644
--- a/INSTALL.txt
+++ b/INSTALL.txt
@@ -37,6 +37,17 @@ you will need PHP's XML extension. This extension is enabled by default.
- If you want support for clean URLs, you'll need mod_rewrite and the ability
to use local .htaccess files.
+- Various Drupal features require that the web server process (for
+ example, httpd) needs to be able to initiate outbound connections.
+ This is usually possible, but some hosting providers or server
+ configurations forbid such connections. The features that depend on
+ this functionality include the integrated "Update status" module
+ which downloads information about available updates of Drupal core
+ and any installed contributed modules and themes, the ability to log
+ in via OpenID, fetching aggregator feeds, or use other
+ network-dependent services.
+
+
INSTALLATION
------------
diff --git a/includes/common.inc b/includes/common.inc
index 82de30b39..ecbc3dfff 100644
--- a/includes/common.inc
+++ b/includes/common.inc
@@ -415,7 +415,23 @@ function drupal_access_denied() {
* data and redirect status.
*/
function drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
+ static $self_test = FALSE;
$result = new stdClass();
+ // Try to clear the drupal_http_request_fails variable if it's set. We
+ // can't tie this call to any error because there is no surefire way to
+ // tell whether a request has failed, so we add the check to places where
+ // some parsing has failed.
+ if (!$self_test && variable_get('drupal_http_request_fails', FALSE)) {
+ $self_test = TRUE;
+ $works = module_invoke('system', 'check_http_request');
+ $self_test = FALSE;
+ if (!$works) {
+ // Do not bother with further operations if we already know that we
+ // have no chance.
+ $result->error = t("The server can't issue HTTP requests");
+ return $result;
+ }
+ }
// Parse the URL and make sure we can handle the schema.
$uri = parse_url($url);
@@ -439,8 +455,8 @@ function drupal_http_request($url, $headers = array(), $method = 'GET', $data =
// Make sure the socket opened properly.
if (!$fp) {
- // When a network error occurs, we make sure that it is a negative number so
- // it can clash with the HTTP status codes.
+ // When a network error occurs, we use a negative number so it does not
+ // clash with the HTTP status codes.
$result->code = -$errno;
$result->error = trim($errstr);
return $result;
diff --git a/includes/xmlrpc.inc b/includes/xmlrpc.inc
index ebd19c461..6dd79b8c3 100644
--- a/includes/xmlrpc.inc
+++ b/includes/xmlrpc.inc
@@ -350,6 +350,7 @@ function xmlrpc_error($code = NULL, $message = NULL) {
$xmlrpc_error->is_error = TRUE;
$xmlrpc_error->code = $code;
$xmlrpc_error->message = $message;
+ module_invoke('system', 'check_http_request');
}
return $xmlrpc_error;
}
diff --git a/modules/aggregator/aggregator.module b/modules/aggregator/aggregator.module
index 02128a2bf..add89541a 100644
--- a/modules/aggregator/aggregator.module
+++ b/modules/aggregator/aggregator.module
@@ -600,7 +600,7 @@ function aggregator_refresh($feed) {
case 301:
$feed['url'] = $result->redirect_url;
watchdog('aggregator', 'Updated URL for feed %title to %url.', array('%title' => $feed['title'], '%url' => $feed['url']));
-
+ // Deliberate no break.
case 200:
case 302:
case 307:
@@ -648,11 +648,14 @@ function aggregator_refresh($feed) {
watchdog('aggregator', 'There is new syndicated content from %site.', array('%site' => $feed['title']));
drupal_set_message(t('There is new syndicated content from %site.', array('%site' => $feed['title'])));
+ break;
}
- break;
+ $result->error = t('feed not parseable');
+ // Deliberate no break.
default:
watchdog('aggregator', 'The feed from %site seems to be broken, due to "%error".', array('%site' => $feed['title'], '%error' => $result->code .' '. $result->error), WATCHDOG_WARNING);
drupal_set_message(t('The feed from %site seems to be broken, because of error "%error".', array('%site' => $feed['title'], '%error' => $result->code .' '. $result->error)));
+ module_invoke('system', 'check_http_request');
}
}
diff --git a/modules/openid/openid.module b/modules/openid/openid.module
index cf58a9fbb..7e7114caa 100644
--- a/modules/openid/openid.module
+++ b/modules/openid/openid.module
@@ -290,6 +290,9 @@ function openid_discovery($claimed_id) {
}
}
}
+ if (!$services) {
+ module_invoke('system', 'check_http_request');
+ }
return $services;
}
@@ -321,12 +324,14 @@ function openid_association($op_endpoint) {
$assoc_headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
$assoc_result = drupal_http_request($op_endpoint, $assoc_headers, 'POST', $assoc_message);
if (isset($assoc_result->error)) {
+ module_invoke('system', 'check_http_request');
return FALSE;
}
$assoc_response = _openid_parse_message($assoc_result->data);
if (isset($assoc_response['mode']) && $assoc_response['mode'] == 'error') {
- return FALSE;
+ module_invoke('system', 'check_http_request');
+ return FALSE;
}
if ($assoc_response['session_type'] == 'DH-SHA1') {
@@ -487,6 +492,8 @@ function openid_verify_assertion($op_endpoint, $response) {
}
}
}
-
+ if (!$valid) {
+ module_invoke('system', 'check_http_request');
+ }
return $valid;
}
diff --git a/modules/system/system.install b/modules/system/system.install
index c50f01770..e2fdf6382 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -241,6 +241,14 @@ function system_requirements($phase) {
$requirements['update status'] = array(
'value' => $t('Enabled'),
);
+ if (variable_get('drupal_http_request_fails', FALSE)) {
+ $requirements['http requests'] = array(
+ 'title' => $t('HTTP request status'),
+ 'value' => $t('Fails'),
+ 'severity' => REQUIREMENT_ERROR,
+ 'description' => $t('Your system or network configuration does not allow Drupal to access web pages, resulting in reduced functionality. This could be due to your webserver configuration or PHP settings, and should be resolved in order to download information about available updates, fetch aggregator feeds, sign in via OpenID, or use other network-dependent services.'),
+ );
+ }
}
$requirements['update status']['title'] = $t('Update notifications');
}
diff --git a/modules/system/system.module b/modules/system/system.module
index ff8f7a0ed..4328a38ba 100644
--- a/modules/system/system.module
+++ b/modules/system/system.module
@@ -445,6 +445,15 @@ function system_menu() {
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
+ // Menu handler to test that drupal_http_request() works locally.
+ // @see system_check_http_request().
+ $items['admin/reports/request-test'] = array(
+ 'title' => 'Request test',
+ 'page callback' => 'printf',
+ 'page arguments' => array('request test'),
+ 'access callback' => TRUE,
+ 'type' => MENU_CALLBACK,
+ );
// Reports:
$items['admin/reports'] = array(
@@ -1812,6 +1821,32 @@ function _system_zonelist() {
}
/**
+ * Checks whether the server is capable of issuing HTTP requests.
+ *
+ * The function sets the drupal_http_request_fail system variable to TRUE if
+ * drupal_http_request() does not work and then the system status report page
+ * will contain an error.
+ *
+ * @return
+ * Whether the admin/reports/request-test page can be requested via HTTP
+ * and contains the same output as if called via the menu system.
+ */
+function system_check_http_request() {
+ // Check whether we can do any request at all. First get the results for
+ // a very simple page which has access TRUE set via the menu system. Then,
+ // try to drupal_http_request() the same page and compare.
+ ob_start();
+ $path = 'admin/reports/request-test';
+ menu_execute_active_handler($path);
+ $nothing = ob_get_contents();
+ ob_end_clean();
+ $result = drupal_http_request(url($path, array('absolute' => TRUE)));
+ $works = isset($result->data) && $result->data == $nothing;
+ variable_set('drupal_http_request_fails', !$works);
+ return $works;
+}
+
+/**
* Format the Powered by Drupal text.
*
* @ingroup themeable
diff --git a/modules/update/update.fetch.inc b/modules/update/update.fetch.inc
index a79e71c3a..4ecdbc235 100644
--- a/modules/update/update.fetch.inc
+++ b/modules/update/update.fetch.inc
@@ -42,12 +42,15 @@ function _update_refresh() {
if ($data) {
$parser = new update_xml_parser;
$available = $parser->parse($data);
+ }
+ if (!empty($available) && is_array($available)) {
$frequency = variable_get('update_check_frequency', 1);
cache_set('update_info', $available, 'cache_update', time() + (60 * 60 * 24 * $frequency));
variable_set('update_last_check', time());
watchdog('update', 'Fetched information about all available new releases and updates.', array(), WATCHDOG_NOTICE, l('view', 'admin/reports/updates'));
}
else {
+ module_invoke('system', 'check_http_request');
watchdog('update', 'Unable to fetch any information about available new releases and updates.', array(), WATCHDOG_ERROR, l('view', 'admin/reports/updates'));
}
return $available;