private static function processExtensions($element, $parentExtensions = array())
{
$ret = array('scope' => array(), 'tags' => array(), 'EntityAttributes' => array(), 'RegistrationInfo' => array(), 'UIInfo' => array(), 'DiscoHints' => array());
// Some extensions may get inherited from a parent element
if (($element instanceof \SAML2\XML\md\EntityDescriptor || $element instanceof \SAML2\XML\md\EntitiesDescriptor) && !empty($parentExtensions['RegistrationInfo'])) {
$ret['RegistrationInfo'] = $parentExtensions['RegistrationInfo'];
}
foreach ($element->Extensions as $e) {
if ($e instanceof \SAML2\XML\shibmd\Scope) {
$ret['scope'][] = $e->scope;
continue;
}
// Entity Attributes are only allowed at entity level extensions and not at RoleDescriptor level
if ($element instanceof \SAML2\XML\md\EntityDescriptor || $element instanceof \SAML2\XML\md\EntitiesDescriptor) {
if ($e instanceof \SAML2\XML\mdrpi\RegistrationInfo) {
// Registration Authority cannot be overridden (warn only if override attempts to change the value)
if (isset($ret['RegistrationInfo']['registrationAuthority']) && $ret['RegistrationInfo']['registrationAuthority'] !== $e->registrationAuthority) {
SimpleSAML\Logger::warning('Invalid attempt to override registrationAuthority \'' . $ret['RegistrationInfo']['registrationAuthority'] . "' with '{$e->registrationAuthority}'");
} else {
$ret['RegistrationInfo']['registrationAuthority'] = $e->registrationAuthority;
}
}
if ($e instanceof \SAML2\XML\mdattr\EntityAttributes && !empty($e->children)) {
foreach ($e->children as $attr) {
// only saml:Attribute are currently supported here. The specifications also allows
// saml:Assertions, which more complex processing
if ($attr instanceof \SAML2\XML\saml\Attribute) {
if (empty($attr->Name) || empty($attr->AttributeValue)) {
continue;
}
// attribute names that is not URI is prefixed as this: '{nameformat}name'
$name = $attr->Name;
if (empty($attr->NameFormat)) {
$name = '{' . \SAML2\Constants::NAMEFORMAT_UNSPECIFIED . '}' . $attr->Name;
} elseif ($attr->NameFormat !== 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') {
$name = '{' . $attr->NameFormat . '}' . $attr->Name;
}
$values = array();
foreach ($attr->AttributeValue as $attrvalue) {
$values[] = $attrvalue->getString();
}
$ret['EntityAttributes'][$name] = $values;
}
}
}
}
// UIInfo elements are only allowed at RoleDescriptor level extensions
if ($element instanceof \SAML2\XML\md\RoleDescriptor) {
if ($e instanceof \SAML2\XML\mdui\UIInfo) {
$ret['UIInfo']['DisplayName'] = $e->DisplayName;
$ret['UIInfo']['Description'] = $e->Description;
$ret['UIInfo']['InformationURL'] = $e->InformationURL;
$ret['UIInfo']['PrivacyStatementURL'] = $e->PrivacyStatementURL;
foreach ($e->Keywords as $uiItem) {
if (!$uiItem instanceof \SAML2\XML\mdui\Keywords || empty($uiItem->Keywords) || empty($uiItem->lang)) {
continue;
}
$ret['UIInfo']['Keywords'][$uiItem->lang] = $uiItem->Keywords;
}
foreach ($e->Logo as $uiItem) {
if (!$uiItem instanceof \SAML2\XML\mdui\Logo || empty($uiItem->url) || empty($uiItem->height) || empty($uiItem->width)) {
continue;
}
$logo = array('url' => $uiItem->url, 'height' => $uiItem->height, 'width' => $uiItem->width);
if (!empty($uiItem->lang)) {
$logo['lang'] = $uiItem->lang;
}
$ret['UIInfo']['Logo'][] = $logo;
}
}
}
// DiscoHints elements are only allowed at IDPSSODescriptor level extensions
if ($element instanceof \SAML2\XML\md\IDPSSODescriptor) {
if ($e instanceof \SAML2\XML\mdui\DiscoHints) {
$ret['DiscoHints']['IPHint'] = $e->IPHint;
$ret['DiscoHints']['DomainHint'] = $e->DomainHint;
$ret['DiscoHints']['GeolocationHint'] = $e->GeolocationHint;
}
}
if (!$e instanceof \SAML2\XML\Chunk) {
continue;
}
if ($e->localName === 'Attribute' && $e->namespaceURI === \SAML2\Constants::NS_SAML) {
$attribute = $e->getXML();
$name = $attribute->getAttribute('Name');
$values = array_map(array('SimpleSAML\\Utils\\XML', 'getDOMText'), SimpleSAML\Utils\XML::getDOMChildren($attribute, 'AttributeValue', '@saml2'));
if ($name === 'tags') {
foreach ($values as $tagname) {
if (!empty($tagname)) {
$ret['tags'][] = $tagname;
}
}
}
}
}
return $ret;
}