Passed
Branch feature/php83 (cb5cde)
by Tim
14:20
created

AbstractSubjectConfirmationData::isEmptyElement()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 7
c 1
b 0
f 0
nc 7
nop 0
dl 0
loc 9
rs 8.8333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\saml;
6
7
use DOMElement;
8
use SimpleSAML\Assert\AssertionFailedException;
9
use SimpleSAML\SAML2\Assert\Assert;
10
use SimpleSAML\SAML2\Constants as C;
11
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
12
use SimpleSAML\SAML2\Type\EntityIDValue;
13
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
14
use SimpleSAML\SAML2\Type\SAMLStringValue;
15
use SimpleSAML\SAML2\Utils;
16
use SimpleSAML\XMLSchema\Type\NCNameValue;
17
use SimpleSAML\XMLSchema\XML\AbstractAnyType;
18
use SimpleSAML\XMLSchema\XML\Constants\NS;
19
20
use function strval;
21
22
/**
23
 * Abstract class representing SAML 2 SubjectConfirmationData element.
24
 *
25
 * @package simplesamlphp/saml2
26
 */
27
abstract class AbstractSubjectConfirmationData extends AbstractAnyType
28
{
29
    public const string NS = C::NS_SAML;
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 29 at column 24
Loading history...
30
31
    public const string NS_PREFIX = 'saml';
32
33
    public const string SCHEMA = 'resources/schemas/saml-schema-assertion-2.0.xsd';
34
35
    /** The namespace-attribute for the xs:any element */
36
    public const string XS_ANY_ELT_NAMESPACE = NS::ANY;
37
38
    /** The namespace-attribute for the xs:anyAttribute element */
39
    public const string XS_ANY_ATTR_NAMESPACE = NS::OTHER;
40
41
    /**
42
     * The exclusions for the xs:anyAttribute element
43
     *
44
     * @var array<int, array<int, string>>
45
     */
46
    public const array XS_ANY_ATTR_EXCLUSIONS = [
47
        ['urn:oasis:names:tc:SAML:2.0:assertion', '*'],
48
        ['urn:oasis:names:tc:SAML:2.0:protocol', '*'],
49
    ];
50
51
52
    /**
53
     * Initialize (and parse) a SubjectConfirmationData element.
54
     *
55
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notBefore
56
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $notOnOrAfter
57
     * @param \SimpleSAML\SAML2\Type\EntityIDValue|null $recipient
58
     * @param \SimpleSAML\XMLSchema\Type\NCNameValue|null $inResponseTo
59
     * @param \SimpleSAML\SAML2\Type\SAMLStringValue|null $address
60
     * @param \SimpleSAML\XML\SerializableElementInterface[] $children
61
     * @param list<\SimpleSAML\XML\Attribute> $namespacedAttributes
62
     */
63
    public function __construct(
64
        protected ?SAMLDateTimeValue $notBefore = null,
65
        protected ?SAMLDateTimeValue $notOnOrAfter = null,
66
        protected ?EntityIDValue $recipient = null,
67
        protected ?NCNameValue $inResponseTo = null,
68
        protected ?SAMLStringValue $address = null,
69
        array $children = [],
70
        array $namespacedAttributes = [],
71
    ) {
72
        /** SAML 2.0 Core specifications paragraph 2.4.1.2 */
73
        if ($notBefore !== null && $notOnOrAfter !== null) {
74
            Assert::true(
75
                $notBefore->toDateTime() < $notOnOrAfter->toDateTime(),
76
                "The value for NotBefore MUST be less than (earlier than) the value for NotOnOrAfter.",
77
                ProtocolViolationException::class,
78
            );
79
        }
80
81
        if ($address !== null) {
82
            try {
83
                /**
84
                 * IPv4 addresses SHOULD be represented in the usual dotted-decimal format (e.g., "1.2.3.4").
85
                 * IPv6 addresses SHOULD be represented as defined by Section 2.2 of IETF RFC 3513 [RFC 3513]
86
                 * (e.g., "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210").
87
                 */
88
                Assert::ip($address->getValue());
89
            } catch (AssertionFailedException) {
90
                Utils::getContainer()->getLogger()->warning(
91
                    sprintf('Provided address (%s) is not a valid IPv4 or IPv6  address.', $address->getValue()),
92
                );
93
            }
94
        }
95
96
        $this->setElements($children);
97
98
        foreach ($namespacedAttributes as $attr) {
99
            Assert::notNull(
100
                $attr->getNamespaceURI(),
101
                "Local (non-namespaced) attributes are not allowed.",
102
                ProtocolViolationException::class,
103
            );
104
        }
105
        $this->setAttributesNS($namespacedAttributes);
106
    }
107
108
109
    /**
110
     * Collect the value of the NotBefore-property
111
     *
112
     * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null
113
     */
114
    public function getNotBefore(): ?SAMLDateTimeValue
115
    {
116
        return $this->notBefore;
117
    }
118
119
120
    /**
121
     * Collect the value of the NotOnOrAfter-property
122
     *
123
     * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null
124
     */
125
    public function getNotOnOrAfter(): ?SAMLDateTimeValue
126
    {
127
        return $this->notOnOrAfter;
128
    }
129
130
131
    /**
132
     * Collect the value of the Recipient-property
133
     *
134
     * @return \SimpleSAML\SAML2\Type\EntityIDValue|null
135
     */
136
    public function getRecipient(): ?EntityIDValue
137
    {
138
        return $this->recipient;
139
    }
140
141
142
    /**
143
     * Collect the value of the InResponseTo-property
144
     *
145
     * @return \SimpleSAML\XMLSchema\Type\NCNameValue|null
146
     */
147
    public function getInResponseTo(): ?NCNameValue
148
    {
149
        return $this->inResponseTo;
150
    }
151
152
153
    /**
154
     * Collect the value of the Address-property
155
     *
156
     * @return \SimpleSAML\SAML2\Type\SAMLStringValue|null
157
     */
158
    public function getAddress(): ?SAMLStringValue
159
    {
160
        return $this->address;
161
    }
162
163
164
    /**
165
     * Test if an object, at the state it's in, would produce an empty XML-element
166
     */
167
    public function isEmptyElement(): bool
168
    {
169
        return empty($this->getNotBefore())
170
            && empty($this->getNotOnOrAfter())
171
            && empty($this->getRecipient())
172
            && empty($this->getInResponseTo())
173
            && empty($this->getAddress())
174
            && empty($this->getElements())
175
            && empty($this->getAttributesNS());
176
    }
177
178
179
    /**
180
     * Convert this element to XML.
181
     */
182
    public function toXML(?DOMElement $parent = null): DOMElement
183
    {
184
        $e = $this->instantiateParentElement($parent);
185
186
        if ($this->getNotBefore() !== null) {
187
            $e->setAttribute('NotBefore', strval($this->getNotBefore()));
188
        }
189
        if ($this->getNotOnOrAfter() !== null) {
190
            $e->setAttribute('NotOnOrAfter', strval($this->getNotOnOrAfter()));
191
        }
192
        if ($this->getRecipient() !== null) {
193
            $e->setAttribute('Recipient', strval($this->getRecipient()));
194
        }
195
        if ($this->getInResponseTo() !== null) {
196
            $e->setAttribute('InResponseTo', strval($this->getInResponseTo()));
197
        }
198
        if ($this->getAddress() !== null) {
199
            $e->setAttribute('Address', strval($this->getAddress()));
200
        }
201
202
        foreach ($this->getAttributesNS() as $attr) {
203
            $attr->toXML($e);
204
        }
205
206
        foreach ($this->getElements() as $n) {
207
            $n->toXML($e);
208
        }
209
210
        return $e;
211
    }
212
}
213