From 29df83c706eb300a16cda516a501f7f536df8ed2 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Wed, 22 Feb 2012 17:55:33 +0000 Subject: [PATCH] https://issues.shibboleth.net/jira/browse/CPPOST-73 --- .../impl/EntityAttributesMetadataFilter.cpp | 160 +++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp diff --git a/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp b/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp new file mode 100644 index 0000000..407fd81 --- /dev/null +++ b/saml/saml2/metadata/impl/EntityAttributesMetadataFilter.cpp @@ -0,0 +1,160 @@ +/** + * Licensed to the University Corporation for Advanced Internet + * Development, Inc. (UCAID) under one or more contributor license + * agreements. See the NOTICE file distributed with this work for + * additional information regarding copyright ownership. + * + * UCAID licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the + * License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the License. + */ + +/** + * EntityAttributesMetadataFilter.cpp + * + * Adds EntityAttributes tags to entities. + */ + +#include "internal.h" +#include "saml2/metadata/Metadata.h" +#include "saml2/metadata/MetadataFilter.h" + +#include +#include +#include +#include +#include +#include + +using namespace opensaml::saml2; +using namespace opensaml::saml2md; +using namespace xmltooling::logging; +using namespace xmltooling; +using namespace boost::lambda; +using namespace boost; +using namespace std; + +namespace opensaml { + namespace saml2md { + + class SAML_DLLLOCAL EntityAttributesMetadataFilter : public MetadataFilter + { + public: + EntityAttributesMetadataFilter(const DOMElement* e); + ~EntityAttributesMetadataFilter() {} + + const char* getId() const { return ENTITYATTR_METADATA_FILTER; } + void doFilter(XMLObject& xmlObject) const; + + private: + void filterEntity(EntityDescriptor& entity) const; + void filterGroup(EntitiesDescriptor& entities) const; + + vector< boost::shared_ptr > m_attributes; + typedef multimap applymap_t; + applymap_t m_applyMap; + }; + + MetadataFilter* SAML_DLLLOCAL EntityAttributesMetadataFilterFactory(const DOMElement* const & e) + { + return new EntityAttributesMetadataFilter(e); + } + + static const XMLCh Entity[] = UNICODE_LITERAL_6(E,n,t,i,t,y); + + }; +}; + + +EntityAttributesMetadataFilter::EntityAttributesMetadataFilter(const DOMElement* e) +{ + // Contains ordered set of Attribute and Entity elements. + // We track each Attribute we find, and then consume an Entity by adding. + // a mapping from the Entity to every Attribute seen to that point. + DOMElement* child = XMLHelper::getFirstChildElement(e); + while (child) { + if (XMLHelper::isNodeNamed(child, samlconstants::SAML20_NS, Attribute::LOCAL_NAME)) { + boost::shared_ptr obj(AttributeBuilder::buildOneFromElement(child)); + m_attributes.push_back(boost::shared_dynamic_cast(obj)); + } + else if (XMLString::equals(child->getLocalName(), Entity)) { + const XMLCh* eid = child->getTextContent(); + if (eid && *eid) { + for (vector< boost::shared_ptr >::const_iterator a = m_attributes.begin(); a != m_attributes.end(); ++a) + m_applyMap.insert(applymap_t::value_type(eid, a->get())); + } + } + child = XMLHelper::getNextSiblingElement(child); + } +} + +void EntityAttributesMetadataFilter::doFilter(XMLObject& xmlObject) const +{ + EntitiesDescriptor* group = dynamic_cast(&xmlObject); + if (group) { + filterGroup(*group); + } + else { + EntityDescriptor* entity = dynamic_cast(&xmlObject); + if (entity) { + filterEntity(*entity); + } + else { + throw MetadataFilterException(ENTITYATTR_METADATA_FILTER" MetadataFilter was given an improper metadata instance to filter."); + } + } +} + +void EntityAttributesMetadataFilter::filterGroup(EntitiesDescriptor& entities) const +{ + const vector& v = const_cast(entities).getEntityDescriptors(); + for_each( + make_indirect_iterator(v.begin()), make_indirect_iterator(v.end()), + lambda::bind(&EntityAttributesMetadataFilter::filterEntity, this, _1) + ); + + const vector& v2 = const_cast(entities).getEntitiesDescriptors(); + for_each( + make_indirect_iterator(v2.begin()), make_indirect_iterator(v2.end()), + lambda::bind(&EntityAttributesMetadataFilter::filterGroup, this, _1) + ); +} + +void EntityAttributesMetadataFilter::filterEntity(EntityDescriptor& entity) const +{ + if (entity.getEntityID()) { + pair tags = m_applyMap.equal_range(entity.getEntityID()); + if (tags.first != tags.second) { + Extensions* exts = entity.getExtensions(); + if (!exts) { + entity.setExtensions(ExtensionsBuilder::buildExtensions()); + exts = entity.getExtensions(); + } + EntityAttributes* wrapper = nullptr; + const vector& children = const_cast(exts)->getUnknownXMLObjects(); + XMLObject* xo = find_if(children, ll_dynamic_cast(_1) != ((EntityAttributes*)nullptr)); + if (xo) { + wrapper = dynamic_cast(xo); + } + else { + wrapper = EntityAttributesBuilder::buildEntityAttributes(); + exts->getUnknownXMLObjects().push_back(wrapper); + } + VectorOf(Attribute) attrs = wrapper->getAttributes(); + for (; tags.first != tags.second; ++tags.first) { + auto_ptr np(tags.first->second->cloneAttribute()); + attrs.push_back(np.get()); + np.release(); + } + } + } +} -- 2.1.4