Boost changes
[shibboleth/cpp-sp.git] / shibsp / handler / impl / MetadataGenerator.cpp
index fe541b2..48663b5 100644 (file)
 #include "handler/RemotedHandler.h"
 #include "util/IPRange.h"
 
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/algorithm/string.hpp>
+
 #ifndef SHIBSP_LITE
 # include "attribute/resolver/AttributeExtractor.h"
 # include "metadata/MetadataProviderCriteria.h"
+# include <boost/ptr_container/ptr_vector.hpp>
 # include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/signature/ContentReference.h>
@@ -60,6 +66,7 @@ using namespace opensaml;
 using namespace xmlsignature;
 #endif
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -88,17 +95,7 @@ namespace shibsp {
     {
     public:
         MetadataGenerator(const DOMElement* e, const char* appId);
-        virtual ~MetadataGenerator() {
-#ifndef SHIBSP_LITE
-            delete m_uiinfo;
-            delete m_org;
-            delete m_entityAttrs;
-            for_each(m_contacts.begin(), m_contacts.end(), xmltooling::cleanup<ContactPerson>());
-            for_each(m_formats.begin(), m_formats.end(), xmltooling::cleanup<NameIDFormat>());
-            for_each(m_reqAttrs.begin(), m_reqAttrs.end(), xmltooling::cleanup<RequestedAttribute>());
-            for_each(m_attrConsumers.begin(), m_attrConsumers.end(), xmltooling::cleanup<AttributeConsumingService>());
-#endif
-        }
+        virtual ~MetadataGenerator() {}
 
         pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
         void receive(DDF& in, ostream& out);
@@ -111,18 +108,27 @@ namespace shibsp {
             HTTPResponse& httpResponse
             ) const;
 
+        void parseACL(const string& acl) {
+            try {
+                m_acl.push_back(IPRange::parseCIDRBlock(acl.c_str()));
+            }
+            catch (std::exception& ex) {
+                m_log.error("invalid CIDR block (%s): %s", acl.c_str(), ex.what());
+            }
+        }
+
         vector<IPRange> m_acl;
 #ifndef SHIBSP_LITE
         string m_salt;
         short m_http,m_https;
         vector<string> m_bases;
-        UIInfo* m_uiinfo;
-        Organization* m_org;
-        EntityAttributes* m_entityAttrs;
-        vector<ContactPerson*> m_contacts;
-        vector<NameIDFormat*> m_formats;
-        vector<RequestedAttribute*> m_reqAttrs;
-        vector<AttributeConsumingService*> m_attrConsumers;
+        scoped_ptr<UIInfo> m_uiinfo;
+        scoped_ptr<Organization> m_org;
+        scoped_ptr<EntityAttributes> m_entityAttrs;
+        ptr_vector<ContactPerson> m_contacts;
+        ptr_vector<NameIDFormat> m_formats;
+        ptr_vector<RequestedAttribute> m_reqAttrs;
+        ptr_vector<AttributeConsumingService> m_attrConsumers;
 #endif
     };
 
@@ -140,7 +146,7 @@ namespace shibsp {
 MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
     : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".MetadataGenerator"), &g_Blocker)
 #ifndef SHIBSP_LITE
-        ,m_http(0), m_https(0), m_uiinfo(nullptr), m_org(nullptr), m_entityAttrs(nullptr)
+        ,m_http(0), m_https(0)
 #endif
 {
     string address(appId);
@@ -151,25 +157,9 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
         pair<bool,const char*> acl = getString("acl");
         if (acl.first) {
             string aclbuf=acl.second;
-            int j = 0;
-            for (unsigned int i=0;  i < aclbuf.length();  ++i) {
-                if (aclbuf.at(i)==' ') {
-                    try {
-                        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, i-j).c_str()));
-                    }
-                    catch (exception& ex) {
-                        m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-                    }
-                    j = i + 1;
-                }
-            }
-            try {
-                m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-            }
-            catch (exception& ex) {
-                m_log.error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
-            }
-
+            vector<string> aclarray;
+            split(aclarray, aclbuf, is_space(), algorithm::token_compress_on);
+            for_each(aclarray.begin(), aclarray.end(), boost::bind(&MetadataGenerator::parseACL, this, _1));
             if (m_acl.empty()) {
                 m_log.warn("invalid CIDR range(s) in Metadata Generator acl property, allowing 127.0.0.1 as a fall back");
                 m_acl.push_back(IPRange::parseCIDRBlock("127.0.0.1"));
@@ -203,33 +193,33 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
             auto_ptr<XMLObject> child(XMLObjectBuilder::buildOneFromElement(const_cast<DOMElement*>(e)));
             ContactPerson* cp = dynamic_cast<ContactPerson*>(child.get());
             if (cp) {
-                child.release();
                 m_contacts.push_back(cp);
+                child.release();
             }
             else {
                 NameIDFormat* nif = dynamic_cast<NameIDFormat*>(child.get());
                 if (nif) {
-                    child.release();
                     m_formats.push_back(nif);
+                    child.release();
                 }
                 else {
                     RequestedAttribute* req = dynamic_cast<RequestedAttribute*>(child.get());
                     if (req) {
-                        child.release();
                         m_reqAttrs.push_back(req);
+                        child.release();
                     }
                     else {
                         AttributeConsumingService* acs = dynamic_cast<AttributeConsumingService*>(child.get());
                         if (acs) {
-                            child.release();
                             m_attrConsumers.push_back(acs);
+                            child.release();
                         }
                         else {
                             UIInfo* info = dynamic_cast<UIInfo*>(child.get());
                             if (info) {
                                 if (!m_uiinfo) {
+                                    m_uiinfo.reset(info);
                                     child.release();
-                                    m_uiinfo = info;
                                 }
                                 else {
                                     m_log.warn("skipping duplicate UIInfo element");
@@ -239,8 +229,8 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
                                 Organization* org = dynamic_cast<Organization*>(child.get());
                                 if (org) {
                                     if (!m_org) {
+                                        m_org.reset(org);
                                         child.release();
-                                        m_org = org;
                                     }
                                     else {
                                         m_log.warn("skipping duplicate Organization element");
@@ -250,8 +240,8 @@ MetadataGenerator::MetadataGenerator(const DOMElement* e, const char* appId)
                                     EntityAttributes* ea = dynamic_cast<EntityAttributes*>(child.get());
                                     if (ea) {
                                         if (!m_entityAttrs) {
+                                            m_entityAttrs.reset(ea);
                                             child.release();
-                                            m_entityAttrs = ea;
                                         }
                                         else {
                                             m_log.warn("skipping duplicate EntityAttributes element");
@@ -273,14 +263,11 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
 {
     SPConfig& conf = SPConfig::getConfig();
     if (conf.isEnabled(SPConfig::InProcess) && !m_acl.empty()) {
-        bool found = false;
-        for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-            found = acl->contains(request.getRemoteAddr().c_str());
-        }
-        if (!found) {
+        static bool (IPRange::* contains)(const char*) const = &IPRange::contains;
+        if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, request.getRemoteAddr().c_str())) == m_acl.end()) {
             m_log.error("request for metadata blocked from invalid address (%s)", request.getRemoteAddr().c_str());
             istringstream msg("Metadata Request Blocked");
-            return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
+            return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN));
         }
     }
 
@@ -302,10 +289,10 @@ pair<bool,long> MetadataGenerator::run(SPRequest& request, bool isHandler) const
             return unwrap(request, out);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while processing request: %s", ex.what());
         istringstream msg("Metadata Request Failed");
-        return make_pair(true,request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
+        return make_pair(true, request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_ERROR));
     }
 }
 
@@ -327,12 +314,12 @@ void MetadataGenerator::receive(DDF& in, ostream& out)
     // Wrap a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     // Since we're remoted, the result should either be a throw, a false/0 return,
     // which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    processMessage(*app, hurl, in["entity_id"].string(), *resp.get());
+    processMessage(*app, hurl, in["entity_id"].string(), *resp);
     out << ret;
 }
 
@@ -343,9 +330,9 @@ pair<bool,long> MetadataGenerator::processMessage(
 #ifndef SHIBSP_LITE
     m_log.debug("processing metadata request");
 
-    const PropertySet* relyingParty=nullptr;
+    const PropertySet* relyingParty = nullptr;
     if (entityID) {
-        MetadataProvider* m=application.getMetadataProvider();
+        MetadataProvider* m = application.getMetadataProvider();
         Locker locker(m);
         MetadataProviderCriteria mc(application, entityID);
         relyingParty = application.getRelyingParty(m->getEntityDescriptor(mc).first);
@@ -354,7 +341,7 @@ pair<bool,long> MetadataGenerator::processMessage(
         relyingParty = &application;
     }
 
-    EntityDescriptor* entity;
+    scoped_ptr<EntityDescriptor> entity;
     pair<bool,const char*> prop = getString("template");
     if (prop.first) {
         // Load a template to use for our metadata.
@@ -363,17 +350,17 @@ pair<bool,long> MetadataGenerator::processMessage(
         auto_ptr_XMLCh widenit(templ.c_str());
         LocalFileInputSource src(widenit.get());
         Wrapper4InputSource dsrc(&src,false);
-        DOMDocument* doc=XMLToolingConfig::getConfig().getParser().parse(dsrc);
+        DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(dsrc);
         XercesJanitor<DOMDocument> docjan(doc);
         auto_ptr<XMLObject> xmlobj(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
         docjan.release();
-        entity = dynamic_cast<EntityDescriptor*>(xmlobj.get());
+        entity.reset(dynamic_cast<EntityDescriptor*>(xmlobj.get()));
+        xmlobj.release();
         if (!entity)
             throw ConfigurationException("Template file ($1) did not contain an EntityDescriptor", params(1, templ.c_str()));
-        xmlobj.release();
     }
     else {
-        entity = EntityDescriptorBuilder::buildEntityDescriptor();
+        entity.reset(EntityDescriptorBuilder::buildEntityDescriptor());
     }
 
     if (!entity->getID()) {
@@ -383,7 +370,6 @@ pair<bool,long> MetadataGenerator::processMessage(
         entity->setID(widenit.get());
     }
 
-    auto_ptr<EntityDescriptor> wrapper(entity);
     pair<bool,unsigned int> cache = getUnsignedInt("cacheDuration");
     if (cache.first) {
         entity->setCacheDuration(cache.second);
@@ -396,8 +382,8 @@ pair<bool,long> MetadataGenerator::processMessage(
     if (m_org && !entity->getOrganization())
         entity->setOrganization(m_org->cloneOrganization());
 
-    for (vector<ContactPerson*>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
-        entity->getContactPersons().push_back((*cp)->cloneContactPerson());
+    for (ptr_vector<ContactPerson>::const_iterator cp = m_contacts.begin(); cp != m_contacts.end(); ++cp)
+        entity->getContactPersons().push_back(cp->cloneContactPerson());
 
     if (m_entityAttrs) {
         if (!entity->getExtensions())
@@ -414,8 +400,8 @@ pair<bool,long> MetadataGenerator::processMessage(
         role = entity->getSPSSODescriptors().front();
     }
 
-    for (vector<NameIDFormat*>::const_iterator nif = m_formats.begin(); nif != m_formats.end(); ++nif)
-        role->getNameIDFormats().push_back((*nif)->cloneNameIDFormat());
+    for (ptr_vector<NameIDFormat>::const_iterator nif = m_formats.begin(); nif != m_formats.end(); ++nif)
+        role->getNameIDFormats().push_back(nif->cloneNameIDFormat());
 
     if (m_uiinfo) {
         if (!role->getExtensions())
@@ -423,14 +409,15 @@ pair<bool,long> MetadataGenerator::processMessage(
         role->getExtensions()->getUnknownXMLObjects().push_back(m_uiinfo->cloneUIInfo());
     }
 
-    for (vector<AttributeConsumingService*>::const_iterator acs = m_attrConsumers.begin(); acs != m_attrConsumers.end(); ++acs)
-        role->getAttributeConsumingServices().push_back((*acs)->cloneAttributeConsumingService());
+    for (ptr_vector<AttributeConsumingService>::const_iterator acs = m_attrConsumers.begin(); acs != m_attrConsumers.end(); ++acs)
+        role->getAttributeConsumingServices().push_back(acs->cloneAttributeConsumingService());
 
     if (!m_reqAttrs.empty()) {
         int index = 1;
         const vector<AttributeConsumingService*>& svcs = const_cast<const SPSSODescriptor*>(role)->getAttributeConsumingServices();
-        for (vector<AttributeConsumingService*>::const_iterator s =svcs.begin(); s != svcs.end(); ++s) {
-            pair<bool,int> i = (*s)->getIndex();
+        for (indirect_iterator<vector<AttributeConsumingService*>::const_iterator> s = make_indirect_iterator(svcs.begin());
+                s != make_indirect_iterator(svcs.end()); ++s) {
+            pair<bool,int> i = s->getIndex();
             if (i.first && index == i.second)
                 index = i.second + 1;
         }
@@ -442,8 +429,8 @@ pair<bool,long> MetadataGenerator::processMessage(
         sn->setName(entity->getEntityID());
         static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
         sn->setLang(english);
-        for (vector<RequestedAttribute*>::const_iterator req = m_reqAttrs.begin(); req != m_reqAttrs.end(); ++req)
-            svc->getRequestedAttributes().push_back((*req)->cloneRequestedAttribute());
+        for (ptr_vector<RequestedAttribute>::const_iterator req = m_reqAttrs.begin(); req != m_reqAttrs.end(); ++req)
+            svc->getRequestedAttributes().push_back(req->cloneRequestedAttribute());
     }
 
     // Policy flags.
@@ -457,30 +444,31 @@ pair<bool,long> MetadataGenerator::processMessage(
     // Ask each handler to generate itself.
     vector<const Handler*> handlers;
     application.getHandlers(handlers);
-    for (vector<const Handler*>::const_iterator h = handlers.begin(); h != handlers.end(); ++h) {
+    for (indirect_iterator<vector<const Handler*>::const_iterator> h = make_indirect_iterator(handlers.begin());
+            h != make_indirect_iterator(handlers.end()); ++h) {
         if (m_bases.empty()) {
             if (strncmp(handlerURL, "https", 5) == 0) {
                 if (m_https >= 0)
-                    (*h)->generateMetadata(*role, handlerURL);
+                    h->generateMetadata(*role, handlerURL);
                 if (m_http == 1) {
                     string temp(handlerURL);
                     temp.erase(4, 1);
-                    (*h)->generateMetadata(*role, temp.c_str());
+                    h->generateMetadata(*role, temp.c_str());
                 }
             }
             else {
                 if (m_http >= 0)
-                    (*h)->generateMetadata(*role, handlerURL);
+                    h->generateMetadata(*role, handlerURL);
                 if (m_https == 1) {
                     string temp(handlerURL);
                     temp.insert(temp.begin() + 4, 's');
-                    (*h)->generateMetadata(*role, temp.c_str());
+                    h->generateMetadata(*role, temp.c_str());
                 }
             }
         }
         else {
             for (vector<string>::const_iterator b = m_bases.begin(); b != m_bases.end(); ++b)
-                (*h)->generateMetadata(*role, b->c_str());
+                h->generateMetadata(*role, b->c_str());
         }
     }
 
@@ -558,7 +546,7 @@ pair<bool,long> MetadataGenerator::processMessage(
             stringstream pretty;
             XMLHelper::serialize(entity->marshall(), pretty, true);
             DOMDocument* prettydoc = XMLToolingConfig::getConfig().getParser().parse(pretty);
-            auto_ptr<XMLObject> prettyentity(XMLObjectBuilder::buildOneFromElement(prettydoc->getDocumentElement(), true));
+            scoped_ptr<XMLObject> prettyentity(XMLObjectBuilder::buildOneFromElement(prettydoc->getDocumentElement(), true));
 
             Signature* sig = SignatureBuilder::buildSignature();
             dynamic_cast<EntityDescriptor*>(prettyentity.get())->setSignature(sig);