JEMBOT MAWOT Bypass Shell
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Core\Currency;
use PrestaShop\CircuitBreaker\Contract\CircuitBreakerInterface;
use PrestaShop\Decimal\DecimalNumber;
use PrestaShop\PrestaShop\Core\Currency\Exception\CurrencyFeedException;
use PrestaShop\PrestaShop\Core\Domain\Currency\ValueObject\ExchangeRate;
use SimpleXMLElement;
use Symfony\Component\Cache\Adapter\AdapterInterface as CacheInterface;
/**
* Retrieves the exchange rate of a currency (based on the default currency). It uses a circuit breaker
* to avoid being blocked in case of network problems and it saves each of its request in a cache to be
* able to have a fallback response.
*/
class ExchangeRateProvider
{
/**
* This url was set in the _PS_CURRENCY_FEED_URL_ const but it is not accessible in every
* context because it is weirdly defined in defines_uri.inc.php So it is safer to define
* it properly here.
*/
public const CURRENCY_FEED_URL = 'http://api.prestashop.com/xml/currencies.xml';
public const CLOSED_ALLOWED_FAILURES = 3;
public const CLOSED_TIMEOUT_SECONDS = 1;
public const OPEN_ALLOWED_FAILURES = 3;
public const OPEN_TIMEOUT_SECONDS = 2;
public const OPEN_THRESHOLD_SECONDS = 3600; // 1 hour
public const CACHE_KEY_XML = 'currency_feed.xml';
/** @var string */
private $currencyFeedUrl;
/** @var string */
private $defaultCurrencyIsoCode;
/** @var CircuitBreakerInterface */
private $remoteServiceProvider;
/** @var CacheInterface */
private $cache;
/** @var string */
private $sourceIsoCode;
/** @var array */
private $currencies = [];
/**
* @param string $currencyFeedUrl
* @param string $defaultCurrencyIsoCode
* @param CircuitBreakerInterface $remoteServiceProvider
* @param CacheInterface $cache
*/
public function __construct(
$currencyFeedUrl,
$defaultCurrencyIsoCode,
CircuitBreakerInterface $remoteServiceProvider,
CacheInterface $cache
) {
$this->currencyFeedUrl = $currencyFeedUrl;
$this->defaultCurrencyIsoCode = $defaultCurrencyIsoCode;
$this->remoteServiceProvider = $remoteServiceProvider;
$this->cache = $cache;
}
/**
* @param string $currencyIsoCode
*
* @return DecimalNumber
*
* @throws CurrencyFeedException
*/
public function getExchangeRate($currencyIsoCode)
{
$this->fetchCurrencyFeed();
// Default feed currency (usually EUR)
if ($this->defaultCurrencyIsoCode == $currencyIsoCode) {
return ExchangeRate::getDefaultExchangeRate();
}
/*
* Search for the currency rate in the source feed, this represents the rate
* relative to the source feed (compared to the feed default currency)
*/
$sourceRate = $this->getExchangeRateFromFeed($currencyIsoCode);
/*
* Fetch the exchange rate of the default currency (compared to the source currency)
* and finally compute the asked currency rate compared to the shop default currency rate
*/
$defaultExchangeRate = $this->getExchangeRateFromFeed($this->defaultCurrencyIsoCode);
return $sourceRate->dividedBy($defaultExchangeRate);
}
/**
* @param string $currencyIsoCode
*
* @return DecimalNumber
*
* @throws CurrencyFeedException
*/
private function getExchangeRateFromFeed(string $currencyIsoCode)
{
if ($this->sourceIsoCode == $currencyIsoCode) {
return new DecimalNumber('1.0');
}
if (!isset($this->currencies[$currencyIsoCode])) {
throw new CurrencyFeedException(sprintf('Exchange rate for currency with ISO code %s was not found', $currencyIsoCode));
}
return $this->currencies[$currencyIsoCode];
}
/**
* Fetch the currency from its url using circuit breaker, if no content was fetched
* fallback on the cache file. This is only performed once per process, if the currencies
* are already present then there is nothing to do.
*
* @throws CurrencyFeedException
*/
private function fetchCurrencyFeed()
{
if (!empty($this->currencies)) {
return;
}
$remoteFeedData = $this->remoteServiceProvider->call($this->currencyFeedUrl);
$cachedFeedData = $this->getCachedCurrencyFeed();
if (empty($remoteFeedData) && empty($cachedFeedData)) {
throw new CurrencyFeedException('Currency feed could not be fetched');
}
$xmlFeed = $this->parseAndSaveXMLFeed($remoteFeedData);
if (null === $xmlFeed) {
$xmlFeed = $this->parseAndSaveXMLFeed($cachedFeedData);
}
if (null === $xmlFeed) {
throw new CurrencyFeedException('Invalid currency XML feed');
}
$this->parseXmlFeed($xmlFeed);
}
/**
* @param string $feedContent
*
* @return SimpleXMLElement|null
*/
private function parseAndSaveXMLFeed($feedContent)
{
$xmlFeed = @simplexml_load_string($feedContent);
if (!$xmlFeed || !$this->isValidXMLFeed($xmlFeed)) {
return null;
}
//Cache the feed
$cacheItem = $this->cache->getItem(self::CACHE_KEY_XML);
$cacheItem->set($feedContent);
$this->cache->save($cacheItem);
return $xmlFeed;
}
/**
* @param SimpleXMLElement $xmlFeed
*/
private function parseXmlFeed($xmlFeed)
{
$xmlCurrencies = $xmlFeed->list->currency;
$this->sourceIsoCode = (string) ($xmlFeed->source['iso_code']);
foreach ($xmlCurrencies as $currency) {
$this->currencies[(string) $currency['iso_code']] = new DecimalNumber((string) $currency['rate']);
}
}
/**
* @return string
*/
private function getCachedCurrencyFeed()
{
$cacheItem = $this->cache->getItem(self::CACHE_KEY_XML);
if (!$cacheItem->isHit()) {
return '';
}
$feedContent = $cacheItem->get();
return !empty($feedContent) ? $feedContent : '';
}
/**
* @param SimpleXMLElement $xmlFeed
*
* @return bool
*/
private function isValidXMLFeed(SimpleXMLElement $xmlFeed): bool
{
return (bool) count($xmlFeed->list->currency);
}
}
xxxxx1.0, XXX xxxx