summaryrefslogtreecommitdiffstats
path: root/lib/SAML2/AttributeQuery.php
blob: 3be052bd3ede6db884d7f46ab916b5b3f7ce0b52 (plain)
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
<?php

/**
 * Class for SAML 2 attribute query messages.
 *
 * An attribute query asks for a set of attributes. The following
 * rules apply:
 *
 * - If no attributes are present in the query, all attributes should be
 *   returned.
 * - If any attributes are present, only those attributes which are present
 *   in the query should be returned.
 * - If an attribute contains any attribute values, only the attribute values
 *   which match those in the query should be returned.
 *
 * @package simpleSAMLphp
 * @version $Id$
 */
class SAML2_AttributeQuery extends SAML2_SubjectQuery {


	/**
	 * The attributes, as an associative array.
	 *
	 * @var array
	 */
	private $attributes;


	/**
	 * The NameFormat used on all attributes.
	 *
	 * If more than one NameFormat is used, this will contain
	 * the unspecified nameformat.
	 *
	 * @var string
	 */
	private $nameFormat;


	/**
	 * Constructor for SAML 2 attribute query messages.
	 *
	 * @param DOMElement|NULL $xml  The input message.
	 */
	public function __construct(DOMElement $xml = NULL) {
		parent::__construct('AttributeQuery', $xml);

		$this->attributes = array();
		$this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED;

		if ($xml === NULL) {
			return;
		}

		$firstAttribute = TRUE;
		$attributes = SAML2_Utils::xpQuery($xml, './saml:Attribute');
		foreach ($attributes as $attribute) {
			if (!$attribute->hasAttribute('Name')) {
				throw new Exception('Missing name on <saml:Attribute> element.');
			}
			$name = $attribute->getAttribute('Name');

			if ($attribute->hasAttribute('NameFormat')) {
				$nameFormat = $attribute->getAttribute('NameFormat');
			} else {
				$nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED;
			}

			if ($firstAttribute) {
				$this->nameFormat = $nameFormat;
				$firstAttribute = FALSE;
			} else {
				if ($this->nameFormat !== $nameFormat) {
					$this->nameFormat = SAML2_Const::NAMEFORMAT_UNSPECIFIED;
				}
			}

			if (!array_key_exists($name, $this->attributes)) {
				$this->attributes[$name] = array();
			}

			$values = SAML2_Utils::xpQuery($attribute, './saml:AttributeValue');
			foreach ($values as $value) {
				$this->attributes[$name][] = trim($value->textContent);
			}
		}
	}


	/**
	 * Retrieve all requested attributes.
	 *
	 * @return array  All requested attributes, as an associative array.
	 */
	public function getAttributes() {

		return $this->attributes;
	}


	/**
	 * Set all requested attributes.
	 *
	 * @param array $attributes  All requested attributes, as an associative array.
	 */
	public function setAttributes(array $attributes) {

		$this->attributes = $attributes;
	}


	/**
	 * Retrieve the NameFormat used on all attributes.
	 *
	 * If more than one NameFormat is used in the received attributes, this
	 * returns the unspecified NameFormat.
	 *
	 * @return string  The NameFormat used on all attributes.
	 */
	public function getAttributeNameFormat() {
		return $this->nameFormat;
	}


	/**
	 * Set the NameFormat used on all attributes.
	 *
	 * @param string $nameFormat  The NameFormat used on all attributes.
	 */
	public function setAttributeNameFormat($nameFormat) {
		assert('is_string($nameFormat)');

		$this->nameFormat = $nameFormat;
	}


	/**
	 * Convert the attribute query message to an XML element.
	 *
	 * @return DOMElement  This attribute query.
	 */
	public function toUnsignedXML() {

		$root = parent::toUnsignedXML();

		foreach ($this->attributes as $name => $values) {
			$attribute = $root->ownerDocument->createElementNS(SAML2_Const::NS_SAML, 'saml:Attribute');
			$root->appendChild($attribute);
			$attribute->setAttribute('Name', $name);

			if ($this->nameFormat !== SAML2_Const::NAMEFORMAT_UNSPECIFIED) {
				$attribute->setAttribute('NameFormat', $this->nameFormat);
			}

			foreach ($values as $value) {
				if (is_string($value)) {
					$type = 'xs:string';
				} elseif (is_int($value)) {
					$type = 'xs:integer';
				} else {
					$type = NULL;
				}

				$attributeValue = $root->ownerDocument->createElementNS(SAML2_Const::NS_SAML, 'saml:AttributeValue');
				$attribute->appendChild($attributeValue);
				if ($type !== NULL) {
					$attributeValue->setAttributeNS(SAML2_Const::NS_XSI, 'xsi:type', $type);
				}
				$attributeValue->appendChild($root->ownerDocument->createTextNode($value));
			}
		}

		return $root;
	}


}