• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

LibreSign / libresign / 21967387454

12 Feb 2026 10:52PM UTC coverage: 51.293%. First build
21967387454

Pull #6824

github

web-flow
Merge bffecf3e4 into 34f32c1fd
Pull Request #6824: fix: signature methods names

215 of 237 new or added lines in 20 files covered. (90.72%)

8987 of 17521 relevant lines covered (51.29%)

6.03 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.85
/lib/Service/File/SignersLoader.php
1
<?php
2

3
declare(strict_types=1);
4
/**
5
 * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
6
 * SPDX-License-Identifier: AGPL-3.0-or-later
7
 */
8

9
namespace OCA\Libresign\Service\File;
10

11
use DateTime;
12
use DateTimeInterface;
13
use OCA\Libresign\Db\File;
14
use OCA\Libresign\Db\SignRequestMapper;
15
use OCA\Libresign\Service\IdentifyMethodService;
16
use OCA\Libresign\Service\SubjectAlternativeNameService;
17
use OCP\Accounts\IAccountManager;
18
use OCP\IUserManager;
19
use stdClass;
20

21
/**
22
 * Handles loading signer data for files
23
 */
24
class SignersLoader {
25
        private bool $signersLibreSignLoaded = false;
26

27
        public function __construct(
28
                private SignRequestMapper $signRequestMapper,
29
                private IdentifyMethodService $identifyMethodService,
30
                private SubjectAlternativeNameService $subjectAlternativeNameService,
31
                private IAccountManager $accountManager,
32
                private IUserManager $userManager,
33
        ) {
34
        }
51✔
35

36
        public function loadLibreSignSigners(
37
                ?File $file,
38
                stdClass $fileData,
39
                FileResponseOptions $options,
40
                array $certData = [],
41
        ): void {
42
                if ($this->signersLibreSignLoaded || !$file) {
2✔
43
                        return;
×
44
                }
45
                $signers = $this->signRequestMapper->getByFileId($file->getId());
2✔
46
                if (empty($signers)) {
2✔
47
                        return;
×
48
                }
49
                $signRequestIds = array_column(array_map(fn ($s) => ['id' => $s->getId()], $signers), 'id');
2✔
50
                $identifyMethodsBatch = $this->identifyMethodService
2✔
51
                        ->setIsRequest(false)
2✔
52
                        ->getIdentifyMethodsFromSignRequestIds($signRequestIds);
2✔
53

54
                foreach ($signers as $signer) {
2✔
55
                        $identifyMethods = $identifyMethodsBatch[$signer->getId()] ?? [];
2✔
56
                        if (!empty($fileData->signers)) {
2✔
57
                                $found = array_filter($fileData->signers, function (stdClass $found) use ($identifyMethods) {
×
58
                                        if (!isset($found->uid)) {
×
59
                                                return false;
×
60
                                        }
61
                                        [$key, $value] = explode(':', (string)$found->uid);
×
62
                                        foreach ($identifyMethods as $methods) {
×
63
                                                foreach ($methods as $identifyMethod) {
×
64
                                                        $entity = $identifyMethod->getEntity();
×
65
                                                        if ($key === $entity->getIdentifierKey() && $value === $entity->getIdentifierValue()) {
×
66
                                                                return true;
×
67
                                                        }
68
                                                }
69
                                        }
70
                                        return false;
×
71
                                });
×
72
                                if (!empty($found)) {
×
73
                                        $index = key($found);
×
74
                                } else {
75
                                        $index = count($fileData->signers);
×
76
                                }
77
                        } else {
78
                                $index = 0;
2✔
79
                        }
80
                        if (!isset($fileData->signers[$index])) {
2✔
81
                                $fileData->signers[$index] = new stdClass();
2✔
82
                        }
83
                        $fileData->signers[$index]->signRequestId = $signer->getId();
2✔
84
                        $fileData->signers[$index]->signed = $signer->getSigned()?->format(DateTimeInterface::ATOM);
2✔
85
                        $fileData->signers[$index]->status = $signer->getStatus();
2✔
86
                        $fileData->signers[$index]->statusText = $this->signRequestMapper->getTextOfSignerStatus($signer->getStatus());
2✔
87
                        $fileData->signers[$index]->signingOrder = $signer->getSigningOrder();
2✔
88
                        $fileData->signers[$index]->description = $signer->getDescription();
2✔
89
                        $fileData->signers[$index]->displayName = $signer->getDisplayName();
2✔
90
                        $fileData->signers[$index]->request_sign_date = $signer->getCreatedAt()->format(DateTimeInterface::ATOM);
2✔
91
                        $fileData->signers[$index]->metadata = $signer->getMetadata();
2✔
92
                        $fileData->signers[$index]->identifyMethods = [];
2✔
93
                        $fileData->signers[$index]->visibleElements = [];
2✔
94
                        foreach ($identifyMethods as $type => $methods) {
2✔
95
                                foreach ($methods as $identifyMethod) {
2✔
96
                                        $entity = $identifyMethod->getEntity();
2✔
97

98
                                        $fileData->signers[$index]->identifyMethods[] = [
2✔
99
                                                'method' => $entity->getIdentifierKey(),
2✔
100
                                                'value' => $entity->getIdentifierValue(),
2✔
101
                                                'mandatory' => $entity->getMandatory(),
2✔
102
                                        ];
2✔
103

104
                                        switch ($type) {
105
                                                case 'account':
2✔
106
                                                        $fileData->signers[$index]->uid = $entity->getUniqueIdentifier();
×
107
                                                        $currentDisplayName = $fileData->signers[$index]->displayName ?? '';
×
108
                                                        if ($currentDisplayName === '' || $currentDisplayName === $entity->getIdentifierValue()) {
×
109
                                                                $user = $this->userManager->get($entity->getIdentifierValue());
×
110
                                                                if ($user) {
×
111
                                                                        $fileData->signers[$index]->displayName = $user->getDisplayName();
×
112
                                                                } else {
113
                                                                        $fileData->signers[$index]->displayName = $entity->getIdentifierValue();
×
114
                                                                }
115
                                                        }
116
                                                        if (!isset($fileData->signers[$index]->email)) {
×
117
                                                                $user = $this->userManager->get($entity->getIdentifierValue());
×
118
                                                                if (!$user) {
×
119
                                                                        break;
×
120
                                                                }
121
                                                                $account = $this->accountManager->getAccount($user);
×
122
                                                                $fileData->signers[$index]->email = $account->getProperty('email')->getValue();
×
123
                                                        }
124
                                                        break;
×
125
                                                case 'email':
2✔
126
                                                        $fileData->signers[$index]->email = $entity->getIdentifierValue();
2✔
127
                                                        $fileData->signers[$index]->uid = $entity->getUniqueIdentifier();
2✔
128
                                                        if (!isset($fileData->signers[$index]->displayName)) {
2✔
129
                                                                $fileData->signers[$index]->displayName = $entity->getIdentifierValue();
×
130
                                                        }
131
                                                        break;
2✔
132
                                                case 'signatureinit':
×
133
                                                        $fileData->signers[$index]->signatureMethod = 'password';
×
134
                                                        if (!isset($fileData->signers[$index]->email)) {
×
135
                                                                $fileData->signers[$index]->email = '';
×
136
                                                        }
137
                                                        break;
×
138
                                                case 'password':
×
139
                                                        $fileData->signers[$index]->signatureMethod = 'password';
×
140
                                                        if (!isset($fileData->signers[$index]->email)) {
×
141
                                                                $fileData->signers[$index]->email = '';
×
142
                                                        }
143
                                                        break;
×
144
                                        }
145
                                }
146
                        }
147
                        if (isset($fileData->signers[$index]->uid)) {
2✔
148
                                $split = explode(':', $fileData->signers[$index]->uid);
2✔
149
                                $matches = [
2✔
150
                                        'key' => $split[0],
2✔
151
                                        'value' => $split[1],
2✔
152
                                ];
2✔
153
                                if (str_ends_with($matches['value'], $options->getHost())) {
2✔
154
                                        $uid = str_replace('@' . $options->getHost(), '', $matches['value']);
×
155
                                        if (!isset($fileData->signers[$index]->displayName) || $fileData->signers[$index]->displayName === '') {
×
156
                                                $fileData->signers[$index]->displayName = $uid;
×
157
                                        }
158
                                        $fileData->signers[$index]->uid = 'account:' . $uid;
×
159
                                }
160
                        }
161
                        $fileData->signers[$index]->me = false;
2✔
162
                        if ($options->getMe() || $options->getIdentifyMethodId()) {
2✔
163
                                $currentUserData = new stdClass();
1✔
164
                                $currentUserData->me = false;
1✔
165
                                foreach ($identifyMethods as $methods) {
1✔
166
                                        foreach ($methods as $identifyMethod) {
1✔
167
                                                $entity = $identifyMethod->getEntity();
1✔
168
                                                if ($options->getIdentifyMethodId() === $entity->getId()
1✔
169
                                                        || $options->getMe()?->getUID() === $entity->getIdentifierValue()
1✔
170
                                                        || $options->getMe()?->getEMailAddress() === $entity->getIdentifierValue()
1✔
171
                                                ) {
172
                                                        $currentUserData->me = true;
1✔
173
                                                        break 2;
1✔
174
                                                }
175
                                        }
176
                                }
177
                                $fileData->signers[$index]->me = $currentUserData->me;
1✔
178
                        }
179

180
                        if ($fileData->signers[$index]->me) {
2✔
181
                                $fileData->signers[$index]->sign_uuid = $signer->getUuid();
1✔
182
                                if (!$signer->getSigned() && isset($fileData->settings)) {
1✔
183
                                        $fileData->settings['canSign'] = true;
1✔
184
                                        $fileData->settings['signerFileUuid'] = $signer->getUuid();
1✔
185
                                }
186
                                $fileData->signers[$index]->signatureMethods = [];
1✔
187
                                foreach ($identifyMethods as $methods) {
1✔
188
                                        foreach ($methods as $identifyMethod) {
1✔
189
                                                $entity = $identifyMethod->getEntity();
1✔
190
                                                $this->identifyMethodService->setCurrentIdentifyMethod($entity);
1✔
191
                                                $identifyMethodInstance = $this->identifyMethodService
1✔
192
                                                        ->setIsRequest(false)
1✔
193
                                                        ->getInstanceOfIdentifyMethod(
1✔
194
                                                                $entity->getIdentifierKey(),
1✔
195
                                                                $entity->getIdentifierValue(),
1✔
196
                                                        );
1✔
197
                                                $signatureMethods = $identifyMethodInstance->getSignatureMethods();
1✔
198
                                                foreach ($signatureMethods as $signatureMethod) {
1✔
199
                                                        if (!$signatureMethod->isEnabled()) {
1✔
200
                                                                continue;
1✔
201
                                                        }
202
                                                        $signatureMethod->setEntity($identifyMethodInstance->getEntity());
1✔
203
                                                        $fileData->signers[$index]->signatureMethods[$signatureMethod->getName()] = $signatureMethod->toArray();
1✔
204
                                                }
205
                                        }
206
                                }
207
                        }
208
                }
209
                ksort($fileData->signers);
2✔
210
                $this->signersLibreSignLoaded = true;
2✔
211
        }
212

213
        public function loadSignersFromCertData(stdClass $fileData, array $certData, string $host): void {
214
                $existingSigners = $fileData->signers ?? [];
20✔
215
                $indexMap = $this->buildSignerIndexMap($existingSigners);
20✔
216
                $usedIndexes = [];
20✔
217

218
                foreach ($certData as $index => $signer) {
20✔
219
                        $targetIndex = $index;
20✔
220
                        $isLibreSignMatch = false;
20✔
221

222
                        $resolvedUid = $this->tryMatchWithExistingSigners($signer['chain'][0], $existingSigners, $host);
20✔
223
                        if (!$resolvedUid) {
20✔
224
                                $isLibreSignCert = isset($signer['chain'][0]['isLibreSignRootCA'])
15✔
225
                                        && $signer['chain'][0]['isLibreSignRootCA'] === true;
15✔
226
                                if ($isLibreSignCert) {
15✔
227
                                        $certUid = $signer['chain'][0]['subject']['UID'] ?? null;
6✔
228
                                        if ($certUid) {
6✔
229
                                                $resolvedUid = str_contains($certUid, ':') ? $certUid : 'account:' . $certUid;
6✔
230
                                        } else {
231
                                                $resolvedUid = null;
×
232
                                        }
233
                                } else {
234
                                        $resolvedUid = $signer['uid'] ?? null;
9✔
235
                                        if (!$resolvedUid && isset($signer['chain'][0])) {
9✔
236
                                                $resolvedUid = $this->identifyMethodService->resolveUid($signer['chain'][0], $host);
8✔
237
                                        }
238
                                }
239
                        }
240

241
                        $matchedIndex = $this->findMatchingSignerIndex($indexMap, $resolvedUid, $signer);
20✔
242
                        if ($matchedIndex !== null) {
20✔
243
                                $targetIndex = $matchedIndex;
9✔
244
                                $isLibreSignMatch = isset($existingSigners[$matchedIndex]->signRequestId);
9✔
245
                        } else {
246
                                if (!empty($existingSigners)) {
12✔
247
                                        $targetIndex = $this->nextAvailableSignerIndex($existingSigners, $usedIndexes);
4✔
248
                                }
249
                        }
250
                        $usedIndexes[$targetIndex] = true;
20✔
251

252
                        if (!isset($fileData->signers[$targetIndex])) {
20✔
253
                                $fileData->signers[$targetIndex] = new stdClass();
12✔
254
                        }
255

256
                        $preservedDisplayName = $isLibreSignMatch && isset($fileData->signers[$targetIndex]->displayName)
20✔
257
                                ? $fileData->signers[$targetIndex]->displayName
1✔
258
                                : null;
19✔
259

260
                        $fileData->signers[$targetIndex]->status = 2;
20✔
261
                        $fileData->signers[$targetIndex]->statusText = $this->signRequestMapper->getTextOfSignerStatus(2);
20✔
262

263
                        if (isset($signer['timestamp'])) {
20✔
264
                                $fileData->signers[$targetIndex]->timestamp = $signer['timestamp'];
1✔
265
                                if (isset($signer['timestamp']['genTime']) && $signer['timestamp']['genTime'] instanceof DateTimeInterface) {
1✔
266
                                        $fileData->signers[$targetIndex]->timestamp['genTime'] = $signer['timestamp']['genTime']->format(DateTimeInterface::ATOM);
1✔
267
                                }
268
                        }
269
                        if (isset($signer['signingTime']) && $signer['signingTime'] instanceof DateTimeInterface) {
20✔
270
                                $fileData->signers[$targetIndex]->signingTime = $signer['signingTime'];
17✔
271
                                $fileData->signers[$targetIndex]->signed = $signer['signingTime']->format(DateTimeInterface::ATOM);
17✔
272
                        }
273
                        if (isset($signer['docmdp'])) {
20✔
274
                                $fileData->signers[$targetIndex]->docmdp = $signer['docmdp'];
1✔
275
                        }
276
                        if (isset($signer['docmdp_validation'])) {
20✔
277
                                $fileData->signers[$targetIndex]->docmdp_validation = $signer['docmdp_validation'];
1✔
278
                        }
279
                        if (isset($signer['modifications'])) {
20✔
280
                                $fileData->signers[$targetIndex]->modifications = $signer['modifications'];
×
281
                        }
282
                        if (isset($signer['modification_validation'])) {
20✔
283
                                $fileData->signers[$targetIndex]->modification_validation = $signer['modification_validation'];
×
284
                        }
285

286
                        if (isset($signer['chain'])) {
20✔
287
                                $this->processChainData($fileData->signers[$targetIndex], $signer['chain']);
20✔
288
                        }
289

290
                        if (isset($signer['uid'])) {
20✔
291
                                $fileData->signers[$targetIndex]->uid = $signer['uid'];
1✔
292
                        } elseif ($resolvedUid) {
19✔
293
                                $fileData->signers[$targetIndex]->uid = $resolvedUid;
19✔
294
                        } elseif (isset($signer['chain'][0])) {
×
295
                                $fileData->signers[$targetIndex]->uid = $this->identifyMethodService->resolveUid($signer['chain'][0], $host);
×
296
                        }
297

298
                        if (isset($signer['signDate'])) {
20✔
299
                                $fileData->signers[$targetIndex]->signDate = $signer['signDate'];
×
300
                        }
301
                        if (isset($signer['type'])) {
20✔
302
                                $fileData->signers[$targetIndex]->type = $signer['type'];
×
303
                        }
304

305
                        if ($preservedDisplayName) {
20✔
306
                                $fileData->signers[$targetIndex]->displayName = $preservedDisplayName;
1✔
307
                        } elseif (isset($fileData->signers[$targetIndex]->uid) && str_starts_with($fileData->signers[$targetIndex]->uid, 'account:')) {
19✔
308
                                $accountId = substr($fileData->signers[$targetIndex]->uid, strlen('account:'));
5✔
309
                                $user = $this->userManager->get($accountId);
5✔
310
                                if ($user) {
5✔
311
                                        $fileData->signers[$targetIndex]->displayName = $user->getDisplayName();
1✔
312
                                } else {
313
                                        $fileData->signers[$targetIndex]->displayName = $accountId;
4✔
314
                                }
315
                        } elseif (!isset($fileData->signers[$targetIndex]->displayName) && isset($signer['chain'][0])) {
14✔
316
                                $fileData->signers[$targetIndex]->displayName = $signer['chain'][0]['name'] ?? ($signer['chain'][0]['subject']['CN'] ?? '');
12✔
317
                        }
318

319
                        if (isset($fileData->signers[$targetIndex]->uid)) {
20✔
320
                                $indexMap[strtolower((string)$fileData->signers[$targetIndex]->uid)] = $targetIndex;
20✔
321
                        }
322
                }
323
        }
324

325
        private function buildSignerIndexMap(array $signers): array {
326
                $map = [];
20✔
327
                foreach ($signers as $index => $signer) {
20✔
328
                        if (isset($signer->uid)) {
12✔
329
                                $map[strtolower((string)$signer->uid)] = $index;
12✔
330
                        }
331
                        if (!empty($signer->identifyMethods)) {
12✔
NEW
332
                                foreach ($signer->identifyMethods as $identifyMethod) {
×
NEW
333
                                        if (isset($identifyMethod['method']) && isset($identifyMethod['value'])) {
×
NEW
334
                                                $identifier = $this->subjectAlternativeNameService->build($identifyMethod['method'], $identifyMethod['value']);
×
NEW
335
                                                $map[strtolower($identifier)] = $index;
×
336
                                        }
337
                                }
338
                        }
339
                }
340
                return $map;
20✔
341
        }
342

343
        private function findMatchingSignerIndex(array $indexMap, ?string $resolvedUid, array $certSigner): ?int {
344
                $identifiers = [];
20✔
345
                if ($resolvedUid) {
20✔
346
                        $identifiers[] = strtolower($resolvedUid);
20✔
347
                }
348
                if (!empty($certSigner['uid'])) {
20✔
349
                        $identifiers[] = strtolower((string)$certSigner['uid']);
1✔
350
                }
351
                foreach ($identifiers as $identifier) {
20✔
352
                        if (isset($indexMap[$identifier])) {
20✔
353
                                return $indexMap[$identifier];
9✔
354
                        }
355
                }
356
                return null;
12✔
357
        }
358

359
        private function nextAvailableSignerIndex(array $existingSigners, array $usedIndexes): int {
360
                $index = count($existingSigners);
4✔
361
                while (isset($existingSigners[$index]) || isset($usedIndexes[$index])) {
4✔
362
                        $index++;
×
363
                }
364
                return $index;
4✔
365
        }
366

367
        public function reset(): void {
368
                $this->signersLibreSignLoaded = false;
×
369
        }
370

371
        private function processChainData(stdClass $signer, array $chain): void {
372
                $signer->chain = [];
20✔
373

374
                foreach ($chain as $chainIndex => $chainItem) {
20✔
375
                        $chainArr = $chainItem;
20✔
376

377
                        if (isset($chainItem['validFrom_time_t']) && is_numeric($chainItem['validFrom_time_t'])) {
20✔
378
                                $chainArr['valid_from'] = (new DateTime('@' . $chainItem['validFrom_time_t'], new \DateTimeZone('UTC')))->format(DateTimeInterface::ATOM);
3✔
379
                        }
380
                        if (isset($chainItem['validTo_time_t']) && is_numeric($chainItem['validTo_time_t'])) {
20✔
381
                                $chainArr['valid_to'] = (new DateTime('@' . $chainItem['validTo_time_t'], new \DateTimeZone('UTC')))->format(DateTimeInterface::ATOM);
3✔
382
                        }
383

384
                        $chainArr['displayName'] = $chainArr['name'] ?? ($chainArr['subject']['CN'] ?? '');
20✔
385
                        $signer->chain[$chainIndex] = $chainArr;
20✔
386
                }
387

388
                if (isset($chain[0])) {
20✔
389
                        $this->enrichSignerWithCertificateValidation($signer, $chain[0]);
20✔
390
                }
391
        }
392

393
        private function enrichSignerWithCertificateValidation(stdClass $signer, array $endEntityCert): void {
394
                if (isset($endEntityCert['name']) && !isset($signer->name)) {
20✔
395
                        $signer->name = $endEntityCert['name'];
10✔
396
                }
397
                if (isset($endEntityCert['hash']) && !isset($signer->hash)) {
20✔
398
                        $signer->hash = $endEntityCert['hash'];
10✔
399
                }
400
                if (isset($endEntityCert['serialNumber']) && !isset($signer->serialNumber)) {
20✔
401
                        $signer->serialNumber = $endEntityCert['serialNumber'];
10✔
402
                }
403
                if (isset($endEntityCert['serialNumberHex']) && !isset($signer->serialNumberHex)) {
20✔
404
                        $signer->serialNumberHex = $endEntityCert['serialNumberHex'];
5✔
405
                }
406
                if (isset($endEntityCert['signatureTypeSN']) && !isset($signer->signatureTypeSN)) {
20✔
407
                        $signer->signatureTypeSN = $endEntityCert['signatureTypeSN'];
1✔
408
                }
409

410
                if (isset($endEntityCert['subject']) && !isset($signer->subject)) {
20✔
411
                        $signer->subject = $endEntityCert['subject'];
20✔
412
                }
413

414
                if (isset($endEntityCert['crl_urls']) && !isset($signer->crl_urls)) {
20✔
415
                        $signer->crl_urls = $endEntityCert['crl_urls'];
1✔
416
                }
417
                if (isset($endEntityCert['crl_validation']) && !isset($signer->crl_validation)) {
20✔
418
                        $signer->crl_validation = $endEntityCert['crl_validation'];
2✔
419
                }
420
                if (isset($endEntityCert['crl_revoked_at']) && !isset($signer->crl_revoked_at)) {
20✔
421
                        $signer->crl_revoked_at = $endEntityCert['crl_revoked_at'];
1✔
422
                }
423

424
                if (isset($endEntityCert['signature_validation']) && !isset($signer->signature_validation)) {
20✔
425
                        $signer->signature_validation = $endEntityCert['signature_validation'];
1✔
426
                }
427

428
                if (isset($endEntityCert['isLibreSignRootCA']) && !isset($signer->isLibreSignRootCA)) {
20✔
429
                        $signer->isLibreSignRootCA = $endEntityCert['isLibreSignRootCA'];
6✔
430
                }
431
        }
432

433
        private function tryMatchWithExistingSigners(array $certData, array $existingSigners, string $host): ?string {
434
                if (empty($existingSigners)) {
20✔
435
                        return null;
8✔
436
                }
437

438
                $certSerialNumber = $certData['serialNumber'] ?? null;
12✔
439
                $certSerialNumberHex = $certData['serialNumberHex'] ?? null;
12✔
440
                $certHash = $certData['hash'] ?? null;
12✔
441

442
                if (!$certSerialNumber && !$certSerialNumberHex && !$certHash) {
12✔
443
                        return null;
2✔
444
                }
445

446
                foreach ($existingSigners as $signer) {
10✔
447
                        if (!isset($signer->metadata) || !is_array($signer->metadata)) {
10✔
448
                                continue;
3✔
449
                        }
450

451
                        $certInfo = $signer->metadata['certificate_info'] ?? null;
7✔
452
                        if (!is_array($certInfo)) {
7✔
453
                                continue;
×
454
                        }
455

456
                        if ($certSerialNumber && isset($certInfo['serialNumber'])) {
7✔
457
                                if ($certSerialNumber === $certInfo['serialNumber']) {
4✔
458
                                        return $signer->uid ?? $this->identifyMethodService->resolveUid($certData, $host);
3✔
459
                                }
460
                        }
461

462
                        if ($certSerialNumberHex && isset($certInfo['serialNumberHex'])) {
4✔
463
                                if ($certSerialNumberHex === $certInfo['serialNumberHex']) {
2✔
464
                                        return $signer->uid ?? $this->identifyMethodService->resolveUid($certData, $host);
1✔
465
                                }
466
                        }
467

468
                        if ($certHash && isset($certInfo['hash'])) {
3✔
469
                                if ($certHash === $certInfo['hash']) {
2✔
470
                                        return $signer->uid ?? $this->identifyMethodService->resolveUid($certData, $host);
1✔
471
                                }
472
                        }
473
                }
474

475
                return null;
5✔
476
        }
477

478
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc