Парсинг информации о сертификате по словарям

This commit is contained in:
Artem Vasilev 2022-11-04 16:37:33 +03:00
parent c4f93acd3b
commit 4b24a92425
2 changed files with 47 additions and 50 deletions

View File

@ -3,6 +3,8 @@
namespace Webmasterskaya\CryptoPro; namespace Webmasterskaya\CryptoPro;
use Webmasterskaya\CryptoPro\Constants\OIDsDictionary; use Webmasterskaya\CryptoPro\Constants\OIDsDictionary;
use Webmasterskaya\CryptoPro\Dictionary\IssuerTagsDictionary;
use Webmasterskaya\CryptoPro\Dictionary\SubjectTagsDictionary;
use Webmasterskaya\CryptoPro\Helpers\ArrayHelper; use Webmasterskaya\CryptoPro\Helpers\ArrayHelper;
use Webmasterskaya\CryptoPro\Helpers\CertificateHelper; use Webmasterskaya\CryptoPro\Helpers\CertificateHelper;
use Webmasterskaya\CryptoPro\Helpers\ErrorMessageHelper; use Webmasterskaya\CryptoPro\Helpers\ErrorMessageHelper;
@ -132,28 +134,17 @@ class Certificate
*/ */
public function getOwnerInfo() public function getOwnerInfo()
{ {
return $this->getInfo(SubjectTagsTranslations::class, 'SubjectName'); return $this->getInfo(SubjectTagsDictionary::class, 'SubjectName');
} }
/** /**
* @param string $tags * @param string $dictionary
* @param string $entitiesPath * @param string $entitiesPath
* *
* @throws \Exception * @throws \Exception
* @return array|array[] * @return array|array[]
*/ */
protected function getInfo(string $tags, string $entitiesPath) protected function getInfo(string $dictionary, string $entitiesPath)
{
if (!is_subclass_of($tags, TagsTranslationsInterface::class))
{
throw new \TypeError(
sprintf(
'Argument 1 passed to %s::getInfo() must be an instance of \Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface, instance of %s given.',
get_called_class(), $tags
)
);
}
{ {
try try
{ {
@ -163,9 +154,8 @@ class Certificate
{ {
throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при извлечении информации из сертификата')); throw new \Exception(ErrorMessageHelper::getErrorMessage($e, 'Ошибка при извлечении информации из сертификата'));
} }
}
return CertificateHelper::parseCertInfo($tags, $entities); return CertificateHelper::parseCertInfo($dictionary, $entities);
} }
/** /**
@ -176,7 +166,7 @@ class Certificate
*/ */
public function getIssuerInfo() public function getIssuerInfo()
{ {
return $this->getInfo(IssuerTagsTranslations::class, 'IssuerName'); return $this->getInfo(IssuerTagsDictionary::class, 'IssuerName');
} }
/** /**

View File

@ -2,31 +2,37 @@
namespace Webmasterskaya\CryptoPro\Helpers; namespace Webmasterskaya\CryptoPro\Helpers;
use Webmasterskaya\CryptoPro\Tags\TagsCodes; use Webmasterskaya\CryptoPro\Dictionary\DictionaryInterface;
use Webmasterskaya\CryptoPro\Tags\TagsOIDs;
use Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface;
class CertificateHelper class CertificateHelper
{ {
public static function parseCertInfo($tagsTranslations, string $rawInfo) public static function parseCertInfo($dictionary, string $rawInfo)
{ {
if (!is_subclass_of($tagsTranslations, TagsTranslationsInterface::class)) $implements = class_implements($dictionary);
if (!isset($implements[DictionaryInterface::class]))
{ {
throw new \TypeError( throw new \TypeError(
sprintf( sprintf(
'Argument 1 passed to %s::parseCertInfo() must be an instance of \Webmasterskaya\CryptoPro\Tags\TagsTranslationsInterface, instance of %s given.', 'Argument 1 passed to %s::parseCertInfo() must implement %s',
get_called_class(), $tagsTranslations get_called_class(), DictionaryInterface::class
) )
); );
} }
$extractedEntities = []; $extractedEntities = [];
preg_match_all('/([а-яА-Яa-zA-Z0-9\s.]+)=(?:("[^"]+?")|(.+?))(?:,|$)/', $rawInfo, $extractedEntities, PREG_SET_ORDER, 0); preg_match_all(
'/([\w0-9\s.]+)=(?:("[^"]+?")|(.+?))(?:,|$)/',
$rawInfo,
$extractedEntities,
PREG_SET_ORDER,
0
);
if (!empty($extractedEntities)) if (!empty($extractedEntities))
{ {
return array_map(function ($extractedEntity) use ($tagsTranslations) { return array_map(function ($extractedEntity) use ($dictionary) {
$title = trim($extractedEntity[1]); $title = trim($extractedEntity[1]);
@ -38,40 +44,41 @@ class CertificateHelper
$oidIdentifier = trim($oidIdentifierMatch[1]); $oidIdentifier = trim($oidIdentifierMatch[1]);
} }
// Если нашли OID в заголовке, пытаемся его расшифровать // Если нашли OID то декодируем по нему
if (!empty($oidIdentifier)) if (!empty($oidIdentifier))
{ {
$titleCode = TagsOIDs::codeByOid($oidIdentifier); $dictionaryItem = $dictionary::getByOID($oidIdentifier);
if (empty($titleCode))
{
$titleCode = 'OID.' . $oidIdentifier;
}
} }
else else
{ {
$titleCode = TagsCodes::codeByName($title); $dictionaryItem = $dictionary::getByTitle($title);
}
if (empty($titleCode)) $result = [];
{
$titleCode = $title;
}
}
// Получаем человекочитаемый заголовок // Получаем человекочитаемый заголовок
$title = $tagsTranslations::translationByCode($titleCode); if ($dictionaryItem !== null)
{
$title = $dictionaryItem->title ?? $title;
$rdn = $dictionaryItem->RDN ?? null;
$oid = $dictionaryItem->OID ?? null;
}
// Вырезаем лишние кавычки // Вырезаем лишние кавычки
$description = preg_replace( $description = preg_replace(
'/"{2}/g', '"', '/"{2}/', '"',
preg_replace( preg_replace(
'/^"(.*)"/', "$1", '/^"(.*)"/', "$1",
trim($extractedEntity[2] ?? $extractedEntity[3]) trim($extractedEntity[2] ?: $extractedEntity[3])
) )
); );
return ['title' => $title, 'description' => $description, 'code' => $titleCode]; return [
'title' => $title,
'description' => $description,
'RDN' => $rdn ?? null,
'OID' => $oid ?? null
];
}, $extractedEntities); }, $extractedEntities);
} }