File: AttributeMap.php

package info (click to toggle)
simplesamlphp 1.19.7-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 42,920 kB
  • sloc: php: 202,044; javascript: 14,867; xml: 2,700; sh: 225; perl: 82; makefile: 70; python: 5
file content (156 lines) | stat: -rw-r--r-- 4,833 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<?php

declare(strict_types=1);

namespace SimpleSAML\Module\core\Auth\Process;

use SimpleSAML\Configuration;
use SimpleSAML\Module;

/**
 * Attribute filter for renaming attributes.
 *
 * @author Olav Morken, UNINETT AS.
 * @package SimpleSAMLphp
 */
class AttributeMap extends \SimpleSAML\Auth\ProcessingFilter
{
    /**
     * Associative array with the mappings of attribute names.
     * @var array
     */
    private $map = [];

    /**
     * Should attributes be duplicated or renamed.
     * @var bool
     */
    private $duplicate = false;


    /**
     * Initialize this filter, parse configuration
     *
     * @param array &$config Configuration information about this filter.
     * @param mixed $reserved For future use.
     *
     * @throws \Exception If the configuration of the filter is wrong.
     */
    public function __construct(&$config, $reserved)
    {
        parent::__construct($config, $reserved);

        assert(is_array($config));
        $mapFiles = [];

        foreach ($config as $origName => $newName) {
            if (is_int($origName)) {
                if ($newName === '%duplicate') {
                    $this->duplicate = true;
                } else {
                    // no index given, this is a map file
                    $mapFiles[] = $newName;
                }
                continue;
            }

            if (!is_string($origName)) {
                throw new \Exception('Invalid attribute name: ' . var_export($origName, true));
            }

            if (!is_string($newName) && !is_array($newName)) {
                throw new \Exception('Invalid attribute name: ' . var_export($newName, true));
            }

            $this->map[$origName] = $newName;
        }

        // load map files after we determine duplicate or rename
        foreach ($mapFiles as &$file) {
            $this->loadMapFile($file);
        }
    }


    /**
     * Loads and merges in a file with a attribute map.
     *
     * @param string $fileName Name of attribute map file. Expected to be in the attributemap directory in the root
     * of the SimpleSAMLphp installation, or in the root of a module.
     *
     * @throws \Exception If the filter could not load the requested attribute map file.
     * @return void
     */
    private function loadMapFile(string $fileName): void
    {
        $config = Configuration::getInstance();

        $m = explode(':', $fileName);
        if (count($m) === 2) {
            // we are asked for a file in a module
            if (!Module::isModuleEnabled($m[0])) {
                throw new \Exception("Module '$m[0]' is not enabled.");
            }
            $filePath = Module::getModuleDir($m[0]) . '/attributemap/' . $m[1] . '.php';
        } else {
            $attributenamemapdir = $config->getPathValue('attributenamemapdir', 'attributemap/') ?: 'attributemap/';
            $filePath = $attributenamemapdir . $fileName . '.php';
        }

        if (!file_exists($filePath)) {
            throw new \Exception('Could not find attribute map file: ' . $filePath);
        }

        $attributemap = null;
        include($filePath);
        if (!is_array($attributemap)) {
            throw new \Exception('Attribute map file "' . $filePath . '" didn\'t define an attribute map.');
        }

        if ($this->duplicate) {
            $this->map = array_merge_recursive($this->map, $attributemap);
        } else {
            $this->map = array_merge($this->map, $attributemap);
        }
    }


    /**
     * Apply filter to rename attributes.
     *
     * @param array &$request The current request.
     * @return void
     */
    public function process(&$request)
    {
        assert(is_array($request));
        assert(array_key_exists('Attributes', $request));

        $mapped_attributes = [];

        foreach ($request['Attributes'] as $name => $values) {
            if (array_key_exists($name, $this->map)) {
                if (!is_array($this->map[$name])) {
                    if ($this->duplicate) {
                        $mapped_attributes[$name] = $values;
                    }
                    $mapped_attributes[$this->map[$name]] = $values;
                } else {
                    foreach ($this->map[$name] as $to_map) {
                        $mapped_attributes[$to_map] = $values;
                    }
                    if ($this->duplicate && !in_array($name, $this->map[$name], true)) {
                        $mapped_attributes[$name] = $values;
                    }
                }
            } else {
                if (array_key_exists($name, $mapped_attributes)) {
                    continue;
                }
                $mapped_attributes[$name] = $values;
            }
        }

        $request['Attributes'] = $mapped_attributes;
    }
}