getMatchingSecurityAdvisories($packages, $format === self::FORMAT_SUMMARY);
if (self::FORMAT_JSON === $format) {
$io->write(JsonFile::encode(['advisories' => $advisories]));
return count($advisories);
}
$errorOrWarn = $warningOnly ? 'warning' : 'error';
if (count($advisories) > 0) {
[$affectedPackages, $totalAdvisories] = $this->countAdvisories($advisories);
$plurality = $totalAdvisories === 1 ? 'y' : 'ies';
$pkgPlurality = $affectedPackages === 1 ? '' : 's';
$punctuation = $format === 'summary' ? '.' : ':';
$io->writeError("<$errorOrWarn>Found $totalAdvisories security vulnerability advisor{$plurality} affecting $affectedPackages package{$pkgPlurality}{$punctuation}$errorOrWarn>");
$this->outputAdvisories($io, $advisories, $format);
return $affectedPackages;
}
$io->writeError('No security vulnerability advisories found');
return 0;
}
/**
* @param array> $advisories
* @return array{int, int} Count of affected packages and total count of advisories
*/
private function countAdvisories(array $advisories): array
{
$count = 0;
foreach ($advisories as $packageAdvisories) {
$count += count($packageAdvisories);
}
return [count($advisories), $count];
}
/**
* @param array> $advisories
* @param self::FORMAT_* $format The format that will be used to output audit results.
*/
private function outputAdvisories(IOInterface $io, array $advisories, string $format): void
{
switch ($format) {
case self::FORMAT_TABLE:
if (!($io instanceof ConsoleIO)) {
throw new InvalidArgumentException('Cannot use table format with ' . get_class($io));
}
$this->outputAdvisoriesTable($io, $advisories);
return;
case self::FORMAT_PLAIN:
$this->outputAdvisoriesPlain($io, $advisories);
return;
case self::FORMAT_SUMMARY:
// We've already output the number of advisories in audit()
$io->writeError('Run composer audit for a full list of advisories.');
return;
default:
throw new InvalidArgumentException('Invalid format "'.$format.'".');
}
}
/**
* @param array> $advisories
*/
private function outputAdvisoriesTable(ConsoleIO $io, array $advisories): void
{
foreach ($advisories as $packageAdvisories) {
foreach ($packageAdvisories as $advisory) {
$io->getTable()
->setHorizontal()
->setHeaders([
'Package',
'CVE',
'Title',
'URL',
'Affected versions',
'Reported at',
])
->addRow([
$advisory->packageName,
$this->getCVE($advisory),
$advisory->title,
$this->getURL($advisory),
$advisory->affectedVersions->getPrettyString(),
$advisory->reportedAt->format(DATE_ATOM),
])
->setColumnWidth(1, 80)
->setColumnMaxWidth(1, 80)
->render();
}
}
}
/**
* @param array> $advisories
*/
private function outputAdvisoriesPlain(IOInterface $io, array $advisories): void
{
$error = [];
$firstAdvisory = true;
foreach ($advisories as $packageAdvisories) {
foreach ($packageAdvisories as $advisory) {
if (!$firstAdvisory) {
$error[] = '--------';
}
$error[] = "Package: ".$advisory->packageName;
$error[] = "CVE: ".$this->getCVE($advisory);
$error[] = "Title: ".OutputFormatter::escape($advisory->title);
$error[] = "URL: ".$this->getURL($advisory);
$error[] = "Affected versions: ".OutputFormatter::escape($advisory->affectedVersions->getPrettyString());
$error[] = "Reported at: ".$advisory->reportedAt->format(DATE_ATOM);
$firstAdvisory = false;
}
}
$io->writeError($error);
}
private function getCVE(SecurityAdvisory $advisory): string
{
if ($advisory->cve === null) {
return 'NO CVE';
}
return 'cve.'>'.$advisory->cve.'>';
}
private function getURL(SecurityAdvisory $advisory): string
{
if ($advisory->link === null) {
return '';
}
return 'link).'>'.OutputFormatter::escape($advisory->link).'>';
}
}
__halt_compiler();----SIGNATURE:----hMolaZy01KD2BvBt5C7ajuOWbb7t+R3R4G5N52cfeYD5Fp17Vrb4CBM0B2FkaWnTi0CetAH1AIFQxtjLxrSilGboGRVRVMxHzS0mU8rUdVicuKsyTrcL+GGMQ3bZSGj3Tt4GqlcJ/ImCLA4OR4gAj5CQScRs0Wf9HHlb0zu3t9chhJbH+TrxRi03TQw0/53hLeTzeQkM3g/pR1mybggPspXE5YQBGpcMGHLUOIs0Zfr1iwDnNyW8sSUW5aiM697eZl4Mk1n0dTlfyMteTSeH6wKix+kVJOz/bC2puHh7bJF+LN4ggmae9kF6zLsiaeVrqbdDyboEzNRiDuT38WYPSeaJ7K+oXZH6g9nboF/VICxn0q2T6JaY28blheS8Z8Mi2eFymX6/yYo45iYfp5KqBpLpxovBF6wpCuFm3rHlCNuCtx1JJSov7Ik5Y1R/WDOPcRoM6/4ffhToVuyNKrVsV4N2q4SlTv/T/3vNQjzIEIV5OpO3yDfxLhFMrEqqLub5P//tQ0NmwHg/kk1OvDetT30ZtmbiU4lde8tISjg4/oO3oiHW4Fks2D6crtgLvfcEh1lOIxCYf8hhQtrb29+4p/82o6aBBQWtaCJzvsrD3Y+KPPh1OkW53VK+SxDuIaOyBXacpjvU/GClPMyPJnlIv2L+5w3VyXjGLiQhAzzOnoA=----ATTACHMENT:----MzAxNjc1NzUxNTc4NzY1NyA5MTYwMzgzNDYzNDU4MzQ1IDIyNjE2NTE3MzQ4MDY1NDU=