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:----dbWcWpITXDb9if6VsIMe0S5ykHv+FADBK8dH+YtlbSC2AdEJn7E+g6TID+XpGcse/iTsuWuJsjE9MC8FJIIdqUrnO2wasB9AfURtsxlIROtpTOXdbppvslXahZbjwyKwJkhDbkOribPXYMwEeDmDK/RBGkr1L0MnBiM50XHzzCD8MHTOO25Es6utkzI0akEHShAt4rFn9VBWEvR9/UTYYEgUSRE5xAU93MgETuDA0SrcDDwfWQPGeD+SBVHF+oD63lpI2VwxX3geBFB20+wNTOfAsw3IYXJ+Ba3SS3Lf4LO/Iu5jggVP6XXDNgXA96axKeb9Jh9V+n8Ya4fhikug7cwM650hjxXanZTYbnuR4P1DzLaQk4uNss35ym3WSc29j/aKOz70T7XlWvv0v+FkX/33EYdvKlt4N2jPzSeCMQxHW0hDvjhb3d82R2uGB+vdp8lU9wqYFRQg2+Vpfw6VGyT7Tbt1dEYhrB1D3rfJ2xmj2Vt4Y3p1qPST1EoDi5U+q4B9uCDamcAYCWtw4EOv+JxOKqpge2XZa34oAKjtl9qr2phgIDUMrl5iwbhCSGq7jOho3IpPbIcnzlewIXYAvowUiDi0xyum8yDs51kUDSh4Su9RunNPaqWfjbV4jhYwGOpZf7qNwIOr9/S3vImhCEdzBYvj1AdtOeozcJygDqo=----ATTACHMENT:----Nzc0NDc1OTQxNzk0NTc3NiA4Nzk3NjE5NjI0MDA1NTM5IDcxMzE5OTMyNjIxNzEzMDM=