Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+42 -22
View File
@@ -11,7 +11,7 @@
namespace IPS\Http\Request;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -51,6 +51,11 @@ class _Sockets
* @brief Follow redirects?
*/
protected $followRedirects = TRUE;
/**
* @brief Allowed protocols
*/
protected $allowedProtocols = array();
/**
* Contructor
@@ -59,15 +64,17 @@ class _Sockets
* @param int $timeout Timeout (in seconds)
* @param string $httpVersion HTTP Version
* @param bool|int $followRedirects Automatically follow redirects? If a number is provided, will follow up to that number of redirects
* @param array|null $allowedProtocols Protocols allowed (if NULL we default to array( 'http', 'https', 'ftp', 'scp', 'sftp', 'ftps' ))
* @return void
*/
public function __construct( $url, $timeout, $httpVersion, $followRedirects )
public function __construct( $url, $timeout=5, $httpVersion=NULL, $followRedirects=TRUE, $allowedProtocols=NULL )
{
$this->url = $url;
$this->context = stream_context_create();
$this->httpVersion = $httpVersion ?: '1.1';
$this->timeout = $timeout;
$this->followRedirects = $followRedirects;
$this->url = $url;
$this->context = stream_context_create();
$this->httpVersion = $httpVersion ?: '1.1';
$this->timeout = $timeout;
$this->followRedirects = $followRedirects;
$this->allowedProtocols = $allowedProtocols ?: array( 'http', 'https', 'ftp', 'scp', 'sftp', 'ftps' );
/* Set our basic settings */
stream_context_set_option( $this->context, array(
@@ -87,9 +94,9 @@ class _Sockets
/**
* Login
*
* @param string Username
* @param string Password
* @return \IPS\Http\Request\Socket (for daisy chaining)
* @param string $username Username
* @param string $password Password
* @return static (for daisy chaining)
*/
public function login( $username, $password )
{
@@ -100,8 +107,8 @@ class _Sockets
/**
* Set Headers
*
* @param array Key/Value pair of headers
* @return \IPS\Http\Request\Socket
* @param array $headers Key/Value pair of headers
* @return static
*/
public function setHeaders( $headers )
{
@@ -113,7 +120,7 @@ class _Sockets
* Toggle SSL checks
*
* @param boolean $value True will enable SSL checks, false will disable them
* @return \IPS\Http\Request\Socket
* @return static
*/
public function sslCheck( $value=TRUE )
{
@@ -130,11 +137,11 @@ class _Sockets
/**
* Force TLS
*
* @return \IPS\Http\Request\Socket
* @return static
*/
public function forceTls()
{
if ( defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT') )
if ( \defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT') )
{
stream_context_set_option( $this->context, array(
'ssl' => array(
@@ -142,7 +149,7 @@ class _Sockets
)
) );
}
elseif ( defined('STREAM_CRYPTO_METHOD_TLS_CLIENT') )
elseif ( \defined('STREAM_CRYPTO_METHOD_TLS_CLIENT') )
{
stream_context_set_option( $this->context, array(
'ssl' => array(
@@ -168,7 +175,7 @@ class _Sockets
$method = mb_strtoupper( $method );
/* The data (string or array) will be the first parameter */
if ( isset( $params[0] ) && is_array( $params[0] ) )
if ( isset( $params[0] ) && \is_array( $params[0] ) )
{
$this->setHeaders( array( 'Content-Type' => 'application/x-www-form-urlencoded' ) );
$data = http_build_query( $params[0], '', '&' );
@@ -218,7 +225,7 @@ class _Sockets
/* Get the location */
$location = $this->url->data['path'] ? \IPS\Http\Url::encodeComponent( \IPS\Http\Url::COMPONENT_PATH, $this->url->data['path'] ) : '';
$location .= ( count( $this->url->queryString ) ) ? '?' . \IPS\Http\Url::convertQueryAsArrayToString( $this->url->queryString, true ) : '';
$location .= ( \count( $this->url->queryString ) ) ? '?' . \IPS\Http\Url::convertQueryAsArrayToString( $this->url->queryString, true ) : '';
$location .= $this->url->data['fragment'] ? '#' . \IPS\Http\Url::encodeComponent( \IPS\Http\Url::COMPONENT_FRAGMENT, $this->url->data['fragment'] ) : '';
/* Send request */
@@ -255,7 +262,7 @@ class _Sockets
\fclose( $resource );
/* Log - but because the output can be large, only do this if we explicitly have debug logging enabled */
if ( defined('\IPS\DEBUG_LOG') and \IPS\DEBUG_LOG )
if ( \defined('\IPS\DEBUG_LOG') and \IPS\DEBUG_LOG )
{
\IPS\Log::debug( "\n\n------------------------------------\nSOCKETS REQUEST: {$this->url}\n------------------------------------\n\n{$request}\n\n------------------------------------\nRESPONSE\n------------------------------------\n\n" . $response, 'request' );
}
@@ -264,17 +271,30 @@ class _Sockets
$response = new \IPS\Http\Response( $response );
/* Either return it or follow it */
if ( $this->followRedirects and in_array( $response->httpResponseCode, array( 301, 302, 303, 307, 308 ) ) )
if ( $this->followRedirects and \in_array( $response->httpResponseCode, array( 301, 302, 303, 307, 308 ) ) )
{
/* Fix missing hostname in location */
$location = $response->httpHeaders['Location'];
foreach( $response->httpHeaders as $k => $v )
{
if( mb_strtolower( $k ) == 'location' )
{
$location = $v;
}
}
if( parse_url( $location, PHP_URL_HOST ) === NULL )
{
$location = $this->url->data['scheme'] . '://' . $this->url->data['host'] . $location;
}
$newRequest = \IPS\Http\Url::external( $location )->request( $this->timeout, $this->httpVersion, is_int( $this->followRedirects ) ? ( $this->followRedirects - 1 ) : $this->followRedirects );
$newRequest = \IPS\Http\Url::external( $location );
if( !\in_array( $newRequest->data['scheme'], $this->allowedProtocols ) )
{
throw new \IPS\Http\Request\Exception( 'protocol_not_followed' );
}
$newRequest = $newRequest->request( $this->timeout, $this->httpVersion, \is_int( $this->followRedirects ) ? ( $this->followRedirects - 1 ) : $this->followRedirects );
return $newRequest->$method( $params );
}
return $response;