Passed
Push — master ( 22acbe...a6e730 )
by Théo
02:08
created

Verify   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 103
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 9
dl 0
loc 103
rs 10
c 0
b 0
f 0

2 Methods

Rating   Name   Duplication   Size   Complexity  
A configure() 0 23 1
C execute() 0 66 8
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box\Console\Command;
16
17
use Assert\Assertion;
18
use Phar;
19
use Symfony\Component\Console\Command\Command;
20
use Symfony\Component\Console\Input\InputArgument;
21
use Symfony\Component\Console\Input\InputInterface;
22
use Symfony\Component\Console\Output\OutputInterface;
23
use Symfony\Component\Console\Style\SymfonyStyle;
24
use Throwable;
25
26
final class Verify extends Command
27
{
28
    private const PHAR_ARG = 'phar';
29
    private const VERBOSITY_LEVEL = OutputInterface::VERBOSITY_VERBOSE;
30
31
    /**
32
     * {@inheritdoc}
33
     */
34
    protected function configure(): void
35
    {
36
        $this->setName('verify');
37
        $this->setDescription('Verifies the PHAR signature');
38
        $this->setHelp(
39
            <<<'HELP'
40
The <info>%command.name%</info> command will verify the signature of the PHAR.
41
42
<question>Why would I require that box handle the verification process?</question>
43
44
If you meet all of the following conditions:
45
 - The <comment>openssl</comment> extension is not installed
46
 - You need to verify a PHAR signed using a private key
47
48
Box supports verifying private key signed PHARs without using
49
either extensions. <error>Note however, that the entire PHAR will need
50
to be read into memory before the verification can be performed.</error>
51
HELP
52
        );
53
        $this->addArgument(
54
            self::PHAR_ARG,
55
            InputArgument::REQUIRED,
56
            'The PHAR file'
57
        );
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63
    protected function execute(InputInterface $input, OutputInterface $output): int
64
    {
65
        $io = new SymfonyStyle($input, $output);
66
67
        $pharPath = $input->getArgument(self::PHAR_ARG);
68
69
        Assertion::file($pharPath);
70
71
        $pharPath = false !== realpath($pharPath) ? realpath($pharPath) : $pharPath;
72
73
        $io->writeln(
74
            sprintf(
75
                'Verifying the PHAR "<comment>%s</comment>"...',
76
                $pharPath
77
            ),
78
            self::VERBOSITY_LEVEL
79
        );
80
81
        try {
82
            $phar = new Phar($pharPath);
83
84
            $verified = true;
85
            $signature = $phar->getSignature();
86
        } catch (Throwable $throwable) {
87
            // Continue
88
89
            $verified = false;
90
            $signature = null;
91
        }
92
93
        if (false === $verified) {
94
            $message = isset($throwable) && '' !== $throwable->getMessage()
95
                ? $throwable->getMessage()
96
                : 'Unknown reason.'
97
            ;
98
99
            $io->writeln(
100
                sprintf(
101
                    '<error>The PHAR failed the verification: %s</error>',
102
                    $message
103
                )
104
            );
105
106
            if ($output->isVerbose() && isset($throwable)) {
107
                throw $throwable;
108
            }
109
110
            return 1;
111
        }
112
113
        $io->writeln('<info>The PHAR passed verification.</info>');
114
115
        $io->writeln(
116
            '',
117
            self::VERBOSITY_LEVEL
118
        );
119
        $io->writeln(
120
            sprintf(
121
                '%s signature: <info>%s</info>',
122
                $signature['hash_type'],
123
                $signature['hash']
124
            ),
125
            self::VERBOSITY_LEVEL
126
        );
127
128
        return 0;
129
    }
130
}
131