Passed
Push — master ( 087c8d...44e79a )
by Tim
02:20
created

SubjectConfirmationData::fromXML()   B

Complexity

Conditions 7
Paths 16

Size

Total Lines 48
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 33
c 1
b 0
f 0
nc 16
nop 1
dl 0
loc 48
rs 8.4586
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\saml;
6
7
use DateTimeImmutable;
8
use DOMElement;
9
use SimpleSAML\Assert\Assert;
10
use SimpleSAML\SAML2\Constants as C;
11
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
12
use SimpleSAML\SAML2\Utils;
13
use SimpleSAML\XML\Chunk;
14
use SimpleSAML\XML\Exception\InvalidDOMElementException;
15
use SimpleSAML\XML\ExtendableAttributesTrait;
16
use SimpleSAML\XML\ExtendableElementTrait;
17
use SimpleSAML\XMLSecurity\XML\ds\KeyInfo;
18
19
use function filter_var;
20
use function gmdate;
21
use function is_null;
22
23
/**
24
 * Class representing SAML 2 SubjectConfirmationData element.
25
 *
26
 * @package simplesamlphp/saml2
27
 */
28
final class SubjectConfirmationData extends AbstractSamlElement
29
{
30
    use ExtendableAttributesTrait;
1 ignored issue
show
introduced by
The trait SimpleSAML\XML\ExtendableAttributesTrait requires some properties which are not provided by SimpleSAML\SAML2\XML\saml\SubjectConfirmationData: $localName, $nodeValue, $namespaceURI, $prefix, $attributes
Loading history...
31
    use ExtendableElementTrait;
32
33
    /** The namespace-attribute for the xs:any element */
34
    public const XS_ANY_ELT_NAMESPACE = C::XS_ANY_NS_ANY;
35
36
    /** The namespace-attribute for the xs:anyAttribute element */
37
    public const XS_ANY_ATTR_NAMESPACE = C::XS_ANY_NS_OTHER;
38
39
40
    /**
41
     * Initialize (and parse) a SubjectConfirmationData element.
42
     *
43
     * @param \DateTimeImmutable|null $notBefore
44
     * @param \DateTimeImmutable|null $notOnOrAfter
45
     * @param string|null $recipient
46
     * @param string|null $inResponseTo
47
     * @param string|null $address
48
     * @param \SimpleSAML\XML\SerializableElementInterface[] $children
49
     * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\saml\list was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
50
     */
51
    public function __construct(
52
        protected ?DateTimeImmutable $notBefore = null,
53
        protected ?DateTimeImmutable $notOnOrAfter = null,
54
        protected ?string $recipient = null,
55
        protected ?string $inResponseTo = null,
56
        protected ?string $address = null,
57
        array $children = [],
58
        array $namespacedAttributes = [],
59
    ) {
60
        Assert::nullOrSame($notBefore?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class);
61
        Assert::nullOrSame($notOnOrAfter?->getTimeZone()->getName(), 'Z', ProtocolViolationException::class);
62
        Assert::nullOrNotWhitespaceOnly($recipient);
63
        Assert::nullOrValidNCName($inResponseTo); // Covers the empty string
64
65
        if (!is_null($address) && !filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_IPV6)) {
66
            Utils::getContainer()->getLogger()->warning(
67
                sprintf('Provided argument (%s) is not a valid IP address.', $address),
68
            );
69
        }
70
71
        $this->setElements($children);
72
        $this->setAttributesNS($namespacedAttributes);
73
    }
74
75
76
    /**
77
     * Collect the value of the NotBefore-property
78
     *
79
     * @return \DateTimeImmutable|null
80
     */
81
    public function getNotBefore(): ?DateTimeImmutable
82
    {
83
        return $this->notBefore;
84
    }
85
86
87
    /**
88
     * Collect the value of the NotOnOrAfter-property
89
     *
90
     * @return \DateTimeImmutable|null
91
     */
92
    public function getNotOnOrAfter(): ?DateTimeImmutable
93
    {
94
        return $this->notOnOrAfter;
95
    }
96
97
98
    /**
99
     * Collect the value of the Recipient-property
100
     *
101
     * @return string|null
102
     */
103
    public function getRecipient(): ?string
104
    {
105
        return $this->recipient;
106
    }
107
108
109
    /**
110
     * Collect the value of the InResponseTo-property
111
     *
112
     * @return string|null
113
     */
114
    public function getInResponseTo(): ?string
115
    {
116
        return $this->inResponseTo;
117
    }
118
119
120
    /**
121
     * Collect the value of the Address-property
122
     *
123
     * @return string|null
124
     */
125
    public function getAddress(): ?string
126
    {
127
        return $this->address;
128
    }
129
130
131
    /**
132
     * Test if an object, at the state it's in, would produce an empty XML-element
133
     *
134
     * @return bool
135
     */
136
    public function isEmptyElement(): bool
137
    {
138
        return empty($this->notBefore)
139
            && empty($this->notOnOrAfter)
140
            && empty($this->recipient)
141
            && empty($this->inResponseTo)
142
            && empty($this->address)
143
            && empty($this->elements)
144
            && empty($this->namespacedAttributes);
145
    }
146
147
148
    /**
149
     * Convert XML into a SubjectConfirmationData
150
     *
151
     * @param \DOMElement $xml The XML element we should load
152
     * @return static
153
     *
154
     * @throws \SimpleSAML\XML\Exception\InvalidDOMElementException
155
     *   if the qualified name of the supplied element is wrong
156
     * @throws \SimpleSAML\XML\Exception\MissingAttributeException
157
     *   if the supplied element is missing any of the mandatory attributes
158
     * @throws \SimpleSAML\Assert\AssertionFailedException
159
     *   if NotBefore or NotOnOrAfter contain an invalid date.
160
     */
161
    public static function fromXML(DOMElement $xml): static
162
    {
163
        Assert::same($xml->localName, 'SubjectConfirmationData', InvalidDOMElementException::class);
164
        Assert::same($xml->namespaceURI, SubjectConfirmationData::NS, InvalidDOMElementException::class);
165
166
        $NotBefore = self::getOptionalAttribute($xml, 'NotBefore', null);
167
        if ($NotBefore !== null) {
168
            // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
169
            $NotBefore = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotBefore, 1);
170
171
            Assert::validDateTimeZulu($NotBefore, ProtocolViolationException::class);
172
            $NotBefore = new DateTimeImmutable($NotBefore);
173
        }
174
175
        $NotOnOrAfter = self::getOptionalAttribute($xml, 'NotOnOrAfter', null);
176
        if ($NotOnOrAfter !== null) {
177
            // Strip sub-seconds - See paragraph 1.3.3 of SAML core specifications
178
            $NotOnOrAfter = preg_replace('/([.][0-9]+Z)$/', 'Z', $NotOnOrAfter, 1);
179
180
            Assert::validDateTimeZulu($NotOnOrAfter, ProtocolViolationException::class);
181
            $NotOnOrAfter = new DateTimeImmutable($NotOnOrAfter);
182
        }
183
184
        $Recipient = self::getOptionalAttribute($xml, 'Recipient', null);
185
        $InResponseTo = self::getOptionalAttribute($xml, 'InResponseTo', null);
186
        $Address = self::getOptionalAttribute($xml, 'Address', null);
187
188
        $children = [];
189
        foreach ($xml->childNodes as $n) {
190
            if (!($n instanceof DOMElement)) {
191
                continue;
192
            } elseif ($n->namespaceURI === C::NS_XDSIG && $n->localName === 'KeyInfo') {
193
                $children[] = KeyInfo::fromXML($n);
194
                continue;
195
            } else {
196
                $children[] = new Chunk($n);
197
                continue;
198
            }
199
        }
200
201
        return new static(
202
            $NotBefore,
203
            $NotOnOrAfter,
204
            $Recipient,
205
            $InResponseTo,
206
            $Address,
207
            $children,
208
            self::getAttributesNSFromXML($xml),
209
        );
210
    }
211
212
213
    /**
214
     * Convert this element to XML.
215
     *
216
     * @param  \DOMElement|null $parent The parent element we should append this element to.
217
     * @return \DOMElement This element, as XML.
218
     */
219
    public function toXML(DOMElement $parent = null): DOMElement
220
    {
221
        $e = $this->instantiateParentElement($parent);
222
223
        if ($this->getNotBefore() !== null) {
224
            $e->setAttribute('NotBefore', $this->getNotBefore()->format(C::DATETIME_FORMAT));
225
        }
226
        if ($this->getNotOnOrAfter() !== null) {
227
            $e->setAttribute('NotOnOrAfter', $this->getNotOnOrAfter()->format(C::DATETIME_FORMAT));
228
        }
229
        if ($this->getRecipient() !== null) {
230
            $e->setAttribute('Recipient', $this->getRecipient());
231
        }
232
        if ($this->getInResponseTo() !== null) {
233
            $e->setAttribute('InResponseTo', $this->getInResponseTo());
234
        }
235
        if ($this->getAddress() !== null) {
236
            $e->setAttribute('Address', $this->getAddress());
237
        }
238
239
        foreach ($this->getAttributesNS() as $attr) {
240
            $attr->toXML($e);
241
        }
242
243
        foreach ($this->getElements() as $n) {
244
            $n->toXML($e);
245
        }
246
247
        return $e;
248
    }
249
}
250