Page Menu
Home
In-Portal Phabricator
Search
Configure Global Search
Log In
Files
F800398
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:06 AM
Size
13 KB
Mime Type
text/x-diff
Expires
Mon, Feb 24, 12:06 AM (1 h, 37 m)
Engine
blob
Format
Raw Data
Handle
573654
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 15425)
+++ branches/5.2.x/core/units/helpers/curl_helper.php (revision 15426)
@@ -1,519 +1,531 @@
<?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;
+ 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->options = Array ();
}
/**
* 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,
// don't verify SSL certificates
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
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');
$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;
return strlen($header);
}
/**
* Sets request data for next query
*
* @param mixed $data Array or string
*/
public function SetRequestData($data)
{
if ( is_array($data) ) {
$params_str = '';
$data = $this->Application->HttpQuery->_transformArrays($data);
foreach ($data as $key => $value) {
$params_str .= $key . '=' . urlencode($value) . '&';
}
$data = $params_str;
}
$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
*/
public function SetRequestMethod($request_method)
{
if ($request_method != self::REQUEST_METHOD_GET || $request_method != self::REQUEST_METHOD_POST) {
throw new Exception('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 = '')
+ public function Send($url, $close_connection = true, $log_status = NULL, $log_message = '')
{
if ( isset($log_status) ) {
// override debug mode setting
$this->debugMode = $log_status;
}
$this->connectionID = curl_init($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->execFollow();
+ $this->lastResponse = $this->_sendRequest();
$this->Finalize($close_connection);
return $this->lastResponse;
}
/**
- * Fixes curl inability to automatically follow location when safe_mode/open_basedir restriction in effect
+ * Reads data from remote url
*
- * @param bool $headers_only
* @return string
* @access protected
*/
- protected function execFollow($headers_only = false)
+ protected function _sendRequest()
{
- curl_setopt($this->connectionID, CURLOPT_HEADER, true);
curl_setopt($this->connectionID, CURLOPT_RETURNTRANSFER, true);
- if ( $this->followLocation && !$this->followLocationLimited() ) {
- // no restrictions - let curl do automatic redirects
- curl_setopt($this->connectionID, CURLOPT_FOLLOWLOCATION, 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 ( isset($url_parsed) ) {
curl_setopt($this->connectionID, CURLOPT_URL, $url);
$this->lastRedirectCount++;
- return $this->execFollow($headers_only);
+ return $this->_followLocationManually();
}
}
- if ( $headers_only ) {
- return $data;
- }
-
list(, $body) = explode("\r\n\r\n", $data, 2);
return $body;
}
/**
* 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);
}
/**
* 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)
{
$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