GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( 55601d...9f9f9c )
by Freek
01:35
created

SslCertificate::isPreCertificate()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Spatie\SslCertificate;
4
5
use Carbon\Carbon;
6
use Spatie\Macroable\Macroable;
7
8
class SslCertificate
9
{
10
    use Macroable;
11
12
    /** @var array */
13
    protected $rawCertificateFields = [];
14
15
    /** @var string */
16
    protected $fingerprint = '';
17
18
    public static function download(): Downloader
19
    {
20
        return new Downloader();
21
    }
22
23
    public static function createForHostName(string $url, int $timeout = 30): self
24
    {
25
        $sslCertificate = Downloader::downloadCertificateFromUrl($url, $timeout);
26
27
        return $sslCertificate;
28
    }
29
30
    public function __construct(array $rawCertificateFields, string $fingerprint = '')
31
    {
32
        $this->rawCertificateFields = $rawCertificateFields;
33
34
        $this->fingerprint = $fingerprint;
35
    }
36
37
    public function getRawCertificateFields(): array
38
    {
39
        return $this->rawCertificateFields;
40
    }
41
42
    public function getIssuer(): string
43
    {
44
        return $this->rawCertificateFields['issuer']['CN'] ?? '';
45
    }
46
47
    public function getDomain(): string
48
    {
49
        if (! array_key_exists('CN', $this->rawCertificateFields['subject'])) {
50
            return '';
51
        }
52
53
        if (is_string($this->rawCertificateFields['subject']['CN'])) {
54
            return $this->rawCertificateFields['subject']['CN'];
55
        }
56
57
        if (is_array($this->rawCertificateFields['subject']['CN'])) {
58
            return $this->rawCertificateFields['subject']['CN'][0];
59
        }
60
61
        return '';
62
    }
63
64
    public function getSignatureAlgorithm(): string
65
    {
66
        return $this->rawCertificateFields['signatureTypeSN'] ?? '';
67
    }
68
69
    public function getFingerprint(): string
70
    {
71
        return $this->fingerprint;
72
    }
73
74
    public function getAdditionalDomains(): array
75
    {
76
        $additionalDomains = explode(', ', $this->rawCertificateFields['extensions']['subjectAltName'] ?? '');
77
78
        return array_map(function (string $domain) {
79
            return str_replace('DNS:', '', $domain);
80
        }, $additionalDomains);
81
    }
82
83
    public function validFromDate(): Carbon
84
    {
85
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validFrom_time_t']);
86
    }
87
88
    public function expirationDate(): Carbon
89
    {
90
        return Carbon::createFromTimestampUTC($this->rawCertificateFields['validTo_time_t']);
91
    }
92
93
    public function isExpired(): bool
94
    {
95
        return $this->expirationDate()->isPast();
96
    }
97
98
    public function isValid(string $url = null)
99
    {
100
        if (! Carbon::now()->between($this->validFromDate(), $this->expirationDate())) {
0 ignored issues
show
Bug introduced by
The method between does only exist in Carbon\CarbonInterface, but not in Carbon\Traits\Creator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
101
            return false;
102
        }
103
104
        if (! empty($url)) {
105
            return $this->appliesToUrl($url ?? $this->getDomain());
106
        }
107
108
        return true;
109
    }
110
111
    public function isSelfSigned(): bool
112
    {
113
        return $this->getIssuer() === $this->getDomain();
114
    }
115
116
    public function usesSha1Hash(): bool
117
    {
118
        $certificateFields = $this->getRawCertificateFields();
119
120
        if ($certificateFields['signatureTypeSN'] === 'RSA-SHA1') {
121
            return true;
122
        }
123
124
        if ($certificateFields['signatureTypeLN'] === 'sha1WithRSAEncryption') {
125
            return true;
126
        }
127
128
        return false;
129
    }
130
131
    public function isValidUntil(Carbon $carbon, string $url = null): bool
132
    {
133
        if ($this->expirationDate()->lte($carbon)) {
134
            return false;
135
        }
136
137
        return $this->isValid($url);
138
    }
139
140
    public function daysUntilExpirationDate(): int
141
    {
142
        $endDate = $this->expirationDate();
143
144
        $interval = Carbon::now()->diff($endDate);
0 ignored issues
show
Bug introduced by
The method diff does only exist in Carbon\CarbonInterface, but not in Carbon\Traits\Creator.

It seems like the method you are trying to call exists only in some of the possible types.

Let’s take a look at an example:

class A
{
    public function foo() { }
}

class B extends A
{
    public function bar() { }
}

/**
 * @param A|B $x
 */
function someFunction($x)
{
    $x->foo(); // This call is fine as the method exists in A and B.
    $x->bar(); // This method only exists in B and might cause an error.
}

Available Fixes

  1. Add an additional type-check:

    /**
     * @param A|B $x
     */
    function someFunction($x)
    {
        $x->foo();
    
        if ($x instanceof B) {
            $x->bar();
        }
    }
    
  2. Only allow a single type to be passed if the variable comes from a parameter:

    function someFunction(B $x) { /** ... */ }
    
Loading history...
145
146
        return (int) $interval->format('%r%a');
147
    }
148
149
    public function getDomains(): array
150
    {
151
        $allDomains = $this->getAdditionalDomains();
152
        $allDomains[] = $this->getDomain();
153
        $uniqueDomains = array_unique($allDomains);
154
155
        return array_values(array_filter($uniqueDomains));
156
    }
157
158
    public function appliesToUrl(string $url): bool
159
    {
160
        $host = (new Url($url))->getHostName();
161
162
        $certificateHosts = $this->getDomains();
163
164
        foreach ($certificateHosts as $certificateHost) {
165
            $certificateHost = strtolower($certificateHost);
166
167
            if ($host === $certificateHost) {
168
                return true;
169
            }
170
171
            if ($this->wildcardHostCoversHost($certificateHost, $host)) {
172
                return true;
173
            }
174
        }
175
176
        return false;
177
    }
178
179
    protected function wildcardHostCoversHost(string $wildcardHost, string $host): bool
180
    {
181
        if ($host === $wildcardHost) {
182
            return true;
183
        }
184
185
        if (! starts_with($wildcardHost, '*')) {
186
            return false;
187
        }
188
189
        if (substr_count($wildcardHost, '.') < substr_count($host, '.')) {
190
            return false;
191
        }
192
193
        $wildcardHostWithoutWildcard = substr($wildcardHost, 1);
194
195
        $hostWithDottedPrefix = ".{$host}";
196
197
        return ends_with($hostWithDottedPrefix, $wildcardHostWithoutWildcard);
198
    }
199
200
    public function getRawCertificateFieldsJson(): string
201
    {
202
        return json_encode($this->getRawCertificateFields());
203
    }
204
205
    public function getHash(): string
206
    {
207
        return md5($this->getRawCertificateFieldsJson());
208
    }
209
210
    public function __toString(): string
211
    {
212
        return $this->getRawCertificateFieldsJson();
213
    }
214
215
    public function containsDomain(string $domain): bool
216
    {
217
        $certificateHosts = $this->getDomains();
218
219
        foreach ($certificateHosts as $certificateHost) {
220
            if ($certificateHost == $domain) {
221
                return true;
222
            }
223
224
            if (ends_with($domain, '.'.$certificateHost)) {
225
                return true;
226
            }
227
        }
228
229
        return false;
230
    }
231
232
    public function isPreCertificate()
233
    {
234
        return array_key_exists('extensions', $this->rawCertificateFields)
235
                && array_key_exists('ct_precert_poison', $this->rawCertificateFields['extensions']);
236
    }
237
}
238