diff --git a/core/src/Revolution/Processors/System/Dashboard/Widget/Feed.php b/core/src/Revolution/Processors/System/Dashboard/Widget/Feed.php index 1c80540dd51..8db6d363b05 100644 --- a/core/src/Revolution/Processors/System/Dashboard/Widget/Feed.php +++ b/core/src/Revolution/Processors/System/Dashboard/Widget/Feed.php @@ -62,6 +62,11 @@ public function loadFeed($url) $this->modx->cacheManager->writeTree($cachePath); } + $proxy_config = $this->buildProxyOptions(); + if (!empty($proxy_config)) { + $feed->set_curl_options($proxy_config); + } + $feed->set_cache_location($cachePath); $feed->set_useragent($this->modx->getVersionData()['full_version']); $feed->set_feed_url($url); @@ -115,4 +120,28 @@ public function getFileChunk($tpl, array $placeholders = []) return $output; } + + /** + * Build configuration for the SimplePie client based on configuration settings. + * + * @return array The proxy configuration. + */ + private function buildProxyOptions() + { + $config = []; + $proxyHost = $this->modx->getOption('proxy_host', null, ''); + if (!empty($proxyHost)) { + $config['CURLOPT_PROXY'] = $proxyHost; + $proxyPort = $this->modx->getOption('proxy_port', null, ''); + if (!empty($proxyPort)) { + $config['CURLOPT_PROXY'] .= ':' . $proxyPort; + } + $proxyUsername = $this->modx->getOption('proxy_username', null, ''); + if (!empty($proxyUsername)) { + $proxyPassword = $this->modx->getOption('proxy_password', null, ''); + $config['CURLOPT_PROXYUSERPWD'] = $proxyUsername . ':' . $proxyPassword; + } + } + return $config; + } } diff --git a/core/src/Revolution/modX.php b/core/src/Revolution/modX.php index 08af9fd04ea..624b592e405 100644 --- a/core/src/Revolution/modX.php +++ b/core/src/Revolution/modX.php @@ -2700,7 +2700,8 @@ protected function _initHttpClient() // Http Client is created as a factory, so that repeat calls get a fresh client. This is done to make sure // mutable clients (perhaps they allow setting options after instantiation) do not cause side-effects elsewhere $this->services->add(ClientInterface::class, $this->services->factory(function() { - return new Client(); + $opts = $this->buildHttpClientOptions(); + return new Client($opts); })); } if (!$this->services->has(ServerRequestFactoryInterface::class)) { @@ -2720,6 +2721,30 @@ protected function _initHttpClient() } } + /** + * Build options for the HTTP client based on configuration settings. + * + * @return array The HTTP client options. + */ + private function buildHttpClientOptions() { + $opts = []; + $proxyHost = $this->getOption('proxy_host', null, ''); + if (!empty($proxyHost)) { + $proxy_str = $proxyHost; + $proxyPort = $this->getOption('proxy_port', null, ''); + if (!empty($proxyPort)) { + $proxy_str .= ':' . $proxyPort; + } + $proxyUsername = $this->getOption('proxy_username', null, ''); + if (!empty($proxyUsername)) { + $proxyPassword = $this->getOption('proxy_password', null, ''); + $proxy_str = $proxyUsername . ':' . $proxyPassword . '@' . $proxy_str; + } + $opts['proxy'] = $proxy_str; + } + return $opts; + } + /** * Populates the map of events and registered plugins for each. *