浏览代码

Improved version of DoPostRequest which optionally uses cURL to workaround PHP/OpenSSL bugs !

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2972 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 11 年之前
父节点
当前提交
33be18aec0
共有 1 个文件被更改,包括 95 次插入31 次删除
  1. 95 31
      application/utils.inc.php

+ 95 - 31
application/utils.inc.php

@@ -886,6 +886,7 @@ class utils
 	 * @param string $sUrl The URL to POST the data to
 	 * @param string $sUrl The URL to POST the data to
 	 * @param hash $aData The data to POST as an array('param_name' => value)
 	 * @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 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
 	 * @return string The result of the POST request
 	 * @throws Exception
 	 * @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.
 		// $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;
+			// 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)
+			{
+				if(preg_match('/^([^:]): (.+)$/', $sHeaderString, $aMatches))
+				{
+					$aHTTPHeaders[$aMatches[1]] = $aMatches[2];
+				}
+			}
+			$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("Problem opening URL: $sUrl, $sErrMsg");
+			}
+			if (is_array($aResponseHeaders))
+			{
+				$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 );
 		}
 		}
-		$ctx = stream_context_create($aParams);
-	
-		$fp = @fopen($sUrl, 'rb', false, $ctx);
-		if (!$fp)
+		else
 		{
 		{
-			global $php_errormsg;
-			if (isset($php_errormsg))
+			// 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)
 			{
 			{
-				throw new Exception("Wrong URL: $sUrl, $php_errormsg");
+				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");
+				}
 			}
 			}
-			elseif ((strtolower(substr($sUrl, 0, 5)) == 'https') && !extension_loaded('openssl'))
+			$response = @stream_get_contents($fp);
+			if ($response === false)
 			{
 			{
-				throw new Exception("Cannot connect to $sUrl: missing module 'openssl'");
+				throw new Exception("Problem reading data from $sUrl, $php_errormsg");
 			}
 			}
-			else
+			if (is_array($aResponseHeaders))
 			{
 			{
-				throw new Exception("Wrong URL: $sUrl");
+				$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]);
+					}
+				}
 			}
 			}
 		}
 		}
-		$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);
-			$aResponseHeaders = $aMeta['wrapper_data'];
-		}
 		return $response;
 		return $response;
 	}
 	}
 }
 }
-?>
+?>