diff --git a/application/utils.inc.php b/application/utils.inc.php index fec1fd4a6..8f83ef7fd 100644 --- a/application/utils.inc.php +++ b/application/utils.inc.php @@ -886,6 +886,7 @@ class utils * @param string $sUrl The URL to POST the data to * @param hash $aData The data to POST as an array('param_name' => value) * @param string $sOptionnalHeaders Additional HTTP headers as a string with newlines between headers + * @param hash $aResponseHeaders An array to be filled with reponse headers: WARNING: the actual content of the array depends on the library used: cURL or fopen, test with both !! See: http://fr.php.net/manual/en/function.curl-getinfo.php * @return string The result of the POST request * @throws Exception */ @@ -893,47 +894,110 @@ class utils { // $sOptionnalHeaders is a string containing additional HTTP headers that you would like to send in your request. - $sData = http_build_query($aData); - - $aParams = array('http' => array( - 'method' => 'POST', - 'content' => $sData, - 'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n", - )); - if ($sOptionnalHeaders !== null) + if (function_exists('curl_init')) { - $aParams['http']['header'] .= $sOptionnalHeaders; - } - $ctx = stream_context_create($aParams); - - $fp = @fopen($sUrl, 'rb', false, $ctx); - if (!$fp) - { - global $php_errormsg; - if (isset($php_errormsg)) + // If cURL is available, let's use it, since it provides a greater control over the various HTTP/SSL options + // For instance fopen does not allow to work around the bug: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112 + // by setting the SSLVERSION to 3 as done below. + $aHeaders = explode("\n", $sOptionnalHeaders); + $aHTTPHeaders = array(); + foreach($aHeaders as $sHeaderString) { - throw new Exception("Wrong URL: $sUrl, $php_errormsg"); + if(preg_match('/^([^:]): (.+)$/', $sHeaderString, $aMatches)) + { + $aHTTPHeaders[$aMatches[1]] = $aMatches[2]; + } } - elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl')) + $aOptions = array( + CURLOPT_RETURNTRANSFER => true, // return the content of the request + CURLOPT_HEADER => false, // don't return the headers in the output + CURLOPT_FOLLOWLOCATION => true, // follow redirects + CURLOPT_ENCODING => "", // handle all encodings + CURLOPT_USERAGENT => "spider", // who am i + CURLOPT_AUTOREFERER => true, // set referer on redirect + CURLOPT_CONNECTTIMEOUT => 120, // timeout on connect + CURLOPT_TIMEOUT => 120, // timeout on response + CURLOPT_MAXREDIRS => 10, // stop after 10 redirects + CURLOPT_SSL_VERIFYPEER => false, // Disabled SSL Cert checks + CURLOPT_SSLVERSION => 3, // MUST to prevent a strange SSL error: http://stackoverflow.com/questions/18191672/php-curl-ssl-routinesssl23-get-server-helloreason1112 + CURLOPT_POST => count($aData), + CURLOPT_POSTFIELDS => http_build_query($aData), + CURLOPT_HTTPHEADER => $aHTTPHeaders, + ); + + $ch = curl_init($sUrl); + curl_setopt_array($ch, $aOptions); + $response = curl_exec($ch); + $iErr = curl_errno($ch); + $sErrMsg = curl_error( $ch ); + $aHeaders = curl_getinfo( $ch ); + if ($iErr !== 0) { - throw new Exception("Cannot connect to $sUrl: missing module 'openssl'"); + throw new Exception("Problem opening URL: $sUrl, $sErrMsg"); } - else + if (is_array($aResponseHeaders)) { - throw new Exception("Wrong URL: $sUrl"); + $aHeaders = curl_getinfo($ch); + foreach($aHeaders as $sCode => $sValue) + { + $sName = str_replace(' ' , '-', ucwords(str_replace('_', ' ', $sCode))); // Transform "content_type" into "Content-Type" + $aResponseHeaders[$sName] = $sValue; + } } + curl_close( $ch ); } - $response = @stream_get_contents($fp); - if ($response === false) + else { - throw new Exception("Problem reading data from $sUrl, $php_errormsg"); - } - if (is_array($aResponseHeaders)) - { - $aMeta = stream_get_meta_data($fp); - $aResponseHeaders = $aMeta['wrapper_data']; + // cURL is not available let's try with streams and fopen... + + $sData = http_build_query($aData); + $aParams = array('http' => array( + 'method' => 'POST', + 'content' => $sData, + 'header'=> "Content-type: application/x-www-form-urlencoded\r\nContent-Length: ".strlen($sData)."\r\n", + )); + if ($sOptionnalHeaders !== null) + { + $aParams['http']['header'] .= $sOptionnalHeaders; + } + $ctx = stream_context_create($aParams); + + $fp = @fopen($sUrl, 'rb', false, $ctx); + if (!$fp) + { + global $php_errormsg; + if (isset($php_errormsg)) + { + throw new Exception("Wrong URL: $sUrl, $php_errormsg"); + } + elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl')) + { + throw new Exception("Cannot connect to $sUrl: missing module 'openssl'"); + } + else + { + throw new Exception("Wrong URL: $sUrl"); + } + } + $response = @stream_get_contents($fp); + if ($response === false) + { + throw new Exception("Problem reading data from $sUrl, $php_errormsg"); + } + if (is_array($aResponseHeaders)) + { + $aMeta = stream_get_meta_data($fp); + $aHeaders = $aMeta['wrapper_data']; + foreach($aHeaders as $sHeaderString) + { + if(preg_match('/^([^:]+): (.+)$/', $sHeaderString, $aMatches)) + { + $aResponseHeaders[$aMatches[1]] = trim($aMatches[2]); + } + } + } } return $response; } } -?> \ No newline at end of file +?>