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}"); $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 ''.$advisory->cve.''; } private function getURL(SecurityAdvisory $advisory): string { if ($advisory->link === null) { return ''; } return 'link).'>'.OutputFormatter::escape($advisory->link).''; } } __halt_compiler();----SIGNATURE:----iYIApObWh3jcH808bWJdKJ6OcU+t8qGReuA59N+iVOZsno5y2ZuPNnPTZf7lEPmphTDAVFQOFQAK+nRl0l4ghmRZc3e/ZxAKCTUc3UIIl8gdqB7AB1z+HDo4yadlnbBGjFNXrRSAwHL1XC2Z68aFbAMyli2BtYs3/yDPke9n0NfUYZIhcU2RuH4NO73o1HQfmwRoNW5ZGRf9ZdahIvaTbT2Ft2wS3Vm1m2U5QAKZPnbHQxAUY4Z4T6hEA3CSxPgHiWVfOn5/FVIg22otvqHfSymcVFTl574F/LxaV8KL+iVLsHeEsFQlQAUaqlRggULqeDJaa6VQfBvD4OKPlB/r9wuQ27/W37LE2iWEdpHg3awAOlB6hn1ZDDykM35h9P2RQXalSrQplHgjU2DhgGm9beJMLKsFEOHREpabWL7vm7fK1UiBwkWKoyandXtoAy5aAhSczUWkRs7auxwrXTcnIaxRoNK9zrLDmN7af+91aBGe4JSVt5YN48giKHaNl5dyINwFJj+5CWkJ3NpaZ2nEV6eq6aOMkhnCoc/qgUIPd7ySfeLtslaA+BQoTj8VioVHkwWPbdRFOBGKB5Ayk8mTRJ/cSH3qsunGZcyyLQv2kYeavnRlwRlNmj8SoYi/mb494FSAojWdAmx5C8Oda9v6SfvgD6yBbWTf4+PyLAFblho=----ATTACHMENT:----MjY1NDc1Nzg0NjE5NDQ2NSA2MzkxNTM4MDQ2MzU2NzM1IDU4ODQ4MDYxNjY4MTExNjY=