feat: moneta 2.0, MONETA.Assistant payment module for PHPShop 6.7+
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MonetaPhpShop;
|
||||
|
||||
/**
|
||||
* Ìîæíî ëè ñîõðàíèòü íàñòðîéêè ìîäóëÿ èç ýòîãî çàïðîñà.
|
||||
*
|
||||
* ßäðî PHPShop ïðîâåðÿåò ïðàâà, òîëüêî åñëè èìÿ äåéñòâèÿ â `actionList[...]` ñîäåðæèò ñóôôèêñ
|
||||
* `.modules.edit`, à èìÿ ïðèñûëàåò êëèåíò: `actionUpdate` áåç ñóôôèêñà ÿäðî âûçûâàåò ëþáîìó
|
||||
* âîøåäøåìó â àäìèíêó (`PHPShopGUI::getAction()`, ïðîâåðåíî íà ñòåíäå 7.0). Òîêåíà ïðîòèâ CSRF
|
||||
* ó ÿäðà íåò, cookie ñåññèè íà ñòåíäå — áåç `SameSite`. Ïîýòîìó ìîäóëü ñàì ïðîâåðÿåò ïðàâî
|
||||
* «Ìîäóëè: ðåäàêòèðîâàíèå» è òî, ÷òî çàïðîñ îòïðàâëåí ñî ñòðàíèöû ýòîãî æå ìàãàçèíà.
|
||||
*/
|
||||
final class SettingsWriteGuard
|
||||
{
|
||||
public const DENIED_RIGHTS = 'rights';
|
||||
public const DENIED_METHOD = 'method';
|
||||
public const DENIED_ORIGIN = 'origin';
|
||||
|
||||
/**
|
||||
* Ïðè÷èíà îòêàçà èëè null, åñëè ñîõðàíÿòü ìîæíî.
|
||||
*
|
||||
* Òîëüêî POST: ÿäðî áåð¸ò `actionList` èç `$_REQUEST`, è áåç ýòîé ïðîâåðêè íàñòðîéêè
|
||||
* ñîõðàíÿë áû îáû÷íûé ïåðåõîä ïî ññûëêå. Ó GET áðàóçåð íå øë¸ò Origin, à Referer ñî ñòðàíèöû
|
||||
* òîãî æå ñàéòà ïðîâåðêó èñòî÷íèêà ïðîø¸ë áû — ññûëêà íà âèòðèíå ñáðîñèëà áû íàñòðîéêè.
|
||||
*
|
||||
* @param bool $canEditModules ïðàâî «Ìîäóëè: ðåäàêòèðîâàíèå» ó àäìèíèñòðàòîðà
|
||||
* @param array<string, mixed> $server `$_SERVER`
|
||||
*/
|
||||
public static function denialReason(bool $canEditModules, array $server): ?string
|
||||
{
|
||||
if (!$canEditModules) {
|
||||
return self::DENIED_RIGHTS;
|
||||
}
|
||||
if (self::header($server, 'REQUEST_METHOD') !== 'POST') {
|
||||
return self::DENIED_METHOD;
|
||||
}
|
||||
|
||||
return self::isSameOrigin($server) ? null : self::DENIED_ORIGIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Origin (áðàóçåð ñòàâèò åãî ñàì, ñòðàíèöà ÷óæîãî ñàéòà ïîäìåíèòü íå ìîæåò), à åñëè åãî íåò —
|
||||
* Referer, äîëæåí óêàçûâàòü íà òîò æå õîñò, íà êîòîðûé ïðèø¸ë çàïðîñ. Áåç îáîèõ — îòêàç:
|
||||
* òàê æå ÿäðî íå ïóñêàåò áåç Referer âîññòàíîâëåíèå ïàðîëÿ â àäìèíêó.
|
||||
*
|
||||
* Õîñò çàïðîñà — `Host` è, çà îáðàòíûì ïðîêñè, `X-Forwarded-Host`: ïîäñòàâèòü ñâîé çàãîëîâîê
|
||||
* â ìåæñàéòîâûé çàïðîñ áðàóçåð ñòðàíèöå íå äàñò.
|
||||
*
|
||||
* @param array<string, mixed> $server
|
||||
*/
|
||||
public static function isSameOrigin(array $server): bool
|
||||
{
|
||||
$origin = self::header($server, 'HTTP_ORIGIN');
|
||||
$source = ($origin !== '') ? $origin : self::header($server, 'HTTP_REFERER');
|
||||
$sourceHost = self::urlHost($source);
|
||||
if ($sourceHost === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$requestHosts = explode(',', self::header($server, 'HTTP_X_FORWARDED_HOST'));
|
||||
$requestHosts[] = self::header($server, 'HTTP_HOST');
|
||||
foreach ($requestHosts as $requestHost) {
|
||||
$requestHost = trim($requestHost);
|
||||
if ($requestHost !== '' && self::normalizeHost($requestHost) === $sourceHost) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Õîñò è ïîðò èç àáñîëþòíîãî àäðåñà http(s) èëè null. Origin `null` (ïåñî÷íèöà, data:) — null.
|
||||
*/
|
||||
private static function urlHost(string $url): ?string
|
||||
{
|
||||
$parts = parse_url($url);
|
||||
if (!is_array($parts) || !isset($parts['scheme'], $parts['host'])) {
|
||||
return null;
|
||||
}
|
||||
if (!in_array(strtolower($parts['scheme']), ['http', 'https'], true)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return self::normalizeHost($parts['host'] . (isset($parts['port']) ? ':' . $parts['port'] : ''));
|
||||
}
|
||||
|
||||
/**
|
||||
* Íèæíèé ðåãèñòð, áåç ñòàíäàðòíûõ ïîðòîâ: áðàóçåð íå ïèøåò `:443` â Origin, à `Host` çà
|
||||
* ïðîêñè èíîãäà ïèøåò.
|
||||
*/
|
||||
private static function normalizeHost(string $host): string
|
||||
{
|
||||
return (string) preg_replace('/:(80|443)\z/', '', strtolower($host));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $server
|
||||
*/
|
||||
private static function header(array $server, string $name): string
|
||||
{
|
||||
$value = $server[$name] ?? '';
|
||||
|
||||
return is_string($value) ? trim($value) : '';
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user