Passed
Pull Request — master (#305)
by Jaime Pérez
02:19
created

AbstractContainer   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 170
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 23
c 3
b 0
f 0
dl 0
loc 170
rs 10
wmc 9

4 Methods

Rating   Name   Duplication   Size   Complexity  
A getBlacklistedEncryptionAlgorithms() 0 3 1
A getElementHandler() 0 11 3
A getExtensionHandler() 0 9 2
A registerExtensionHandler() 0 10 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\Compat;
6
7
use Psr\Log\LoggerInterface;
8
use SimpleSAML\Assert\Assert;
9
use SimpleSAML\XML\AbstractXMLElement;
10
use SimpleSAML\XML\Exception\SchemaViolationException;
11
use SimpleSAML\SAML2\XML\ExtensionPointInterface;
12
13
use function array_key_exists;
14
use function is_subclass_of;
15
use function implode;
16
17
abstract class AbstractContainer
18
{
19
    /** @var string */
20
    private const XSI_TYPE_PREFIX = '<xsi:type>';
21
22
    /** @var array */
23
    public array $registry = [];
24
25
    /** @var array|null */
26
    protected ?array $blacklistedEncryptionAlgorithms;
27
28
29
    /**
30
     * Set the list of algorithms that are blacklisted for any encryption operation.
31
     *
32
     * @param string[]|null $algos An array with all algorithm identifiers that are blacklisted,
33
     * or null if we want to use the defaults.
34
     */
35
    abstract public function setBlacklistedAlgorithms(?array $algos): void;
36
37
38
    /**
39
     * Get the list of algorithms that are blacklisted for any encryption operation.
40
     *
41
     * @return string[]|null An array with all algorithm identifiers that are blacklisted, or null if we want to use the
42
     * defaults.
43
     */
44
    public function getBlacklistedEncryptionAlgorithms(): ?array
45
    {
46
        return $this->blacklistedEncryptionAlgorithms;
47
    }
48
49
50
    /**
51
     * Get a PSR-3 compatible logger.
52
     * @return \Psr\Log\LoggerInterface
53
     */
54
    abstract public function getLogger(): LoggerInterface;
55
56
57
    /**
58
     * Generate a random identifier for identifying SAML2 documents.
59
     * @return string
60
     */
61
    abstract public function generateId(): string;
62
63
64
    /**
65
     * Log an incoming message to the debug log.
66
     *
67
     * Type can be either:
68
     * - **in** XML received from third party
69
     * - **out** XML that will be sent to third party
70
     * - **encrypt** XML that is about to be encrypted
71
     * - **decrypt** XML that was just decrypted
72
     *
73
     * @param \DOMElement|string $message
74
     * @param string $type
75
     */
76
    abstract public function debugMessage($message, string $type): void;
77
78
79
    /**
80
     * Trigger the user to perform a GET to the given URL with the given data.
81
     *
82
     * @param string $url
83
     * @param array $data
84
     */
85
    abstract public function redirect(string $url, array $data = []): void;
86
87
88
    /**
89
     * Trigger the user to perform a POST to the given URL with the given data.
90
     *
91
     * @param string $url
92
     * @param array $data
93
     */
94
    abstract public function postRedirect(string $url, array $data = []): void;
95
96
97
    /**
98
     * This function retrieves the path to a directory where temporary files can be saved.
99
     *
100
     * @throws \Exception If the temporary directory cannot be created or it exists and does not belong
101
     * to the current user.
102
     * @return string Path to a temporary directory, without a trailing directory separator.
103
     */
104
    abstract public function getTempDir(): string;
105
106
107
    /**
108
     * Atomically write a file.
109
     *
110
     * This is a helper function for writing data atomically to a file. It does this by writing the file data to a
111
     * temporary file, then renaming it to the required file name.
112
     *
113
     * @param string $filename The path to the file we want to write to.
114
     * @param string $data The data we should write to the file.
115
     * @param int|null $mode The permissions to apply to the file. Defaults to 0600.
116
     */
117
    abstract public function writeFile(string $filename, string $data, int $mode = null): void;
118
119
120
    /**
121
     * Register a class that can handle given extension points of the standard.
122
     *
123
     * @param string $class The class name of a class extending AbstractXMLElement or implementing ExtensionPointInterface.
124
     * @psalm-param class-string $class
125
     */
126
    public function registerExtensionHandler(string $class): void
127
    {
128
        Assert::subclassOf($class, AbstractXMLElement::class);
129
        if (is_subclass_of($class, ExtensionPointInterface::class, true)) {
130
            $key = implode(':', [self::XSI_TYPE_PREFIX, $class::getXsiTypeNamespaceURI(), $class::getXsiTypeName()]);
131
        } else {
132
            $className = AbstractXMLElement::getClassName($class);
133
            $key = ($class::NS === null) ? $className : implode(':', [$class::NS, $className]);
134
        }
135
        $this->registry[$key] = $class;
136
    }
137
138
139
    /**
140
     * Search for a class that implements an $element in the given $namespace.
141
     *
142
     * Such classes must have been registered previously by calling registerExtensionHandler(), and they must
143
     * extend \SimpleSAML\XML\AbstractXMLElement.
144
     *
145
     * @param string|null $namespace The namespace URI for the given element.
146
     * @param string $element The local name of the element.
147
     *
148
     * @return string|null The fully-qualified name of a class extending \SimpleSAML\XML\AbstractXMLElement and
149
     * implementing support for the given element, or null if no such class has been registered before.
150
     * @psalm-return class-string|null
151
     */
152
    public function getElementHandler(?string $namespace, string $element): ?string
153
    {
154
        Assert::nullOrValidURI($namespace, SchemaViolationException::class);
155
        Assert::validNCName($element, SchemaViolationException::class);
156
157
        $key = ($namespace === null) ? $element : implode(':', [$namespace, $element]);
158
        if (array_key_exists($key, $this->registry) === true) {
159
            return $this->registry[$key];
160
        }
161
162
        return null;
163
    }
164
165
166
    /**
167
     * Search for a class that implements a custom element type.
168
     *
169
     * Such classes must have been registered previously by calling registerExtensionHandler(), and they must
170
     * implement \SimpleSAML\SAML2\XML\saml\ExtensionPointInterface.
171
     *
172
     * @param string $type The type of the identifier (xsi:type of a BaseID element).
173
     *
174
     * @return string|null The fully-qualified name of a class implementing
175
     *  \SimpleSAML\SAML2\XML\saml\ExtensionPointInterface or null if no such class has been registered before.
176
     * @psalm-return class-string|null
177
     */
178
    public function getExtensionHandler(string $type): ?string
179
    {
180
        Assert::notEmpty($type, 'Cannot search for identifier handlers with an empty type.');
181
        $type = implode(':', [self::XSI_TYPE_PREFIX, $type]);
182
        if (!array_key_exists($type, $this->registry)) {
183
            return null;
184
        }
185
        Assert::implementsInterface($this->registry[$type], ExtensionPointInterface::class);
186
        return $this->registry[$type];
187
    }
188
}
189