Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F800465
in-portal
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Feb 22, 12:07 AM
Size
14 KB
Mime Type
text/x-diff
Expires
Mon, Feb 24, 12:07 AM (1 h, 49 m)
Engine
blob
Format
Raw Data
Handle
573719
Attached To
rINP In-Portal
in-portal
View Options
Index: branches/5.2.x/core/units/helpers/curl_helper.php
===================================================================
--- branches/5.2.x/core/units/helpers/curl_helper.php (revision 16750)
+++ branches/5.2.x/core/units/helpers/curl_helper.php (revision 16751)
@@ -1,573 +1,586 @@
<?php
/**
* @version $Id$
* @package In-Portal
* @copyright Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/
defined('FULL_PATH') or die('restricted access!');
class kCurlHelper extends kHelper {
const REQUEST_METHOD_GET = 1;
const REQUEST_METHOD_POST = 2;
/**
* ID of database record of currently active curl request
*
* @var int
* @access protected
*/
protected $logId = 0;
/**
* Connection to host
*
* @var resource
* @access protected
*/
protected $connectionID = NULL;
/**
* Response waiting timeout in seconds
*
* @var int
* @access public
*/
public $timeout = 90;
/**
* Follow to url, if redirect received instead of document (only works when open_basedir and safe mode is off)
*
* @var bool
* @access public
*/
public $followLocation = false;
/**
* Last response received by Curl
*
* @var string
* @access public
*/
public $lastResponse = '';
/**
* Last error code
*
* @var int
* @access public
*/
public $lastErrorCode = 0;
/**
* Last error message
*
* @var string
* @access public
*/
public $lastErrorMsg = '';
/**
* Most recent HTTP response code received
*
* @var int
* @access public
*/
public $lastHTTPCode = 0;
/**
* Count of intermediate redirects performed to get actual content
*
* @var int
* @access protected
*/
protected $lastRedirectCount = 0;
/**
* Default request method
*
* @var int
* @access protected
*/
protected $requestMethod = self::REQUEST_METHOD_GET;
/**
* Data to be sent using curl
*
* @var string
* @access protected
*/
protected $requestData = '';
/**
* Request headers (associative array)
*
* @var Array
* @access protected
*/
protected $requestHeaders = Array ();
/**
* Response headers
*
* @var Array
* @access protected
*/
protected $responseHeaders = Array ();
/**
* CURL options
*
* @var Array
* @access protected
*/
protected $options = Array ();
/**
* Indicates debug mode status
*
* @var bool
* @access public
*/
public $debugMode = false;
/**
* Creates an instance of kCurlHelper class
*/
public function __construct()
{
parent::__construct();
$this->debugMode = kUtil::constOn('DBG_CURL');
}
/**
* Reset connection settings (not results) after connection was closed
*
* @access protected
*/
protected function _resetSettings()
{
$this->timeout = 90;
$this->followLocation = false;
$this->requestMethod = self::REQUEST_METHOD_GET;
$this->requestData = '';
$this->requestHeaders = Array ();
+ $this->responseHeaders = Array ();
$this->options = Array ();
}
/**
* Resets information in last* properties.
*
* @return void
*/
protected function resetLastInfo()
{
$this->lastErrorCode = 0;
$this->lastErrorMsg = '';
$this->lastHTTPCode = 0;
$this->lastRedirectCount = 0;
}
/**
* Sets CURL options (adds to options set before)
*
* @param Array $options_hash
* @access public
*/
public function setOptions($options_hash)
{
$this->options = kUtil::array_merge_recursive($this->options, $options_hash);
}
/**
* Combines user-defined and default options before setting them to CURL
*
* @access protected
*/
protected function prepareOptions()
{
$default_options = Array (
// customizable options
CURLOPT_TIMEOUT => $this->timeout,
// hardcoded options
CURLOPT_RETURNTRANSFER => 1,
CURLOPT_REFERER => PROTOCOL.SERVER_NAME,
CURLOPT_MAXREDIRS => 5,
// don't verify SSL certificates
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
// Prevents CURL from adding "Expect: 100-continue" header for POST requests.
CURLOPT_HTTPHEADER => Array ('Expect:'),
);
if ( isset($_SERVER['HTTP_USER_AGENT']) ) {
$default_options[CURLOPT_USERAGENT] = $_SERVER['HTTP_USER_AGENT'];
}
if ($this->requestHeaders) {
$default_options[CURLOPT_HTTPHEADER] = $this->prepareHeaders();
}
// if we have post data, then POST else use GET method instead
if ($this->requestMethod == self::REQUEST_METHOD_POST) {
$default_options[CURLOPT_POST] = 1;
$default_options[CURLOPT_POSTFIELDS] = $this->requestData;
}
-// $default_options[CURLOPT_HEADERFUNCTION] = Array(&$this, 'ParseHeader');
+ $default_options[CURLOPT_HEADERFUNCTION] = array(&$this, 'ParseHeader');
$user_options = $this->options; // backup options, that user set directly
$this->setOptions($default_options);
$this->setOptions($user_options);
$this->applyOptions();
}
/**
* Sets prepared options to CURL
*
* @access protected
*/
protected function applyOptions()
{
foreach ($this->options as $option_name => $option_value) {
curl_setopt($this->connectionID, $option_name, $option_value);
}
}
/**
* Parses headers from CURL request
*
* @param resource $ch
* @param string $header
* @return int
* @access protected
*/
protected function ParseHeader(&$ch, $header)
{
- $this->responseHeaders[] = $header;
+ $trimmed_header = rtrim($header);
+
+ if ( $trimmed_header ) {
+ $this->responseHeaders[] = $trimmed_header;
+ }
return strlen($header);
}
/**
* Sets request data for next query
*
* @param mixed $data Array or string
*/
public function SetRequestData($data)
{
if ( is_array($data) ) {
$data = http_build_query($data);
}
$this->requestData = $data;
}
/**
* Sets request data for next query and switches request method to POST
*
* @param mixed $data Array or string
* @access public
*/
public function SetPostData($data)
{
$this->requestMethod = self::REQUEST_METHOD_POST;
$this->SetRequestData($data);
}
/**
* Sets request method to be used in next request
*
* @param int $request_method
*
* @throws InvalidArgumentException When invalid request method given.
*/
public function SetRequestMethod($request_method)
{
if ($request_method != self::REQUEST_METHOD_GET && $request_method != self::REQUEST_METHOD_POST) {
throw new InvalidArgumentException('Method "' . __METHOD__ . '": Invalid $request_method parameter value');
return ;
}
$this->requestMethod = $request_method;
}
/**
* Sets headers to be sent along with next query
*
* @param Array $headers
* @access public
*/
public function SetHeaders($headers)
{
$this->requestHeaders = array_merge($this->requestHeaders, $headers);
}
/**
* Returns compiled header to be used by curl
*
* @return Array
* @access protected
*/
protected function prepareHeaders()
{
$ret = Array ();
foreach ($this->requestHeaders as $header_name => $header_value) {
$ret[] = is_numeric($header_name) ? $header_value : $header_name . ': ' . $header_value;
}
return $ret;
}
/**
* Performs CURL request and returns it's result
*
* @param string $url
* @param bool $close_connection
* @param bool $log_status
* @param string $log_message
* @return string
* @access public
*/
public function Send($url, $close_connection = true, $log_status = NULL, $log_message = '')
{
if ( isset($log_status) ) {
// override debug mode setting
$this->debugMode = $log_status;
}
$request_url = $url;
if ( $this->requestMethod == self::REQUEST_METHOD_GET && $this->requestData ) {
$request_url .= (strpos($request_url, '?') !== false ? '&' : '?') . $this->requestData;
}
$this->connectionID = curl_init($request_url);
if ( $this->debugMode ) {
// collect page data
$page_data = Array ();
if ( $_GET ) {
$page_data[] = '_GET:' . "\n" . print_r($_GET, true);
}
if ( $_POST ) {
$page_data[] = '_POST:' . "\n" . print_r($_POST, true);
}
if ( $_COOKIE ) {
$page_data[] = '_COOKIE:' . "\n" . print_r($_COOKIE, true);
}
// create log record
$fields_hash = Array (
'Message' => $log_message,
'PageUrl' => $_SERVER['REQUEST_URI'],
'RequestUrl' => $url,
'PortalUserId' => $this->Application->RecallVar('user_id'),
'SessionKey' => $this->Application->GetSID(),
'IsAdmin' => $this->Application->isAdminUser ? 1 : 0,
'PageData' => implode("\n", $page_data),
'RequestData' => $this->requestData,
'RequestDate' => adodb_mktime(),
);
$this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'CurlLog');
$this->logId = $this->Conn->getInsertID();
}
- $this->responseHeaders = Array ();
-
$this->prepareOptions();
$this->lastResponse = $this->_sendRequest();
$this->Finalize($close_connection);
return $this->lastResponse;
}
/**
* Reads data from remote url
*
* @return string
* @access protected
*/
protected function _sendRequest()
{
$this->resetLastInfo();
curl_setopt($this->connectionID, CURLOPT_RETURNTRANSFER, true);
if ( $this->followLocation ) {
if ( $this->followLocationLimited() ) {
return $this->_followLocationManually();
}
else {
// no restrictions - let curl do automatic redirects
curl_setopt($this->connectionID, CURLOPT_FOLLOWLOCATION, true);
}
}
return curl_exec($this->connectionID);
}
/**
* Fixes curl inability to automatically follow location when safe_mode/open_basedir restriction in effect
*
* @return string
* @access protected
*/
protected function _followLocationManually()
{
curl_setopt($this->connectionID, CURLOPT_HEADER, true);
$data = curl_exec($this->connectionID);
$http_code = $this->getInfo(CURLINFO_HTTP_CODE);
if ( $http_code == 301 || $http_code == 302 ) {
// safe more or open_basedir restriction - do redirects manually
list ($header) = explode("\r\n\r\n", $data, 2);
preg_match('/(Location:|URI:)(.*?)\n/', $header, $regs);
$url = trim(array_pop($regs));
$url_parsed = parse_url($url);
if ( $this->lastRedirectCount == $this->options[CURLOPT_MAXREDIRS] ) {
return $this->setError(CURLE_TOO_MANY_REDIRECTS, 'Maximum (' . $this->options[CURLOPT_MAXREDIRS] . ') redirects followed');
}
if ( isset($url_parsed) ) {
curl_setopt($this->connectionID, CURLOPT_URL, $url);
$this->lastRedirectCount++;
return $this->_followLocationManually();
}
}
list(, $body) = explode("\r\n\r\n", $data, 2);
return $body;
}
/**
* Sets error manually.
*
* @param integer $code Code.
* @param string $message Message.
*
* @return boolean
*/
protected function setError($code, $message)
{
$this->lastErrorCode = $code;
$this->lastErrorMsg = $message;
return false;
}
/**
* Returns various info about request made
*
* @param int $info_type
* @return mixed
*
* @see http://www.php.net/manual/ru/function.curl-getinfo.php
* @access public
*/
public function getInfo($info_type)
{
if ( $info_type == CURLINFO_REDIRECT_COUNT && $this->followLocationLimited() ) {
return $this->lastRedirectCount;
}
return curl_getinfo($this->connectionID, $info_type);
}
/**
+ * Returns response headers.
+ *
+ * @return array
+ */
+ public function getResponseHeaders()
+ {
+ return $this->responseHeaders;
+ }
+
+ /**
* Detects, that follow location can't be done automatically by curl due safe_mode/open_basedir restrictions
*
* @return bool
* @access protected
*/
protected function followLocationLimited()
{
return (defined('SAFE_MODE') && SAFE_MODE) || ini_get('open_basedir');
}
/**
* Finalizes curl request and saves some data from curl before closing connection
*
* @param bool $close_connection
* @return void
* @access public
*/
public function Finalize($close_connection = true)
{
if ( $this->lastErrorCode == 0 ) {
// error not set manually -> get it from curl
$this->lastErrorCode = curl_errno($this->connectionID);
$this->lastErrorMsg = curl_error($this->connectionID);
}
$this->lastHTTPCode = $this->getInfo(CURLINFO_HTTP_CODE);
if ( $close_connection ) {
$this->CloseConnection();
}
$this->_resetSettings();
}
/**
* Closes connection to server
*
* @access public
*/
public function CloseConnection()
{
curl_close($this->connectionID);
if ( $this->debugMode ) {
$fields_hash = Array (
'ResponseData' => $this->lastResponse,
'ResponseDate' => adodb_mktime(),
'ResponseHttpCode' => $this->lastHTTPCode,
'CurlError' => $this->lastErrorCode != 0 ? '#' . $this->lastErrorCode . ' (' . $this->lastErrorMsg . ')' : '',
);
$this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'CurlLog', 'LogId = ' . $this->logId);
}
// restore debug mode setting
$this->debugMode = kUtil::constOn('DBG_CURL');
}
/**
* Checks, that last curl request was successful
*
* @return bool
* @access public
*/
public function isGoodResponseCode()
{
if ( $this->lastErrorCode != 0 ) {
return false;
}
return ($this->lastHTTPCode == 200) || ($this->lastHTTPCode >= 300 && $this->lastHTTPCode < 310);
}
- }
\ No newline at end of file
+ }
Event Timeline
Log In to Comment