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

LibreSign / libresign / 21967842076

12 Feb 2026 11:09PM UTC coverage: 51.292%. First build
21967842076

Pull #6824

github

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

217 of 241 new or added lines in 21 files covered. (90.04%)

8989 of 17525 relevant lines covered (51.29%)

6.03 hits per line

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

86.76
/lib/Service/SubjectAlternativeNameService.php
1
<?php
2

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

9
namespace OCA\Libresign\Service;
10

11
use OCP\IUserManager;
12

13
/**
14
 * Service to handle Subject Alternative Name (SAN) according to RFC 5280 Section 4.2.1.6
15
 */
16
class SubjectAlternativeNameService {
17
        public function __construct(
18
                private IUserManager $userManager,
19
        ) {
20
        }
110✔
21

22
        public function parseFromCertificate(array $certificateData): ?array {
23
                if (empty($certificateData['extensions']['subjectAltName'])) {
7✔
24
                        return null;
1✔
25
                }
26

27
                $subjectAltName = $certificateData['extensions']['subjectAltName'];
6✔
28
                if (is_array($subjectAltName)) {
6✔
29
                        $subjectAltName = $subjectAltName[0];
1✔
30
                }
31

32
                return $this->parse((string)$subjectAltName);
6✔
33
        }
34

35
        protected function parse(string $subjectAltName): ?array {
36
                $pattern = '/^(?<method>' . implode('|', IdentifyMethodService::IDENTIFY_METHODS) . '):(?<value>.+)$/';
20✔
37

38
                if (preg_match($pattern, $subjectAltName, $matches)) {
20✔
39
                        return [
16✔
40
                                'method' => $matches['method'],
16✔
41
                                'value' => $matches['value'],
16✔
42
                        ];
16✔
43
                }
44

45
                if (filter_var($subjectAltName, FILTER_VALIDATE_EMAIL)) {
4✔
46
                        return [
1✔
47
                                'method' => IdentifyMethodService::IDENTIFY_EMAIL,
1✔
48
                                'value' => $subjectAltName,
1✔
49
                        ];
1✔
50
                }
51

52
                return null;
3✔
53
        }
54

55
        public function build(string $method, string $value): string {
56
                return $method . ':' . $value;
14✔
57
        }
58

59
        public function buildForHosts(array $hosts): string {
60
                $altNames = [];
60✔
61
                foreach ($hosts as $host) {
60✔
62
                        if (filter_var($host, FILTER_VALIDATE_EMAIL)) {
5✔
63
                                $altNames[] = $this->build(IdentifyMethodService::IDENTIFY_EMAIL, $host);
4✔
64
                        }
65
                }
66
                return implode(', ', $altNames);
60✔
67
        }
68

69
        public function resolveUid(array $certificateData, string $host): ?string {
70
                if (!empty($certificateData['subject']['CN'])) {
5✔
71
                        $cn = $certificateData['subject']['CN'];
1✔
72
                        if (is_array($cn)) {
1✔
NEW
73
                                $cn = $cn[0];
×
74
                        }
75
                        $pattern = '/^(?<method>' . implode('|', IdentifyMethodService::IDENTIFY_METHODS) . '):(?<value>.*), /';
1✔
76
                        if (preg_match($pattern, (string)$cn, $matches)) {
1✔
77
                                return $matches['method'] . ':' . $matches['value'];
1✔
78
                        }
79
                }
80

81
                $parsed = $this->parseFromCertificate($certificateData);
4✔
82
                if (!$parsed) {
4✔
NEW
83
                        return null;
×
84
                }
85

86
                $method = $parsed['method'];
4✔
87
                $value = $parsed['value'];
4✔
88

89
                if (in_array($method, [IdentifyMethodService::IDENTIFY_EMAIL, IdentifyMethodService::IDENTIFY_ACCOUNT], true)) {
4✔
90
                        if (str_ends_with($value, $host)) {
3✔
91
                                $uid = str_replace('@' . $host, '', $value);
3✔
92
                                $user = $this->userManager->get($uid);
3✔
93
                                if ($user) {
3✔
94
                                        return IdentifyMethodService::IDENTIFY_ACCOUNT . ':' . $uid;
1✔
95
                                }
96

97
                                $users = $this->userManager->getByEmail($value);
2✔
98
                                if (!empty($users)) {
2✔
99
                                        $user = current($users);
1✔
100
                                        return IdentifyMethodService::IDENTIFY_ACCOUNT . ':' . $user->getUID();
1✔
101
                                }
102

103
                                return IdentifyMethodService::IDENTIFY_EMAIL . ':' . $value;
1✔
104
                        }
105

NEW
106
                        $users = $this->userManager->getByEmail($value);
×
NEW
107
                        if (!empty($users)) {
×
NEW
108
                                $user = current($users);
×
NEW
109
                                return IdentifyMethodService::IDENTIFY_ACCOUNT . ':' . $user->getUID();
×
110
                        }
111

NEW
112
                        $user = $this->userManager->get($value);
×
NEW
113
                        if ($user) {
×
NEW
114
                                return IdentifyMethodService::IDENTIFY_ACCOUNT . ':' . $user->getUID();
×
115
                        }
116
                }
117

118
                return $this->build($method, $value);
1✔
119
        }
120

121
        private function extractEmail(string $subjectAltName): ?string {
122
                if (preg_match('/(?:email:)+(?<email>[^\s,]+)/', $subjectAltName, $matches)) {
6✔
123
                        if (filter_var($matches['email'], FILTER_VALIDATE_EMAIL)) {
4✔
124
                                return $matches['email'];
3✔
125
                        }
126
                }
127

128
                if (filter_var($subjectAltName, FILTER_VALIDATE_EMAIL)) {
3✔
129
                        return $subjectAltName;
1✔
130
                }
131

132
                return null;
2✔
133
        }
134

135
        public function extractEmailFromCertificate(array $certificateData): ?string {
136
                if (empty($certificateData['extensions']['subjectAltName'])) {
9✔
137
                        return null;
3✔
138
                }
139

140
                $subjectAltName = $certificateData['extensions']['subjectAltName'];
6✔
141
                if (is_array($subjectAltName)) {
6✔
142
                        $subjectAltName = $subjectAltName[0];
1✔
143
                }
144

145
                return $this->extractEmail((string)$subjectAltName);
6✔
146
        }
147
}
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