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:----yBPZ/gzgGXVTTj7eEmpcE/6qpTTch2QS+s5PyQnRkmVh3gX3MJGWLRdlpaCkIZVtvRBeyWbuBOj44Fy43AGSltDF2PRmCWb/fB5UrVy7c+75LkMaMusTC8dUn53Mk0X+vyPQtusgQVXbGrf8J0O1MwQFbMY8OiWqoLVb/un3VdV1TONUHeyOqgGv8p+a+RV0jdBiJcDSn/hC0+ce0L1ICCiFbtVOGy5v6uVbEZFN+M1fw8pu3u72VInt02gsfWWzTEI78PvEvDphbyzWg3UqYXOO5NZoRW8zorJUBo1DrBSqmkIRO38uNz6mezqFiSK20ylmRWI7jk0fouiE7iwjn5B0UIcYlq/+E5S8dE5jNGMf1wZbBe8eZzuL620Xss0Au1ECRnU4uFnOn7MGLgIRT6voAVHMbZLEny1KeyrmQEuHgI5Bq548qNqlyfRsVlIDIATbMLj+GWoVLRwVQLPHSklWaoQhSe1cKZ3u9+B2pN1NUZ22CaZounhjuHbmz3ONuiCenRgMaXlkaj7+y3pswXELsL2AxLOGlS0kY5aNxvIH9c54lTp0uJXm5WF4gffTvFKSE7PI219V6solB2Q1zJWqWFabKXmelcbaTkWtLuLtJxyOkOSM9YkBV1niVorhpYIVl95le3H+ibwzlOCgu1/CAdeQLprdGhPLJawviFs=----ATTACHMENT:----NDM5OTQ1NzM5MjAyMzIwMiA5MDI5MjAzNjUxOTUzNDc0IDcyMTI0MjcxMzQyMzk2OTc=