Boost code changes
authorScott Cantor <cantor.2@osu.edu>
Tue, 10 Jan 2012 20:53:27 +0000 (20:53 +0000)
committerScott Cantor <cantor.2@osu.edu>
Tue, 10 Jan 2012 20:53:27 +0000 (20:53 +0000)
29 files changed:
configure.ac
shibsp/AbstractSPRequest.cpp
shibsp/AbstractSPRequest.h
shibsp/Application.cpp
shibsp/SPConfig.cpp
shibsp/ServiceProvider.cpp
shibsp/attribute/KeyInfoAttributeDecoder.cpp
shibsp/attribute/NameIDAttributeDecoder.cpp
shibsp/attribute/StringAttributeDecoder.cpp
shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
shibsp/binding/impl/XMLProtocolProvider.cpp
shibsp/impl/ChainingAccessControl.cpp
shibsp/impl/StorageServiceSessionCache.cpp
shibsp/impl/XMLAccessControl.cpp
shibsp/impl/XMLRequestMapper.cpp
shibsp/impl/XMLSecurityPolicyProvider.cpp
shibsp/impl/XMLServiceProvider.cpp
shibsp/metadata/DynamicMetadataProvider.cpp
shibsp/metadata/MetadataExtImpl.cpp
shibsp/remoting/ddf.h
shibsp/remoting/impl/SocketListener.cpp
shibsp/remoting/impl/SocketListener.h
shibsp/remoting/impl/TCPListener.cpp
shibsp/remoting/impl/ddf.cpp
shibsp/security/PKIXTrustEngine.cpp
shibsp/util/CGIParser.cpp
shibsp/util/DOMPropertySet.cpp
shibsp/util/DOMPropertySet.h
shibsp/util/TemplateParameters.cpp

index 9dbef5e..c72f7a5 100644 (file)
@@ -126,7 +126,9 @@ BOOST_REQUIRE
 BOOST_BIND
 BOOST_LAMBDA
 BOOST_PTR_CONTAINER
+BOOST_SMART_PTR
 BOOST_STRING_ALGO
+BOOST_TUPLE
 CPPFLAGS="$BOOST_CPPFLAGS $CPPFLAGS"
 
 # Thank you Solaris, really.
index 57f941a..41ea499 100644 (file)
@@ -33,6 +33,8 @@
 #include "SessionCache.h"
 #include "util/CGIParser.h"
 
+#include <boost/lexical_cast.hpp>
+
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
@@ -66,10 +68,10 @@ GSSRequest::~GSSRequest()
 #endif
 
 AbstractSPRequest::AbstractSPRequest(const char* category)
-    : m_sp(nullptr), m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
-        m_log(&Category::getInstance(category)), m_parser(nullptr)
+    : m_sp(SPConfig::getConfig().getServiceProvider()),
+        m_mapper(nullptr), m_app(nullptr), m_sessionTried(false), m_session(nullptr),
+        m_log(&Category::getInstance(category))
 {
-    m_sp=SPConfig::getConfig().getServiceProvider();
     m_sp->lock();
 }
 
@@ -81,7 +83,6 @@ AbstractSPRequest::~AbstractSPRequest()
         m_mapper->unlock();
     if (m_sp)
         m_sp->unlock();
-    delete m_parser;
 }
 
 const ServiceProvider& AbstractSPRequest::getServiceProvider() const
@@ -93,7 +94,7 @@ RequestMapper::Settings AbstractSPRequest::getRequestSettings() const
 {
     if (!m_mapper) {
         // Map request to application and content settings.
-        m_mapper=m_sp->getRequestMapper();
+        m_mapper = m_sp->getRequestMapper();
         m_mapper->lock();
         m_settings = m_mapper->getSettings(*this);
 
@@ -110,7 +111,7 @@ const Application& AbstractSPRequest::getApplication() const
 {
     if (!m_app) {
         // Now find the application from the URL settings
-        m_app=m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
+        m_app = m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
         if (!m_app)
             throw ConfigurationException("Unable to map non-default applicationId to an ApplicationOverride, check configuration.");
     }
@@ -126,16 +127,16 @@ Session* AbstractSPRequest::getSession(bool checkTimeout, bool ignoreAddress, bo
         m_sessionTried = true;
 
     // Need address checking and timeout settings.
-    time_t timeout=3600;
+    time_t timeout = 3600;
     if (checkTimeout || !ignoreAddress) {
-        const PropertySet* props=getApplication().getPropertySet("Sessions");
+        const PropertySet* props = getApplication().getPropertySet("Sessions");
         if (props) {
             if (checkTimeout) {
-                pair<bool,unsigned int> p=props->getUnsignedInt("timeout");
+                pair<bool,unsigned int> p = props->getUnsignedInt("timeout");
                 if (p.first)
                     timeout = p.second;
             }
-            pair<bool,bool> pcheck=props->getBool("consistentAddress");
+            pair<bool,bool> pcheck = props->getBool("consistentAddress");
             if (pcheck.first)
                 ignoreAddress = !pcheck.second;
         }
@@ -143,7 +144,7 @@ Session* AbstractSPRequest::getSession(bool checkTimeout, bool ignoreAddress, bo
 
     // The cache will either silently pass a session or nullptr back, or throw an exception out.
     Session* session = getServiceProvider().getSessionCache()->find(
-        getApplication(), *this, ignoreAddress ? nullptr : getRemoteAddr().c_str(), checkTimeout ? &timeout : nullptr
+        getApplication(), *this, (ignoreAddress ? nullptr : getRemoteAddr().c_str()), (checkTimeout ? &timeout : nullptr)
         );
     if (cache)
         m_session = session;
@@ -198,10 +199,8 @@ const char* AbstractSPRequest::getRequestURL() const
         int port = getPort();
         const char* scheme = getScheme();
         m_url = string(scheme) + "://" + getHostname();
-        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
-            ostringstream portstr;
-            portstr << port;
-            m_url += ":" + portstr.str();
+        if ((!strcmp(scheme,"http") && port != 80) || (!strcmp(scheme,"https") && port != 443)) {
+            m_url += ":" + boost::lexical_cast<string>(port);
         }
         m_url += m_uri;
     }
@@ -216,20 +215,20 @@ string AbstractSPRequest::getRemoteAddr() const
 
 const char* AbstractSPRequest::getParameter(const char* name) const
 {
-    if (!m_parser)
-        m_parser=new CGIParser(*this);
+    if (!m_parser.get())
+        m_parser.reset(new CGIParser(*this));
 
-    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
+    pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
     return (bounds.first==bounds.second) ? nullptr : bounds.first->second;
 }
 
 vector<const char*>::size_type AbstractSPRequest::getParameters(const char* name, vector<const char*>& values) const
 {
-    if (!m_parser)
-        m_parser=new CGIParser(*this);
+    if (!m_parser.get())
+        m_parser.reset(new CGIParser(*this));
 
-    pair<CGIParser::walker,CGIParser::walker> bounds=m_parser->getParameters(name);
-    while (bounds.first!=bounds.second) {
+    pair<CGIParser::walker,CGIParser::walker> bounds = m_parser->getParameters(name);
+    while (bounds.first != bounds.second) {
         values.push_back(bounds.first->second);
         ++bounds.first;
     }
@@ -241,19 +240,18 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
     if (!resource)
         resource = getRequestURL();
 
-    if (!m_handlerURL.empty() && resource && !strcmp(getRequestURL(),resource))
+    if (!m_handlerURL.empty() && resource && !strcmp(getRequestURL(), resource))
         return m_handlerURL.c_str();
 
+    // Check for relative URL.
     string stackresource;
     if (resource && *resource == '/') {
         // Compute a URL to the root of the site and point resource at constructed string.
         int port = getPort();
         const char* scheme = getScheme();
         stackresource = string(scheme) + "://" + getHostname();
-        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
-            ostringstream portstr;
-            portstr << port;
-            stackresource += ":" + portstr.str();
+        if ((!strcmp(scheme,"http") && port != 80) || (!strcmp(scheme,"https") && port != 443)) {
+            stackresource += ":" + boost::lexical_cast<string>(port);
         }
         stackresource += resource;
         resource = stackresource.c_str();
@@ -266,16 +264,16 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
 #endif
         throw ConfigurationException("Target resource was not an absolute URL.");
 
-    bool ssl_only=true;
-    const char* handler=nullptr;
-    const PropertySet* props=getApplication().getPropertySet("Sessions");
+    bool ssl_only = true;
+    const char* handler = nullptr;
+    const PropertySet* props = getApplication().getPropertySet("Sessions");
     if (props) {
-        pair<bool,bool> p=props->getBool("handlerSSL");
+        pair<bool,bool> p = props->getBool("handlerSSL");
         if (p.first)
-            ssl_only=p.second;
-        pair<bool,const char*> p2=props->getString("handlerURL");
+            ssl_only = p.second;
+        pair<bool,const char*> p2 = props->getString("handlerURL");
         if (p2.first)
-            handler=p2.second;
+            handler = p2.second;
     }
 
     if (!handler) {
@@ -314,9 +312,9 @@ const char* AbstractSPRequest::getHandlerURL(const char* resource) const
     }
 
     // break apart the "protocol" string into protocol, host, and "the rest"
-    const char* colon=strchr(prot,':');
+    const char* colon = strchr(prot, ':');
     colon += 3;
-    const char* slash=strchr(colon,'/');
+    const char* slash = strchr(colon, '/');
     if (!path)
         path = slash;
 
index ce55e12..0a2799b 100644 (file)
@@ -28,6 +28,7 @@
 #define __shibsp_abstreq_h__
 
 #include <shibsp/SPRequest.h>
+#include <boost/scoped_ptr.hpp>
 
 namespace shibsp {
     
@@ -87,7 +88,7 @@ namespace shibsp {
         mutable std::string m_url;
         void* m_log; // declared void* to avoid log4cpp header conflicts in Apache
         mutable std::string m_handlerURL;
-        mutable CGIParser* m_parser;
+        mutable boost::scoped_ptr<CGIParser> m_parser;
     };
 
 #if defined (_MSC_VER)
index c602411..43139f3 100644 (file)
 #include "remoting/ListenerService.h"
 
 #include <algorithm>
+#include <boost/bind.hpp>
 #include <xmltooling/util/Threads.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 Application::Application(const ServiceProvider* sp) : m_sp(sp), m_lock(RWLock::create())
@@ -102,8 +104,15 @@ string Application::getSecureHeader(const SPRequest& request, const char* name)
 void Application::clearAttributeHeaders(SPRequest& request) const
 {
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
-            request.clearHeader(i->first.c_str(), i->second.c_str());
+        for_each(
+            m_unsetHeaders.begin(), m_unsetHeaders.end(),
+            boost::bind(
+                &SPRequest::clearHeader,
+                boost::ref(request),
+                boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1)),
+                boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1))
+                )
+            );
         return;
     }
 
@@ -134,8 +143,15 @@ void Application::clearAttributeHeaders(SPRequest& request) const
 
     // Now holding read lock.
     SharedLock unsetLock(m_lock, false);
-    for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
-        request.clearHeader(i->first.c_str(), i->second.c_str());
+    for_each(
+        m_unsetHeaders.begin(), m_unsetHeaders.end(),
+        boost::bind(
+            &SPRequest::clearHeader,
+            boost::ref(request),
+            boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1)),
+            boost::bind(&string::c_str, boost::bind(&pair<string,string>::first, _1))
+            )
+        );
 }
 
 const Handler* Application::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const
index cef253a..75317ea 100644 (file)
@@ -66,6 +66,7 @@
 #endif
 
 #include <ctime>
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/version.h>
 #include <xmltooling/XMLToolingConfig.h>
@@ -79,6 +80,7 @@
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 DECL_XMLTOOLING_EXCEPTION_FACTORY(AttributeException,shibsp);
@@ -101,15 +103,15 @@ namespace shibsp {
     class SHIBSP_DLLLOCAL SPInternalConfig : public SPConfig
     {
     public:
-        SPInternalConfig();
-        ~SPInternalConfig();
+        SPInternalConfig() : m_initCount(0), m_lock(Mutex::create()) {}
+        ~SPInternalConfig() {}
 
         bool init(const char* catalog_path=nullptr, const char* inst_prefix=nullptr);
         void term();
 
     private:
         int m_initCount;
-        Mutex* m_lock;
+        scoped_ptr<Mutex> m_lock;
     };
     
     SPInternalConfig g_config;
@@ -443,15 +445,6 @@ bool SPConfig::instantiate(const char* config, bool rethrow)
     return false;
 }
 
-SPInternalConfig::SPInternalConfig() : m_initCount(0), m_lock(Mutex::create())
-{
-}
-
-SPInternalConfig::~SPInternalConfig()
-{
-    delete m_lock;
-}
-
 bool SPInternalConfig::init(const char* catalog_path, const char* inst_prefix)
 {
 #ifdef _DEBUG
index ab6dc45..8d12c3d 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <fstream>
 #include <sstream>
+#include <boost/algorithm/string.hpp>
 #ifndef SHIBSP_LITE
 # include <saml/exceptions.h>
 # include <saml/saml2/metadata/MetadataProvider.h>
@@ -185,21 +186,21 @@ SecurityPolicyProvider* ServiceProvider::getSecurityPolicyProvider(bool required
 
 Remoted* ServiceProvider::regListener(const char* address, Remoted* listener)
 {
-    Remoted* ret=nullptr;
-    map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
-    if (i!=m_listenerMap.end())
-        ret=i->second;
-    m_listenerMap[address]=listener;
+    Remoted* ret = nullptr;
+    map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+    if (i != m_listenerMap.end())
+        ret = i->second;
+    m_listenerMap[address] = listener;
     Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("registered remoted message endpoint (%s)",address);
     return ret;
 }
 
 bool ServiceProvider::unregListener(const char* address, Remoted* current, Remoted* restore)
 {
-    map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
-    if (i!=m_listenerMap.end() && i->second==current) {
+    map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+    if (i != m_listenerMap.end() && i->second == current) {
         if (restore)
-            m_listenerMap[address]=restore;
+            m_listenerMap[address] = restore;
         else
             m_listenerMap.erase(address);
         Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").info("unregistered remoted message endpoint (%s)",address);
@@ -210,8 +211,8 @@ bool ServiceProvider::unregListener(const char* address, Remoted* current, Remot
 
 Remoted* ServiceProvider::lookupListener(const char *address) const
 {
-    map<string,Remoted*>::const_iterator i=m_listenerMap.find(address);
-    return (i==m_listenerMap.end()) ? nullptr : i->second;
+    map<string,Remoted*>::const_iterator i = m_listenerMap.find(address);
+    return (i == m_listenerMap.end()) ? nullptr : i->second;
 }
 
 pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
@@ -221,7 +222,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
 #endif
     Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
 
-    const Application* app=nullptr;
+    const Application* app = nullptr;
     string targetURL = request.getRequestURL();
 
     try {
@@ -248,7 +249,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                 else {
                     TemplateParameters tp;
                     tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
-                    return make_pair(true,sendError(log, request, app, "ssl", tp, false));
+                    return make_pair(true, sendError(log, request, app, "ssl", tp, false));
                 }
             }
         }
@@ -259,7 +260,7 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
 
         // If the request URL contains the handler base URL for this application, either dispatch
         // directly (mainly Apache 2.0) or just pass back control.
-        if (strstr(targetURL.c_str(),handlerURL)) {
+        if (boost::contains(targetURL, handlerURL)) {
             if (handler)
                 return doHandler(request);
             else
@@ -271,17 +272,11 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
         pair<bool,bool> requireSession = settings.first->getBool("requireSession");
         pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
 
-        string lcAuthType;
-        if (authType.first) {
-            while (*authType.second)
-                lcAuthType += tolower(*authType.second++);
-        }
-
         // If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
         // then we ignore this request and consider it unprotected. Apache might lie to us if
         // ShibBasicHijack is on, but that's up to it.
         if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-                (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+                (!authType.first || m_authTypes.find(boost::to_lower_copy(string(authType.second))) == m_authTypes.end()))
             return make_pair(true, request.returnDecline());
 
         // Fix for secadv 20050901
@@ -294,14 +289,14 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
         catch (exception& e) {
             log.warn("error during session lookup: %s", e.what());
             // If it's not a retryable session failure, we throw to the outer handler for reporting.
-            if (dynamic_cast<opensaml::RetryableProfileException*>(&e)==nullptr)
+            if (dynamic_cast<opensaml::RetryableProfileException*>(&e) == nullptr)
                 throw;
         }
 
         if (!session) {
             // No session.  Maybe that's acceptable?
             if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first)
-                return make_pair(true,request.returnOK());
+                return make_pair(true, request.returnOK());
 
             // No session, but we require one. Initiate a new session using the indicated method.
             const SessionInitiator* initiator=nullptr;
@@ -319,10 +314,10 @@ pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handl
                     throw ConfigurationException("No default session initiator found, check configuration.");
             }
 
-            return initiator->run(request,false);
+            return initiator->run(request, false);
         }
 
-        request.setAuthType(lcAuthType.c_str());
+        request.setAuthType(authType.second);
 
         // We're done.  Everything is okay.  Nothing to report.  Nothing to do..
         // Let the caller decide how to proceed.
@@ -344,7 +339,7 @@ pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
 #endif
     Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
 
-    const Application* app=nullptr;
+    const Application* app = nullptr;
     const Session* session = nullptr;
     string targetURL = request.getRequestURL();
 
@@ -357,17 +352,11 @@ pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
         pair<bool,bool> requireSession = settings.first->getBool("requireSession");
         pair<bool,const char*> requireSessionWith = settings.first->getString("requireSessionWith");
 
-        string lcAuthType;
-        if (authType.first) {
-            while (*authType.second)
-                lcAuthType += tolower(*authType.second++);
-        }
-
         // If no session is required AND the AuthType (an Apache-derived concept) isn't recognized,
         // then we ignore this request and consider it unprotected. Apache might lie to us if
         // ShibBasicHijack is on, but that's up to it.
         if ((!requireSession.first || !requireSession.second) && !requireSessionWith.first &&
-                (!authType.first || m_authTypes.find(lcAuthType) == m_authTypes.end()))
+                (!authType.first || m_authTypes.find(boost::to_lower_copy(string(authType.second))) == m_authTypes.end()))
             return make_pair(true, request.returnDecline());
 
         // Do we have an access control plugin?
@@ -380,26 +369,26 @@ pair<bool,long> ServiceProvider::doAuthorization(SPRequest& request) const
             }
 
             Locker acllock(settings.second);
-            switch (settings.second->authorized(request,session)) {
+            switch (settings.second->authorized(request, session)) {
                 case AccessControl::shib_acl_true:
                     log.debug("access control provider granted access");
-                    return make_pair(true,request.returnOK());
+                    return make_pair(true, request.returnOK());
 
                 case AccessControl::shib_acl_false:
                 {
                     log.warn("access control provider denied access");
                     TemplateParameters tp(nullptr, nullptr, session);
                     tp.m_map["requestURL"] = targetURL;
-                    return make_pair(true,sendError(log, request, app, "access", tp, false));
+                    return make_pair(true, sendError(log, request, app, "access", tp, false));
                 }
 
                 default:
                     // Use the "DECLINE" interface to signal we don't know what to do.
-                    return make_pair(true,request.returnDecline());
+                    return make_pair(true, request.returnDecline());
             }
         }
         else {
-            return make_pair(true,request.returnDecline());
+            return make_pair(true, request.returnDecline());
         }
     }
     catch (exception& e) {
@@ -417,7 +406,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
 #endif
     Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
 
-    const Application* app=nullptr;
+    const Application* app = nullptr;
     const Session* session = nullptr;
     string targetURL = request.getRequestURL();
 
@@ -440,7 +429,7 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                if (requireSession)
                 throw opensaml::RetryableProfileException("Unable to obtain session to export to request.");
                else
-                       return make_pair(false,0L);     // just bail silently
+                       return make_pair(false, 0L);    // just bail silently
         }
 
                pair<bool,const char*> enc = settings.first->getString("encoding");
@@ -477,9 +466,9 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
         }
 
         // Maybe export the assertion keys.
-        pair<bool,bool> exp=settings.first->getBool("exportAssertion");
+        pair<bool,bool> exp = settings.first->getBool("exportAssertion");
         if (exp.first && exp.second) {
-            const PropertySet* sessions=app->getPropertySet("Sessions");
+            const PropertySet* sessions = app->getPropertySet("Sessions");
             pair<bool,const char*> exportLocation = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,nullptr);
             if (!exportLocation.first)
                 log.warn("can't export assertions without an exportLocation Sessions property");
@@ -506,12 +495,12 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
 
         // Export the attributes.
         const multimap<string,const Attribute*>& attributes = session->getIndexedAttributes();
-        for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a!=attributes.end(); ++a) {
+        for (multimap<string,const Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a) {
             if (a->second->isInternal())
                 continue;
             string header(app->getSecureHeader(request, a->first.c_str()));
             const vector<string>& vals = a->second->getSerializedValues();
-            for (vector<string>::const_iterator v = vals.begin(); v!=vals.end(); ++v) {
+            for (vector<string>::const_iterator v = vals.begin(); v != vals.end(); ++v) {
                 if (!header.empty())
                     header += ";";
                                if (enc.first) {
@@ -519,10 +508,10 @@ pair<bool,long> ServiceProvider::doExport(SPRequest& request, bool requireSessio
                                        header += encoder->encode(v->c_str());
                                }
                                else {
-                                       string::size_type pos = v->find_first_of(';',string::size_type(0));
-                                       if (pos!=string::npos) {
+                                       string::size_type pos = v->find_first_of(';', string::size_type(0));
+                                       if (pos != string::npos) {
                                                string value(*v);
-                                               for (; pos != string::npos; pos = value.find_first_of(';',pos)) {
+                                               for (; pos != string::npos; pos = value.find_first_of(';', pos)) {
                                                        value.insert(pos, "\\");
                                                        pos += 2;
                                                }
@@ -572,7 +561,7 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
 #endif
     Category& log = Category::getInstance(SHIBSP_LOGCAT".ServiceProvider");
 
-    const Application* app=nullptr;
+    const Application* app = nullptr;
     string targetURL = request.getRequestURL();
 
     try {
@@ -604,20 +593,20 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
             }
         }
 
-        const char* handlerURL=request.getHandlerURL(targetURL.c_str());
+        const char* handlerURL = request.getHandlerURL(targetURL.c_str());
         if (!handlerURL)
             throw ConfigurationException("Cannot determine handler from resource URL, check configuration.");
 
         // Make sure we only process handler requests.
-        if (!strstr(targetURL.c_str(),handlerURL))
+        if (!boost::contains(targetURL, handlerURL))
             return make_pair(true, request.returnDecline());
 
-        const PropertySet* sessionProps=app->getPropertySet("Sessions");
+        const PropertySet* sessionProps = app->getPropertySet("Sessions");
         if (!sessionProps)
             throw ConfigurationException("Unable to map request to application session settings, check configuration.");
 
         // Process incoming request.
-        pair<bool,bool> handlerSSL=sessionProps->getBool("handlerSSL");
+        pair<bool,bool> handlerSSL = sessionProps->getBool("handlerSSL");
 
         // Make sure this is SSL, if it should be
         if ((!handlerSSL.first || handlerSSL.second) && !request.isSecure())
@@ -625,11 +614,11 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
 
         // We dispatch based on our path info. We know the request URL begins with or equals the handler URL,
         // so the path info is the next character (or null).
-        const Handler* handler=app->getHandler(targetURL.c_str() + strlen(handlerURL));
+        const Handler* handler = app->getHandler(targetURL.c_str() + strlen(handlerURL));
         if (!handler)
             throw ConfigurationException("Shibboleth handler invoked at an unconfigured location.");
 
-        pair<bool,long> hret=handler->run(request);
+        pair<bool,long> hret = handler->run(request);
 
         // Did the handler run successfully?
         if (hret.first)
@@ -643,11 +632,11 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
         try {
             session = request.getSession(false, true);
         }
-        catch (exception& e2) {
+        catch (exception&) {
         }
         TemplateParameters tp(&e, nullptr, session);
-        tp.m_map["requestURL"] = targetURL.substr(0,targetURL.find('?'));
+        tp.m_map["requestURL"] = targetURL.substr(0, targetURL.find('?'));
         tp.m_request = &request;
-        return make_pair(true,sendError(log, request, app, "session", tp));
+        return make_pair(true, sendError(log, request, app, "session", tp));
     }
 }
index 662fd00..d01d183 100644 (file)
@@ -28,6 +28,7 @@
 #include "attribute/AttributeDecoder.h"
 #include "attribute/SimpleAttribute.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/core/Assertions.h>
 #include <xmltooling/XMLToolingConfig.h>
@@ -40,6 +41,7 @@ using namespace shibsp;
 using namespace opensaml;
 using namespace xmlsignature;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -47,9 +49,7 @@ namespace shibsp {
     {
     public:
         KeyInfoAttributeDecoder(const DOMElement* e);
-        ~KeyInfoAttributeDecoder() {
-            delete m_keyInfoResolver;
-        }
+        ~KeyInfoAttributeDecoder() {}
 
         Attribute* decode(
             const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=nullptr, const char* relyingParty=nullptr
@@ -57,22 +57,22 @@ namespace shibsp {
 
     private:
         void extract(const KeyInfo* k, vector<string>& dest) const {
-            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
-            if (cred.get()) {
+            scoped_ptr<Credential> cred(getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+            if (cred) {
                 dest.push_back(string());
-                dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash ? m_keyInfoHashAlg.c_str() : nullptr);
+                dest.back() = SecurityHelper::getDEREncoding(*cred, m_hash ? m_keyInfoHashAlg.c_str() : nullptr);
                 if (dest.back().empty())
                     dest.pop_back();
             }
         }
 
         const KeyInfoResolver* getKeyInfoResolver() const {
-            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+            return m_keyInfoResolver ? m_keyInfoResolver.get() : XMLToolingConfig::getConfig().getKeyInfoResolver();
         }
 
         bool m_hash;
         string m_keyInfoHashAlg;
-        KeyInfoResolver* m_keyInfoResolver;
+        scoped_ptr<KeyInfoResolver> m_keyInfoResolver;
     };
 
     AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
@@ -89,14 +89,13 @@ namespace shibsp {
 KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e)
     : AttributeDecoder(e),
         m_hash(XMLHelper::getAttrBool(e, false, _hash)),
-        m_keyInfoHashAlg(XMLHelper::getAttrString(e, "SHA1", keyInfoHashAlg)),
-        m_keyInfoResolver(nullptr) {
-    e = XMLHelper::getFirstChildElement(e,_KeyInfoResolver);
+        m_keyInfoHashAlg(XMLHelper::getAttrString(e, "SHA1", keyInfoHashAlg)) {
+    e = XMLHelper::getFirstChildElement(e, _KeyInfoResolver);
     if (e) {
         string t(XMLHelper::getAttrString(e, nullptr, _type));
         if (t.empty())
             throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
-        m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.c_str(), e);
+        m_keyInfoResolver.reset(XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.c_str(), e));
     }
 }
 
@@ -154,7 +153,7 @@ Attribute* KeyInfoAttributeDecoder::decode(
             extract(k, dest);
         else if ((*v)->hasChildren()) {
             const list<XMLObject*>& children = (*v)->getOrderedChildren();
-            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+            for (list<XMLObject*>::const_iterator vv = children.begin(); vv != children.end(); ++vv) {
                 if (k=dynamic_cast<const KeyInfo*>(*vv))
                     extract(k, dest);
                 else
index d220e6a..66d6868 100644 (file)
@@ -193,31 +193,26 @@ void NameIDAttributeDecoder::extract(
         dest.push_back(NameIDAttribute::Value());
         NameIDAttribute::Value& val = dest.back();
         val.m_Name = name.get();
-        char* str = toUTF8(n->getFormat());
-        if (str) {
-            val.m_Format = str;
-            delete[] str;
-        }
 
-        str = toUTF8(n->getNameQualifier());
-        if (str && *str)
-            val.m_NameQualifier = str;
+        auto_arrayptr<char> format(toUTF8(n->getFormat()));
+        if (format.get())
+            val.m_Format = format.get();
+
+        auto_arrayptr<char> nameQualifier(toUTF8(n->getNameQualifier()));
+        if (nameQualifier.get() && *nameQualifier.get())
+            val.m_NameQualifier = nameQualifier.get();
         else if (m_defaultQualifiers && assertingParty)
             val.m_NameQualifier = assertingParty;
-        delete[] str;
 
-        str = toUTF8(n->getSPNameQualifier());
-        if (str && *str)
-            val.m_SPNameQualifier = str;
+        auto_arrayptr<char> spNameQualifier(toUTF8(n->getSPNameQualifier()));
+        if (spNameQualifier.get() && *spNameQualifier.get())
+            val.m_SPNameQualifier = spNameQualifier.get();
         else if (m_defaultQualifiers && relyingParty)
             val.m_SPNameQualifier = relyingParty;
-        delete[] str;
 
-        str = toUTF8(n->getSPProvidedID());
-        if (str) {
-            val.m_SPProvidedID = str;
-            delete[] str;
-        }
+        auto_arrayptr<char> spProvidedID(toUTF8(n->getSPProvidedID()));
+        if (spProvidedID.get())
+            val.m_SPProvidedID = spProvidedID.get();
     }
 }
 
@@ -230,18 +225,16 @@ void NameIDAttributeDecoder::extract(
         dest.push_back(NameIDAttribute::Value());
         NameIDAttribute::Value& val = dest.back();
         val.m_Name = name.get();
-        char* str = toUTF8(n->getFormat());
-        if (str) {
-            val.m_Format = str;
-            delete[] str;
-        }
 
-        str = toUTF8(n->getNameQualifier());
-        if (str && *str)
-            val.m_NameQualifier = str;
+        auto_arrayptr<char> format(toUTF8(n->getFormat()));
+        if (format.get())
+            val.m_Format = format.get();
+
+        auto_arrayptr<char> nameQualifier(toUTF8(n->getNameQualifier()));
+        if (nameQualifier.get() && *nameQualifier.get())
+            val.m_NameQualifier = nameQualifier.get();
         else if (m_defaultQualifiers && assertingParty)
             val.m_NameQualifier = assertingParty;
-        delete[] str;
 
         if (m_defaultQualifiers && relyingParty)
             val.m_SPNameQualifier = relyingParty;
index 1fc5d22..8e4127d 100644 (file)
@@ -59,7 +59,6 @@ shibsp::Attribute* StringAttributeDecoder::decode(
     const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
     ) const
 {
-    char* val;
     auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
     vector<string>& dest = simple->getValues();
     vector<XMLObject*>::const_iterator v,stop;
@@ -102,12 +101,11 @@ shibsp::Attribute* StringAttributeDecoder::decode(
 
         for (; v!=stop; ++v) {
             if (!(*v)->hasChildren()) {
-                val = toUTF8((*v)->getTextContent());
-                if (val && *val)
-                    dest.push_back(val);
+                auto_arrayptr<char> val(toUTF8((*v)->getTextContent()));
+                if (val.get() && *val.get())
+                    dest.push_back(val.get());
                 else
                     log.warn("skipping empty AttributeValue");
-                delete[] val;
             }
             else {
                 log.warn("skipping complex AttributeValue");
@@ -123,7 +121,11 @@ shibsp::Attribute* StringAttributeDecoder::decode(
             auto_ptr_char f(saml2name->getFormat());
             log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
         }
-        val = toUTF8(saml2name->getName());
+        auto_arrayptr<char> val(toUTF8(saml2name->getName()));
+        if (val.get() && *val.get())
+            dest.push_back(val.get());
+        else
+            log.warn("ignoring empty NameID");
     }
     else {
         const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
@@ -135,7 +137,11 @@ shibsp::Attribute* StringAttributeDecoder::decode(
                     ids.front().c_str(), f.get() ? f.get() : "unspecified"
                     );
             }
-            val = toUTF8(saml1name->getName());
+            auto_arrayptr<char> val(toUTF8(saml1name->getName()));
+            if (val.get() && *val.get())
+                dest.push_back(val.get());
+            else
+                log.warn("ignoring empty NameIdentifier");
         }
         else {
             log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
@@ -143,10 +149,5 @@ shibsp::Attribute* StringAttributeDecoder::decode(
         }
     }
 
-    if (val && *val)
-        dest.push_back(val);
-    else
-        log.warn("ignoring empty NameID");
-    delete[] val;
     return dest.empty() ? nullptr : _decode(simple.release());
 }
index c270cf8..37906ee 100644 (file)
 #include "security/SecurityPolicy.h"
 #include "util/SPConstants.h"
 
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
+#include <boost/tuple/tuple.hpp>
 #include <saml/SAMLConfig.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/core/Assertions.h>
@@ -55,6 +62,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 using saml1::NameIdentifier;
 using saml2::NameID;
@@ -77,12 +85,6 @@ namespace shibsp {
                 for (decoded_t::iterator attrs = i->second.begin(); attrs!=i->second.end(); ++attrs)
                     for_each(attrs->second.begin(), attrs->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
             }
-            delete m_attrLock;
-            delete m_trust;
-            delete m_metadata;
-            delete m_filter;
-            for (attrmap_t::iterator j = m_attrMap.begin(); j!=m_attrMap.end(); ++j)
-                delete j->second.first;
             if (m_document)
                 m_document->release();
         }
@@ -94,11 +96,11 @@ namespace shibsp {
         void onEvent(const ObservableMetadataProvider& metadata) const {
             // Destroy attributes we cached from this provider.
             m_attrLock->wrlock();
+            SharedLock wrapper(m_attrLock, false);
             decoded_t& d = m_decodedMap[&metadata];
             for (decoded_t::iterator a = d.begin(); a!=d.end(); ++a)
                 for_each(a->second.begin(), a->second.end(), mem_fun_ref<DDF&,DDF>(&DDF::destroy));
             d.clear();
-            m_attrLock->unlock();
         }
 
         void extractAttributes(
@@ -106,42 +108,42 @@ namespace shibsp {
             const char* assertingParty,
             const char* relyingParty,
             const NameIdentifier& nameid,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
             const char* assertingParty,
             const char* relyingParty,
             const NameID& nameid,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
             const char* assertingParty,
             const char* relyingParty,
             const saml1::Attribute& attr,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
             const char* assertingParty,
             const char* relyingParty,
             const saml2::Attribute& attr,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
             const char* assertingParty,
             const char* relyingParty,
             const saml1::AttributeStatement& statement,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
             const char* assertingParty,
             const char* relyingParty,
             const saml2::AttributeStatement& statement,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
         void extractAttributes(
             const Application& application,
@@ -149,7 +151,7 @@ namespace shibsp {
             const XMLCh* entityID,
             const char* relyingParty,
             const Extensions& ext,
-            vector<Attribute*>& attributes
+            ptr_vector<Attribute>& attributes
             ) const;
 
         void getAttributeIds(vector<string>& attributes) const {
@@ -161,20 +163,20 @@ namespace shibsp {
     private:
         Category& m_log;
         DOMDocument* m_document;
-        typedef map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > > attrmap_t;
+        typedef map< pair<xstring,xstring>,pair< boost::shared_ptr<AttributeDecoder>,vector<string> > > attrmap_t;
         attrmap_t m_attrMap;
         vector<string> m_attributeIds;
-        vector< pair< pair<xstring,xstring>,bool > > m_requestedAttrs;
+        vector< tuple<xstring,xstring,bool> > m_requestedAttrs;
 
         // settings for embedded assertions in metadata
         string m_policyId;
-        MetadataProvider* m_metadata;
-        TrustEngine* m_trust;
-        AttributeFilter* m_filter;
+        scoped_ptr<AttributeFilter> m_filter;
+        scoped_ptr<MetadataProvider> m_metadata;
+        scoped_ptr<TrustEngine> m_trust;
         bool m_entityAssertions;
 
         // manages caching of decoded Attributes
-        mutable RWLock* m_attrLock;
+        scoped_ptr<RWLock> m_attrLock;
         typedef map< const EntityAttributes*,vector<DDF> > decoded_t;
         mutable map<const ObservableMetadataProvider*,decoded_t> m_decodedMap;
     };
@@ -182,12 +184,11 @@ namespace shibsp {
     class XMLExtractor : public AttributeExtractor, public ReloadableXMLFile
     {
     public:
-        XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.XML")), m_impl(nullptr) {
+        XMLExtractor(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.XML")) {
             background_load();
         }
         ~XMLExtractor() {
             shutdown();
-            delete m_impl;
         }
 
         void extractAttributes(
@@ -208,7 +209,11 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        XMLExtractorImpl* m_impl;
+        scoped_ptr<XMLExtractorImpl> m_impl;
+
+        void extractAttributes(
+            const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, ptr_vector<Attribute>& attributes
+            ) const;
     };
 
 #if defined (_MSC_VER)
@@ -238,11 +243,7 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
     : m_log(log),
         m_document(nullptr),
         m_policyId(XMLHelper::getAttrString(e, nullptr, metadataPolicyId)),
-        m_metadata(nullptr),
-        m_trust(nullptr),
-        m_filter(nullptr),
-        m_entityAssertions(true),
-        m_attrLock(nullptr)
+        m_entityAssertions(true)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("XMLExtractorImpl");
@@ -258,11 +259,11 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
             if (t.empty())
                 throw ConfigurationException("MetadataProvider element missing type attribute.");
             m_log.info("building MetadataProvider of type %s...", t.c_str());
-            auto_ptr<MetadataProvider> mp(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
-            mp->init();
-            m_metadata = mp.release();
+            m_metadata.reset(SAMLConfig::getConfig().MetadataProviderManager.newPlugin(t.c_str(), child));
+            m_metadata->init();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
+            m_metadata.reset();
             m_entityAssertions = false;
             m_log.crit("error building/initializing dedicated MetadataProvider: %s", ex.what());
             m_log.crit("disabling support for Assertions in EntityAttributes extension");
@@ -277,9 +278,9 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
                 if (t.empty())
                     throw ConfigurationException("TrustEngine element missing type attribute.");
                 m_log.info("building TrustEngine of type %s...", t.c_str());
-                m_trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
+                m_trust.reset(XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child));
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_entityAssertions = false;
                 m_log.crit("error building/initializing dedicated TrustEngine: %s", ex.what());
                 m_log.crit("disabling support for Assertions in EntityAttributes extension");
@@ -295,9 +296,9 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
                 if (t.empty())
                     throw ConfigurationException("AttributeFilter element missing type attribute.");
                 m_log.info("building AttributeFilter of type %s...", t.c_str());
-                m_filter = SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child);
+                m_filter.reset(SPConfig::getConfig().AttributeFilterManager.newPlugin(t.c_str(), child));
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_entityAssertions = false;
                 m_log.crit("error building/initializing dedicated AttributeFilter: %s", ex.what());
                 m_log.crit("disabling support for Assertions in EntityAttributes extension");
@@ -327,18 +328,18 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
             continue;
         }
 
-        AttributeDecoder* decoder=nullptr;
+        boost::shared_ptr<AttributeDecoder> decoder;
         try {
             DOMElement* dchild = XMLHelper::getFirstChildElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, _AttributeDecoder);
             if (dchild) {
                 auto_ptr<xmltooling::QName> q(XMLHelper::getXSIType(dchild));
                 if (q.get())
-                    decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild);
+                    decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(*q.get(), dchild));
             }
             if (!decoder)
-                decoder = SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, nullptr);
+                decoder.reset(SPConfig::getConfig().AttributeDecoderManager.newPlugin(StringAttributeDecoderType, nullptr));
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("skipping Attribute (%s), error building AttributeDecoder: %s", id.get(), ex.what());
         }
 
@@ -354,10 +355,9 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
             format = &chNull;  // ignore default Format/Namespace values
 
         // Fetch/create the map entry and see if it's a duplicate rule.
-        pair< AttributeDecoder*,vector<string> >& decl = m_attrMap[pair<xstring,xstring>(name,format)];
+        pair< boost::shared_ptr<AttributeDecoder>,vector<string> >& decl = m_attrMap[pair<xstring,xstring>(name,format)];
         if (decl.first) {
             m_log.warn("skipping duplicate Attribute mapping (same name and nameFormat)");
-            delete decoder;
             child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
             continue;
         }
@@ -376,36 +376,26 @@ XMLExtractorImpl::XMLExtractorImpl(const DOMElement* e, Category& log)
         bool requested = XMLHelper::getAttrBool(child, false, isRequested);
         bool required = XMLHelper::getAttrBool(child, false, RequestedAttribute::ISREQUIRED_ATTRIB_NAME);
         if (required || requested)
-            m_requestedAttrs.push_back(make_pair(pair<xstring,xstring>(name,format), required));
+            m_requestedAttrs.push_back(tuple<xstring,xstring,bool>(name,format,required));
 
         name = child->getAttributeNS(nullptr, _aliases);
         if (name && *name) {
             auto_ptr_char aliases(name);
-            char* pos;
-            char* start = const_cast<char*>(aliases.get());
-            while (start && *start) {
-                while (*start && isspace(*start))
-                    start++;
-                if (!*start)
-                    break;
-                pos = strchr(start,' ');
-                if (pos)
-                    *pos=0;
-                if (strcmp(start, "REMOTE_USER")) {
-                    decl.second.push_back(start);
-                    m_attributeIds.push_back(start);
-                }
-                else {
-                    m_log.warn("skipping alias, REMOTE_USER is a reserved name");
-                }
-                start = pos ? pos+1 : nullptr;
+            string dup(aliases.get());
+            set<string> new_aliases;
+            split(new_aliases, dup, is_space(), algorithm::token_compress_on);
+            set<string>::iterator ru = new_aliases.find("REMOTE_USER");
+            if (ru != new_aliases.end()) {
+                m_log.warn("skipping alias, REMOTE_USER is a reserved name");
+                new_aliases.erase(ru);
             }
+            m_attributeIds.insert(m_attributeIds.end(), new_aliases.begin(), new_aliases.end());
         }
 
         child = XMLHelper::getNextSiblingElement(child, shibspconstants::SHIB2ATTRIBUTEMAP_NS, saml1::Attribute::LOCAL_NAME);
     }
 
-    m_attrLock = RWLock::create();
+    m_attrLock.reset(RWLock::create());
 }
 
 void XMLExtractorImpl::generateMetadata(SPSSODescriptor& role) const
@@ -428,15 +418,15 @@ void XMLExtractorImpl::generateMetadata(SPSSODescriptor& role) const
     static const XMLCh english[] = UNICODE_LITERAL_2(e,n);
     sn->setLang(english);
 
-    for (vector< pair< pair<xstring,xstring>,bool > >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
+    for (vector< tuple<xstring,xstring,bool> >::const_iterator i = m_requestedAttrs.begin(); i != m_requestedAttrs.end(); ++i) {
         RequestedAttribute* req = RequestedAttributeBuilder::buildRequestedAttribute();
         svc->getRequestedAttributes().push_back(req);
-        req->setName(i->first.first.c_str());
-        if (i->first.second.empty())
+        req->setName(i->get<0>().c_str());
+        if (i->get<1>().empty())
             req->setNameFormat(saml2::Attribute::URI_REFERENCE);
         else
-            req->setNameFormat(i->first.second.c_str());
-        if (i->second)
+            req->setNameFormat(i->get<1>().c_str());
+        if (i->get<2>())
             req->isRequired(true);
     }
 }
@@ -446,18 +436,18 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const NameIdentifier& nameid,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
     const XMLCh* format = nameid.getFormat();
     if (!format || !*format)
         format = NameIdentifier::UNSPECIFIED;
-    if ((rule=m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
-        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
-        if (a)
+    attrmap_t::const_iterator rule;
+    if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
+        auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty));
+        if (a.get()) {
             attributes.push_back(a);
+        }
     }
     else if (m_log.isDebugEnabled()) {
         auto_ptr_char temp(format);
@@ -470,18 +460,18 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const NameID& nameid,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
     const XMLCh* format = nameid.getFormat();
     if (!format || !*format)
         format = NameID::UNSPECIFIED;
-    if ((rule=m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
-        Attribute* a = rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty);
-        if (a)
+    attrmap_t::const_iterator rule;
+    if ((rule = m_attrMap.find(pair<xstring,xstring>(format,xstring()))) != m_attrMap.end()) {
+        auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &nameid, assertingParty, relyingParty));
+        if (a.get()) {
             attributes.push_back(a);
+        }
     }
     else if (m_log.isDebugEnabled()) {
         auto_ptr_char temp(format);
@@ -494,21 +484,21 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const saml1::Attribute& attr,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
     const XMLCh* name = attr.getAttributeName();
     const XMLCh* format = attr.getAttributeNamespace();
     if (!name || !*name)
         return;
     if (!format || XMLString::equals(format, shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI))
         format = &chNull;
-    if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
-        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
-        if (a)
+    attrmap_t::const_iterator rule;
+    if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
+        auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+        if (a.get()) {
             attributes.push_back(a);
+        }
     }
     else if (m_log.isInfoEnabled()) {
         auto_ptr_char temp1(name);
@@ -522,11 +512,9 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const saml2::Attribute& attr,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    map< pair<xstring,xstring>,pair< AttributeDecoder*,vector<string> > >::const_iterator rule;
-
     const XMLCh* name = attr.getName();
     const XMLCh* format = attr.getNameFormat();
     if (!name || !*name)
@@ -535,20 +523,21 @@ void XMLExtractorImpl::extractAttributes(
         format = saml2::Attribute::UNSPECIFIED;
     else if (XMLString::equals(format, saml2::Attribute::URI_REFERENCE))
         format = &chNull;
-
-    if ((rule=m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
-        Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
-        if (a) {
+    attrmap_t::const_iterator rule;
+    if ((rule = m_attrMap.find(pair<xstring,xstring>(name,format))) != m_attrMap.end()) {
+        auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+        if (a.get()) {
             attributes.push_back(a);
             return;
         }
     }
     else if (XMLString::equals(format, saml2::Attribute::UNSPECIFIED)) {
         // As a fallback, if the format is "unspecified", null out the value and re-map.
-        if ((rule=m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
-            Attribute* a = rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty);
-            if (a) {
-                attributes.push_back(a);
+        if ((rule = m_attrMap.find(pair<xstring,xstring>(name,xstring()))) != m_attrMap.end()) {
+            auto_ptr<Attribute> a(rule->second.first->decode(rule->second.second, &attr, assertingParty, relyingParty));
+            if (a.get()) {
+                attributes.push_back(a.get());
+                a.release();
                 return;
             }
         }
@@ -566,12 +555,16 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const saml1::AttributeStatement& statement,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    const vector<saml1::Attribute*>& attrs = statement.getAttributes();
-    for (vector<saml1::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
-        extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+    static void (XMLExtractorImpl::* extract)(
+        const Application&, const char*, const char*, const saml1::Attribute&, ptr_vector<Attribute>&
+        ) const = &XMLExtractorImpl::extractAttributes;
+    for_each(
+        make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
+        boost::bind(extract, this, boost::ref(application), assertingParty, relyingParty, _1, boost::ref(attributes))
+        );
 }
 
 void XMLExtractorImpl::extractAttributes(
@@ -579,12 +572,16 @@ void XMLExtractorImpl::extractAttributes(
     const char* assertingParty,
     const char* relyingParty,
     const saml2::AttributeStatement& statement,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
-    const vector<saml2::Attribute*>& attrs = statement.getAttributes();
-    for (vector<saml2::Attribute*>::const_iterator a = attrs.begin(); a!=attrs.end(); ++a)
-        extractAttributes(application, assertingParty, relyingParty, *(*a), attributes);
+    static void (XMLExtractorImpl::* extract)(
+        const Application&, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
+        ) const = &XMLExtractorImpl::extractAttributes;
+    for_each(
+        make_indirect_iterator(statement.getAttributes().begin()), make_indirect_iterator(statement.getAttributes().end()),
+        boost::bind(extract, this, boost::ref(application), assertingParty, relyingParty, _1, boost::ref(attributes))
+        );
 }
 
 void XMLExtractorImpl::extractAttributes(
@@ -593,11 +590,11 @@ void XMLExtractorImpl::extractAttributes(
     const XMLCh* entityID,
     const char* relyingParty,
     const Extensions& ext,
-    vector<Attribute*>& attributes
+    ptr_vector<Attribute>& attributes
     ) const
 {
     const vector<XMLObject*>& exts = ext.getUnknownXMLObjects();
-    for (vector<XMLObject*>::const_iterator i = exts.begin(); i!=exts.end(); ++i) {
+    for (vector<XMLObject*>::const_iterator i = exts.begin(); i != exts.end(); ++i) {
         const EntityAttributes* container = dynamic_cast<const EntityAttributes*>(*i);
         if (!container)
             continue;
@@ -614,7 +611,8 @@ void XMLExtractorImpl::extractAttributes(
                 m_attrLock->unlock();
                 m_attrLock->wrlock();
                 cacheEntry = m_decodedMap.find(observable);
-                if (cacheEntry==m_decodedMap.end()) {
+                if (cacheEntry == m_decodedMap.end()) {
+                    SharedLock locker(m_attrLock, false);   // guard in case these throw
 
                     // It's still brand new, so hook it for cache activation.
                     observable->addObserver(this);
@@ -624,6 +622,7 @@ void XMLExtractorImpl::extractAttributes(
 
                     // Downgrade the lock.
                     // We don't have to recheck because we never erase the master map entry entirely, even on changes.
+                    locker.release();   // unguard for lock downgrade
                     m_attrLock->unlock();
                     m_attrLock->rdlock();
                 }
@@ -632,46 +631,46 @@ void XMLExtractorImpl::extractAttributes(
         }
 
         if (useCache) {
-            // We're holding a read lock, so check the cache.
+            // We're holding the lock, so check the cache.
             decoded_t::iterator d = cacheEntry->second.find(container);
             if (d != cacheEntry->second.end()) {
                 SharedLock locker(m_attrLock, false);   // pop the lock when we're done
                 for (vector<DDF>::iterator obj = d->second.begin(); obj != d->second.end(); ++obj) {
                     auto_ptr<Attribute> wrapper(Attribute::unmarshall(*obj));
                     m_log.debug("recovered cached metadata attribute (%s)", wrapper->getId());
-                    attributes.push_back(wrapper.release());
+                    attributes.push_back(wrapper);
                 }
                 break;
             }
         }
 
+        // Add a guard for the lock if we're caching.
+        SharedLock locker(useCache ? m_attrLock.get() : nullptr, false);
+
         // Use a holding area to support caching.
-        vector<Attribute*> holding;
+        ptr_vector<Attribute> holding;
 
-        const vector<saml2::Attribute*>& attrs = container->getAttributes();
-        for (vector<saml2::Attribute*>::const_iterator attr = attrs.begin(); attr != attrs.end(); ++attr) {
-            try {
-                extractAttributes(application, nullptr, relyingParty, *(*attr), holding);
-            }
-            catch (...) {
-                if (useCache)
-                    m_attrLock->unlock();
-                for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
-                throw;
-            }
-        }
+        // Extract attributes into holding area with no asserting party set.
+        static void (XMLExtractorImpl::* extractV2Attr)(
+            const Application&, const char*, const char*, const saml2::Attribute&, ptr_vector<Attribute>&
+            ) const = &XMLExtractorImpl::extractAttributes;
+        for_each(
+            make_indirect_iterator(container->getAttributes().begin()), make_indirect_iterator(container->getAttributes().end()),
+            boost::bind(extractV2Attr, this, boost::ref(application), nullptr, relyingParty, _1, boost::ref(holding))
+            );
 
         if (entityID && m_entityAssertions) {
             const vector<saml2::Assertion*>& asserts = container->getAssertions();
-            for (vector<saml2::Assertion*>::const_iterator assert = asserts.begin(); assert != asserts.end(); ++assert) {
-                if (!(*assert)->getSignature()) {
+            for (indirect_iterator<vector<saml2::Assertion*>::const_iterator> assert = make_indirect_iterator(asserts.begin());
+                    assert != make_indirect_iterator(asserts.end()); ++assert) {
+                if (!(assert->getSignature())) {
                     if (m_log.isDebugEnabled()) {
                         auto_ptr_char eid(entityID);
                         m_log.debug("skipping unsigned assertion in metadata extension for entity (%s)", eid.get());
                     }
                     continue;
                 }
-                else if ((*assert)->getAttributeStatements().empty()) {
+                else if (assert->getAttributeStatements().empty()) {
                     if (m_log.isDebugEnabled()) {
                         auto_ptr_char eid(entityID);
                         m_log.debug("skipping assertion with no AttributeStatement in metadata extension for entity (%s)", eid.get());
@@ -680,7 +679,7 @@ void XMLExtractorImpl::extractAttributes(
                 }
                 else {
                     // Check subject.
-                    const NameID* subject = (*assert)->getSubject() ? (*assert)->getSubject()->getNameID() : nullptr;
+                    const NameID* subject = assert->getSubject() ? assert->getSubject()->getNameID() : nullptr;
                     if (!subject ||
                             !XMLString::equals(subject->getFormat(), NameID::ENTITY) ||
                             !XMLString::equals(subject->getName(), entityID)) {
@@ -692,25 +691,22 @@ void XMLExtractorImpl::extractAttributes(
                     }
                 }
 
-                // Use a private holding area for filtering purposes.
-                vector<Attribute*> holding2;
-
                 try {
                     // Set up and evaluate a policy for an AA asserting attributes to us.
                     shibsp::SecurityPolicy policy(application, &AttributeAuthorityDescriptor::ELEMENT_QNAME, false, m_policyId.c_str());
-                    Locker locker(m_metadata);
+                    Locker locker(m_metadata.get());
                     if (m_metadata)
-                        policy.setMetadataProvider(m_metadata);
+                        policy.setMetadataProvider(m_metadata.get());
                     if (m_trust)
-                        policy.setTrustEngine(m_trust);
+                        policy.setTrustEngine(m_trust.get());
                     // Populate recipient as audience.
-                    const XMLCh* issuer = (*assert)->getIssuer() ? (*assert)->getIssuer()->getName() : nullptr;
+                    const XMLCh* issuer = assert->getIssuer() ? assert->getIssuer()->getName() : nullptr;
                     policy.getAudiences().push_back(application.getRelyingParty(issuer)->getXMLString("entityID").second);
 
                     // Extract assertion information for policy.
-                    policy.setMessageID((*assert)->getID());
-                    policy.setIssueInstant((*assert)->getIssueInstantEpoch());
-                    policy.setIssuer((*assert)->getIssuer());
+                    policy.setMessageID(assert->getID());
+                    policy.setIssueInstant(assert->getIssueInstantEpoch());
+                    policy.setIssuer(assert->getIssuer());
 
                     // Look up metadata for issuer.
                     if (policy.getIssuer() && policy.getMetadataProvider()) {
@@ -739,7 +735,7 @@ void XMLExtractorImpl::extractAttributes(
                     }
 
                     // Authenticate the assertion. We have to clone and marshall it to establish the signature for verification.
-                    auto_ptr<saml2::Assertion> tokencopy((*assert)->cloneAssertion());
+                    scoped_ptr<saml2::Assertion> tokencopy(assert->cloneAssertion());
                     tokencopy->marshall();
                     policy.evaluate(*tokencopy);
                     if (!policy.isAuthenticated()) {
@@ -758,37 +754,59 @@ void XMLExtractorImpl::extractAttributes(
                         policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
                     auto_ptr_char inlineAssertingParty(inlineEntity ? inlineEntity->getEntityID() : nullptr);
                     relyingParty = application.getRelyingParty(inlineEntity)->getString("entityID").second;
+
+                    // Use a private holding area for filtering purposes.
+                    ptr_vector<Attribute> holding2;
                     const vector<saml2::Attribute*>& attrs2 =
                         const_cast<const saml2::AttributeStatement*>(tokencopy->getAttributeStatements().front())->getAttributes();
-                    for (vector<saml2::Attribute*>::const_iterator a = attrs2.begin(); a!=attrs2.end(); ++a)
-                        extractAttributes(application, inlineAssertingParty.get(), relyingParty, *(*a), holding2);
+                    for_each(
+                        make_indirect_iterator(attrs2.begin()), make_indirect_iterator(attrs2.end()),
+                        boost::bind(extractV2Attr, this, boost::ref(application), inlineAssertingParty.get(), relyingParty, _1, boost::ref(holding2))
+                        );
 
                     // Now we locally filter the attributes so that the actual issuer can be properly set.
                     // If we relied on outside filtering, the attributes couldn't be distinguished from the
                     // ones that come from the user's IdP.
                     if (m_filter && !holding2.empty()) {
-                        BasicFilteringContext fc(application, holding2, policy.getIssuerMetadata());
-                        Locker filtlocker(m_filter);
+
+                        // The filter API uses an unsafe container, so we have to transfer everything into one and back.
+                        vector<Attribute*> unsafe_holding2;
+
+                        // Use a local exception context since the container is unsafe.
                         try {
-                            m_filter->filterAttributes(fc, holding2);
+                            while (!holding2.empty()) {
+                                ptr_vector<Attribute>::auto_type ptr = holding2.pop_back();
+                                unsafe_holding2.push_back(ptr.get());
+                                ptr.release();
+                            }
+                            BasicFilteringContext fc(application, unsafe_holding2, policy.getIssuerMetadata());
+                            Locker filtlocker(m_filter.get());
+                            m_filter->filterAttributes(fc, unsafe_holding2);
+
+                            // Transfer back to safe container
+                            while (!unsafe_holding2.empty()) {
+                                auto_ptr<Attribute> ptr(unsafe_holding2.back());
+                                unsafe_holding2.pop_back();
+                                holding2.push_back(ptr);
+                            }
                         }
-                        catch (exception& ex) {
+                        catch (std::exception& ex) {
                             m_log.error("caught exception filtering attributes: %s", ex.what());
                             m_log.error("dumping extracted attributes due to filtering exception");
-                            for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
-                            holding2.clear();
+                            for_each(unsafe_holding2.begin(), unsafe_holding2.end(), xmltooling::cleanup<Attribute>());
+                            holding2.clear();   // in case the exception was during transfer between containers
                         }
                     }
 
                     if (!holding2.empty()) {
-                        // Copy them over to the main holding tank.
-                        holding.insert(holding.end(), holding2.begin(), holding2.end());
+                        // Copy them over to the main holding tank, which transfers ownership.
+                        holding.transfer(holding.end(), holding2);
                     }
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     // Known exceptions are handled gracefully by skipping the assertion.
                     if (m_log.isDebugEnabled()) {
-                        auto_ptr_char tempid((*assert)->getID());
+                        auto_ptr_char tempid(assert->getID());
                         auto_ptr_char eid(entityID);
                         m_log.debug(
                             "exception authenticating assertion (%s) in metadata extension for entity (%s): %s",
@@ -797,36 +815,33 @@ void XMLExtractorImpl::extractAttributes(
                             ex.what()
                             );
                     }
-                    for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
                     continue;
                 }
-                catch (...) {
-                    // Unknown exceptions are fatal.
-                    if (useCache)
-                        m_attrLock->unlock();
-                    for_each(holding.begin(), holding.end(), xmltooling::cleanup<Attribute>());
-                    for_each(holding2.begin(), holding2.end(), xmltooling::cleanup<Attribute>());
-                    throw;
-                }
             }
         }
 
         if (!holding.empty()) {
             if (useCache) {
+                locker.release();   // unguard to upgrade lock
                 m_attrLock->unlock();
                 m_attrLock->wrlock();
-                SharedLock locker(m_attrLock, false);   // pop the lock when we're done
+                SharedLock locker2(m_attrLock, false);   // pop the lock when we're done
                 if (cacheEntry->second.count(container) == 0) {
-                    for (vector<Attribute*>::const_iterator held = holding.begin(); held != holding.end(); ++held)
-                        cacheEntry->second[container].push_back((*held)->marshall());
+                    static void (vector<DDF>::* push_back)(DDF const &) = &vector<DDF>::push_back;
+                    vector<DDF>& marshalled = cacheEntry->second[container];
+                    for_each(
+                        holding.begin(), holding.end(),
+                        boost::bind(push_back, boost::ref(marshalled), boost::bind(&Attribute::marshall, _1))
+                        );
                 }
             }
-            attributes.insert(attributes.end(), holding.begin(), holding.end());
-        }
-        else if (useCache) {
-            m_attrLock->unlock();
+
+            // Copy them to the output parameter, which transfers ownership.
+            attributes.transfer(attributes.end(), holding);
         }
 
+        // If the lock is held, it's guarded.
+
         break;  // only process a single extension element
     }
 }
@@ -838,6 +853,30 @@ void XMLExtractor::extractAttributes(
     if (!m_impl)
         return;
 
+    ptr_vector<Attribute> holding;
+    extractAttributes(application, issuer, xmlObject, holding);
+
+    // Transfer ownership from the ptr_vector to the unsafe vector for API compatibility.
+    // Any throws should leave each container in a consistent state. The holding container
+    // is freed by us, and the result container by the caller.
+    while (!holding.empty()) {
+        ptr_vector<Attribute>::auto_type ptr = holding.pop_back();
+        attributes.push_back(ptr.get());
+        ptr.release();
+    }
+}
+
+void XMLExtractor::extractAttributes(
+    const Application& application, const RoleDescriptor* issuer, const XMLObject& xmlObject, ptr_vector<Attribute>& attributes
+    ) const
+{
+    static void (XMLExtractor::* extractEncrypted)(
+        const Application&, const RoleDescriptor*, const XMLObject&, ptr_vector<Attribute>&
+        ) const = &XMLExtractor::extractAttributes;
+    static void (XMLExtractorImpl::* extractV1Statement)(
+        const Application&, const char*, const char*, const saml1::AttributeStatement&, ptr_vector<Attribute>&
+        ) const = &XMLExtractorImpl::extractAttributes;
+
     const EntityDescriptor* entity = issuer ? dynamic_cast<const EntityDescriptor*>(issuer->getParent()) : nullptr;
     const char* relyingParty = application.getRelyingParty(entity)->getString("entityID").second;
 
@@ -849,8 +888,10 @@ void XMLExtractor::extractAttributes(
             m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *statement2, attributes);
             // Handle EncryptedAttributes inline so we have access to the role descriptor.
             const vector<saml2::EncryptedAttribute*>& encattrs = statement2->getEncryptedAttributes();
-            for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
-                extractAttributes(application, issuer, *(*ea), attributes);
+            for_each(
+                make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
+                boost::bind(extractEncrypted, this, boost::ref(application), issuer, _1, boost::ref(attributes))
+                );
             return;
         }
 
@@ -870,12 +911,15 @@ void XMLExtractor::extractAttributes(
         if (token2) {
             auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
             const vector<saml2::AttributeStatement*>& statements = token2->getAttributeStatements();
-            for (vector<saml2::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s) {
-                m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
+            for (indirect_iterator<vector<saml2::AttributeStatement*>::const_iterator> s = make_indirect_iterator(statements.begin());
+                    s != make_indirect_iterator(statements.end()); ++s) {
+                m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *s, attributes);
                 // Handle EncryptedAttributes inline so we have access to the role descriptor.
-                const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement*>(*s)->getEncryptedAttributes();
-                for (vector<saml2::EncryptedAttribute*>::const_iterator ea = encattrs.begin(); ea!=encattrs.end(); ++ea)
-                    extractAttributes(application, issuer, *(*ea), attributes);
+                const vector<saml2::EncryptedAttribute*>& encattrs = const_cast<const saml2::AttributeStatement&>(*s).getEncryptedAttributes();
+                for_each(
+                    make_indirect_iterator(encattrs.begin()), make_indirect_iterator(encattrs.end()),
+                    boost::bind(extractEncrypted, this, boost::ref(application), issuer, _1, boost::ref(attributes))
+                    );
             }
             return;
         }
@@ -884,8 +928,9 @@ void XMLExtractor::extractAttributes(
         if (token1) {
             auto_ptr_char assertingParty(entity ? entity->getEntityID() : nullptr);
             const vector<saml1::AttributeStatement*>& statements = token1->getAttributeStatements();
-            for (vector<saml1::AttributeStatement*>::const_iterator s = statements.begin(); s!=statements.end(); ++s)
-                m_impl->extractAttributes(application, assertingParty.get(), relyingParty, *(*s), attributes);
+            for_each(make_indirect_iterator(statements.begin()), make_indirect_iterator(statements.end()),
+                boost::bind(extractV1Statement, m_impl.get(), boost::ref(application), assertingParty.get(), relyingParty, _1, boost::ref(attributes))
+                );
             return;
         }
 
@@ -955,19 +1000,19 @@ void XMLExtractor::extractAttributes(
                 Locker credlocker(cr);
                 if (issuer) {
                     MetadataCredentialCriteria mcc(*issuer);
-                    auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
+                    scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient, &mcc));
                     if (m_log.isDebugEnabled())
-                        m_log.debugStream() << "decrypted Attribute: " << *(decrypted.get()) << logging::eol;
-                    return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+                        m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
+                    return extractAttributes(application, issuer, *decrypted, attributes);
                 }
                 else {
-                    auto_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
+                    scoped_ptr<XMLObject> decrypted(encattr->decrypt(*cr, recipient));
                     if (m_log.isDebugEnabled())
-                        m_log.debugStream() << "decrypted Attribute: " << *(decrypted.get()) << logging::eol;
-                    return extractAttributes(application, issuer, *(decrypted.get()), attributes);
+                        m_log.debugStream() << "decrypted Attribute: " << *decrypted << logging::eol;
+                    return extractAttributes(application, issuer, *decrypted, attributes);
                 }
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("caught exception decrypting Attribute: %s", ex.what());
                 return;
             }
@@ -998,7 +1043,7 @@ pair<bool,DOMElement*> XMLExtractor::background_load()
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLExtractorImpl* impl = new XMLExtractorImpl(raw.second, m_log);
+    scoped_ptr<XMLExtractorImpl> impl(new XMLExtractorImpl(raw.second, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -1007,8 +1052,7 @@ pair<bool,DOMElement*> XMLExtractor::background_load()
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
+    m_impl.swap(impl);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
index 907c1ff..be0ed8c 100644 (file)
@@ -31,6 +31,8 @@
 #include "util/SPConstants.h"
 
 #include <map>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
 #include <xmltooling/io/HTTPResponse.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 using shibspconstants::SHIB2SPPROTOCOLS_NS;
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
-
     static const XMLCh _id[] =          UNICODE_LITERAL_2(i,d);
     static const XMLCh Binding[] =      UNICODE_LITERAL_7(B,i,n,d,i,n,g);
     static const XMLCh Initiator[] =    UNICODE_LITERAL_9(I,n,i,t,i,a,t,o,r);
@@ -62,10 +64,6 @@ namespace shibsp {
     public:
         XMLProtocolProviderImpl(const DOMElement* e, Category& log);
         ~XMLProtocolProviderImpl() {
-            for (protmap_t::iterator i = m_map.begin(); i != m_map.end(); ++i) {
-                delete i->second.first;
-                for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<PropertySet>());
-            }
             if (m_document)
                 m_document->release();
         }
@@ -86,8 +84,9 @@ namespace shibsp {
     private:
         DOMDocument* m_document;
         // Map of protocol/service pair to an Initiator propset plus an array of Binding propsets.
-        typedef map< pair<string,string>, pair< PropertySet*,vector<const PropertySet*> > > protmap_t;
+        typedef map< pair<string,string>, pair< const PropertySet*,vector<const PropertySet*> > > protmap_t;
         protmap_t m_map;
+        vector< boost::shared_ptr<PropertySet> > m_propsetJanitor;  // needed to maintain vector API
 
         friend class SHIBSP_DLLLOCAL XMLProtocolProvider;
     };
@@ -96,13 +95,12 @@ namespace shibsp {
     {
     public:
         XMLProtocolProvider(const DOMElement* e)
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".ProtocolProvider.XML")), m_impl(nullptr) {
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".ProtocolProvider.XML")) {
             background_load(); // guarantees an exception or the policy is loaded
         }
 
         ~XMLProtocolProvider() {
             shutdown();
-            delete m_impl;
         }
 
         const PropertySet* getInitiator(const char* protocol, const char* service) const {
@@ -121,7 +119,7 @@ namespace shibsp {
 
     private:
         static vector<const PropertySet*> m_noBindings;
-        XMLProtocolProviderImpl* m_impl;
+        scoped_ptr<XMLProtocolProviderImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -154,8 +152,6 @@ XMLProtocolProviderImpl::XMLProtocolProviderImpl(const DOMElement* e, Category&
 #ifdef _DEBUG
     xmltooling::NDC ndc("XMLProtocolProviderImpl");
 #endif
-    //typedef map< pair<string,string>, pair< PropertySet*,vector<const PropertySet*> > > protmap_t;
-
     if (!XMLHelper::isNodeNamed(e, SHIB2SPPROTOCOLS_NS, Protocols))
         throw ConfigurationException("XML ProtocolProvider requires prot:Protocols at root of configuration.");
 
@@ -167,13 +163,14 @@ XMLProtocolProviderImpl::XMLProtocolProviderImpl(const DOMElement* e, Category&
             while (svc) {
                 string svcid = XMLHelper::getAttrString(svc, nullptr, _id);
                 if (!svcid.empty() && m_map.count(make_pair(id,svcid)) == 0) {
-                    pair< PropertySet*,vector<const PropertySet*> >& entry = m_map[make_pair(id,svcid)];
+                    pair< const PropertySet*,vector<const PropertySet*> >& entry = m_map[make_pair(id,svcid)];
                     // Wrap the Initiator in a propset, if any.
                     const DOMElement* child = XMLHelper::getFirstChildElement(svc, SHIB2SPPROTOCOLS_NS, Initiator);
                     if (child) {
-                        DOMPropertySet* initprop = new DOMPropertySet();
-                        entry.first = initprop;
+                        boost::shared_ptr<DOMPropertySet> initprop(new DOMPropertySet());
                         initprop->load(child, nullptr, this);
+                        m_propsetJanitor.push_back(initprop);
+                        entry.first = initprop.get();
                     }
                     else {
                         entry.first = nullptr;
@@ -182,9 +179,10 @@ XMLProtocolProviderImpl::XMLProtocolProviderImpl(const DOMElement* e, Category&
                     // Walk the Bindings.
                     child = XMLHelper::getFirstChildElement(svc, SHIB2SPPROTOCOLS_NS, Binding);
                     while (child) {
-                        DOMPropertySet* bindprop = new DOMPropertySet();
-                        entry.second.push_back(bindprop);
+                        boost::shared_ptr<DOMPropertySet> bindprop(new DOMPropertySet());
                         bindprop->load(child, nullptr, this);
+                        m_propsetJanitor.push_back(bindprop);
+                        entry.second.push_back(bindprop.get());
                         child = XMLHelper::getNextSiblingElement(child, SHIB2SPPROTOCOLS_NS, Binding);
                     }
                 }
@@ -204,7 +202,7 @@ pair<bool,DOMElement*> XMLProtocolProvider::load(bool backup)
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLProtocolProviderImpl* impl = new XMLProtocolProviderImpl(raw.second, m_log);
+    scoped_ptr<XMLProtocolProviderImpl> impl(new XMLProtocolProviderImpl(raw.second, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -213,8 +211,7 @@ pair<bool,DOMElement*> XMLProtocolProvider::load(bool backup)
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
+    m_impl.swap(impl);
 
 
     return make_pair(false,(DOMElement*)nullptr);
@@ -232,7 +229,7 @@ pair<bool,DOMElement*> XMLProtocolProvider::background_load()
             return load(true);
         throw;
     }
-    catch (exception&) {
+    catch (std::exception&) {
         if (!m_loaded && !m_backing.empty())
             return load(true);
         throw;
index d0f35b4..9849124 100644 (file)
 #include "SPRequest.h"
 
 #include <algorithm>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xmltooling/unicode.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -46,23 +48,21 @@ namespace shibsp {
     public:
         ChainingAccessControl(const DOMElement* e);
 
-        ~ChainingAccessControl() {
-            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
-        }
+        ~ChainingAccessControl() {}
 
         Lockable* lock() {
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+            for_each(m_ac.begin(), m_ac.end(), mem_fun_ref<Lockable*,Lockable>(&Lockable::lock));
             return this;
         }
         void unlock() {
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+            for_each(m_ac.begin(), m_ac.end(), mem_fun_ref<void,Lockable>(&Lockable::unlock));
         }
 
         aclresult_t authorized(const SPRequest& request, const Session* session) const;
 
     private:
         enum operator_t { OP_AND, OP_OR } m_op;
-        vector<AccessControl*> m_ac;
+        ptr_vector<AccessControl> m_ac;
     };
 
     AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
@@ -99,26 +99,20 @@ ChainingAccessControl::ChainingAccessControl(const DOMElement* e)
 {
     const XMLCh* op = e ? e->getAttributeNS(nullptr, _operator) : nullptr;
     if (XMLString::equals(op, AND))
-        m_op=OP_AND;
+        m_op = OP_AND;
     else if (XMLString::equals(op, OR))
-        m_op=OP_OR;
+        m_op = OP_OR;
     else
         throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
 
-    try {
-        e = XMLHelper::getFirstChildElement(e, _AccessControl);
-        while (e) {
-            string t(XMLHelper::getAttrString(e, nullptr, _type));
-            if (!t.empty()) {
-                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", t.c_str());
-                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), e));
-            }
-            e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+    e = XMLHelper::getFirstChildElement(e, _AccessControl);
+    while (e) {
+        string t(XMLHelper::getAttrString(e, nullptr, _type));
+        if (!t.empty()) {
+            Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", t.c_str());
+            m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), e));
         }
-    }
-    catch (exception&) {
-        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
-        throw;
+        e = XMLHelper::getNextSiblingElement(e, _AccessControl);
     }
     if (m_ac.empty())
         throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
@@ -129,8 +123,8 @@ AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& re
     switch (m_op) {
         case OP_AND:
         {
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
-                if ((*i)->authorized(request, session) != shib_acl_true) {
+            for (ptr_vector<AccessControl>::const_iterator i = m_ac.begin(); i != m_ac.end(); ++i) {
+                if (i->authorized(request, session) != shib_acl_true) {
                     request.log(SPRequest::SPDebug, "embedded AccessControl plugin unsuccessful, denying access");
                     return shib_acl_false;
                 }
@@ -140,8 +134,8 @@ AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& re
 
         case OP_OR:
         {
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
-                if ((*i)->authorized(request,session) == shib_acl_true)
+            for (ptr_vector<AccessControl>::const_iterator i = m_ac.begin(); i != m_ac.end(); ++i) {
+                if (i->authorized(request,session) == shib_acl_true)
                     return shib_acl_true;
             }
             request.log(SPRequest::SPDebug, "all embedded AccessControl plugins unsuccessful, denying access");
index 8139b02..a3987ab 100644 (file)
@@ -44,6 +44,9 @@
 #include "util/SPConstants.h"
 
 #include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/io/HTTPRequest.h>
 #include <xmltooling/io/HTTPResponse.h>
 #include <xmltooling/util/DateTime.h>
@@ -69,6 +72,7 @@ using namespace opensaml::saml2md;
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -210,26 +214,22 @@ namespace shibsp {
         string m_inboundHeader,m_outboundHeader;
 
         // inproc means we buffer sessions in memory
-        RWLock* m_lock;
+        scoped_ptr<RWLock> m_lock;
         map<string,StoredSession*> m_hashtable;
 
         // management of buffered sessions
-       void dormant(const char* key);
-       static void* cleanup_fn(void*);
+        void dormant(const char* key);
+        static void* cleanup_fn(void*);
 
         bool shutdown;
-        CondWait* shutdown_wait;
-        Thread* cleanup_thread;
+        scoped_ptr<CondWait> shutdown_wait;
+        scoped_ptr<Thread> cleanup_thread;
     };
 
     class StoredSession : public virtual Session
     {
     public:
-        StoredSession(SSCache* cache, DDF& obj) : m_obj(obj),
-#ifndef SHIBSP_LITE
-                m_nameid(nullptr),
-#endif
-                m_cache(cache), m_expires(0), m_lastAccess(time(nullptr)), m_lock(nullptr) {
+        StoredSession(SSCache* cache, DDF& obj) : m_obj(obj), m_cache(cache), m_expires(0), m_lastAccess(time(nullptr)) {
             auto_ptr_XMLCh exp(m_obj["expires"].string());
             if (exp.get()) {
                 DateTime iso(exp.get());
@@ -244,33 +244,27 @@ namespace shibsp {
                 istringstream instr(nameid);
                 DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(instr);
                 XercesJanitor<DOMDocument> janitor(doc);
-                auto_ptr<saml2::NameID> n(saml2::NameIDBuilder::buildNameID());
-                n->unmarshall(doc->getDocumentElement(), true);
+                m_nameid.reset(saml2::NameIDBuilder::buildNameID());
+                m_nameid->unmarshall(doc->getDocumentElement(), true);
                 janitor.release();
-                m_nameid = n.release();
             }
 #endif
             if (cache->inproc)
-                m_lock = Mutex::create();
+                m_lock.reset(Mutex::create());
         }
 
         ~StoredSession() {
-            delete m_lock;
             m_obj.destroy();
             for_each(m_attributes.begin(), m_attributes.end(), xmltooling::cleanup<Attribute>());
-#ifndef SHIBSP_LITE
-            delete m_nameid;
-            for_each(m_tokens.begin(), m_tokens.end(), cleanup_pair<string,Assertion>());
-#endif
         }
 
         Lockable* lock() {
-            if (m_lock)
+            if (m_lock.get())
                 m_lock->lock();
             return this;
         }
         void unlock() {
-            if (m_lock)
+            if (m_lock.get())
                 m_lock->unlock();
             else
                 delete this;
@@ -296,7 +290,7 @@ namespace shibsp {
         }
 #ifndef SHIBSP_LITE
         const saml2::NameID* getNameID() const {
-            return m_nameid;
+            return m_nameid.get();
         }
 #endif
         const char* getSessionIndex() const {
@@ -353,8 +347,8 @@ namespace shibsp {
 
         DDF m_obj;
 #ifndef SHIBSP_LITE
-        saml2::NameID* m_nameid;
-        mutable map<string,Assertion*> m_tokens;
+        scoped_ptr<saml2::NameID> m_nameid;
+        mutable map<string,boost::shared_ptr<Assertion>> m_tokens;
 #endif
         mutable vector<Attribute*> m_attributes;
         mutable multimap<string,const Attribute*> m_attributeIndex;
@@ -362,7 +356,7 @@ namespace shibsp {
 
         SSCache* m_cache;
         time_t m_expires,m_lastAccess;
-        Mutex* m_lock;
+        scoped_ptr<Mutex> m_lock;
     };
 
     SessionCache* SHIBSP_DLLLOCAL StorageServiceCacheFactory(const DOMElement* const & e)
@@ -501,7 +495,7 @@ void StoredSession::validate(const Application& app, const char* client_addr, ti
         try {
             m_cache->m_storage->updateContext(getID(), now + cacheTimeout);
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_cache->m_log.error("failed to update session expiration: %s", ex.what());
         }
 
@@ -559,7 +553,7 @@ void StoredSession::addAttributes(const vector<Attribute*>& attributes)
         try {
             ver = m_cache->m_storage->updateText(getID(), "session", record.c_str(), 0, m_obj["version"].integer()-1);
         }
-        catch (exception&) {
+        catch (std::exception&) {
             // Roll back modification to record.
             m_obj["version"].integer(m_obj["version"].integer()-1);
             vector<Attribute*>::size_type count = attributes.size();
@@ -614,9 +608,9 @@ const Assertion* StoredSession::getAssertion(const char* id) const
     if (!m_cache->m_storage)
         throw ConfigurationException("Assertion retrieval requires a StorageService.");
 
-    map<string,Assertion*>::const_iterator i = m_tokens.find(id);
-    if (i!=m_tokens.end())
-        return i->second;
+    map< string,boost::shared_ptr<Assertion> >::const_iterator i = m_tokens.find(id);
+    if (i != m_tokens.end())
+        return i->second.get();
 
     string tokenstr;
     if (!m_cache->m_storage->readText(getID(), id, &tokenstr, nullptr))
@@ -626,17 +620,15 @@ const Assertion* StoredSession::getAssertion(const char* id) const
     istringstream instr(tokenstr);
     DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(instr);
     XercesJanitor<DOMDocument> janitor(doc);
-    auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
+    boost::shared_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
     janitor.release();
-
-    Assertion* token = dynamic_cast<Assertion*>(xmlObject.get());
+    
+    boost::shared_ptr<Assertion> token = dynamic_pointer_cast<Assertion,XMLObject>(xmlObject);
     if (!token)
         throw FatalProfileException("Request for cached assertion returned an unknown object type.");
 
-    // Transfer ownership to us.
-    xmlObject.release();
-    m_tokens[id]=token;
-    return token;
+    m_tokens[id] = token;
+    return token.get();
 }
 
 void StoredSession::addAssertion(Assertion* assertion)
@@ -682,7 +674,7 @@ void StoredSession::addAssertion(Assertion* assertion)
         try {
             ver = m_cache->m_storage->updateText(getID(), "session", record.c_str(), 0, m_obj["version"].integer()-1);
         }
-        catch (exception&) {
+        catch (std::exception&) {
             token.destroy();
             m_obj["version"].integer(m_obj["version"].integer()-1);
             m_cache->m_storage->deleteText(getID(), id.get());
@@ -777,8 +769,7 @@ SSCache::SSCache(const DOMElement* e)
 #ifndef SHIBSP_LITE
       m_storage(nullptr), m_storage_lite(nullptr), m_cacheAssertions(true),
 #endif
-      m_root(e), m_inprocTimeout(900), m_cacheTimeout(0), m_cacheAllowance(0),
-      m_lock(nullptr), shutdown(false), shutdown_wait(nullptr), cleanup_thread(nullptr)
+      m_root(e), m_inprocTimeout(900), m_cacheTimeout(0), m_cacheAllowance(0), shutdown(false)
 {
     SPConfig& conf = SPConfig::getConfig();
     inproc = conf.isEnabled(SPConfig::InProcess);
@@ -840,9 +831,9 @@ SSCache::SSCache(const DOMElement* e)
     if (inproc) {
         if (!conf.isEnabled(SPConfig::OutOfProcess) && !listener)
             throw ConfigurationException("SessionCache requires a ListenerService, but none available.");
-        m_lock = RWLock::create();
-        shutdown_wait = CondWait::create();
-        cleanup_thread = Thread::create(&cleanup_fn, this);
+        m_lock.reset(RWLock::create());
+        shutdown_wait.reset(CondWait::create());
+        cleanup_thread.reset(Thread::create(&cleanup_fn, this));
     }
 #ifndef SHIBSP_LITE
     else {
@@ -863,14 +854,12 @@ SSCache::~SSCache()
     if (inproc) {
         // Shut down the cleanup thread and let it know...
         shutdown = true;
-        shutdown_wait->signal();
-        cleanup_thread->join(nullptr);
+        if (shutdown_wait.get())
+            shutdown_wait->signal();
+        if (cleanup_thread.get())
+            cleanup_thread->join(nullptr);
 
         for_each(m_hashtable.begin(),m_hashtable.end(),cleanup_pair<string,StoredSession>());
-        delete m_lock;
-
-        delete cleanup_thread;
-        delete shutdown_wait;
     }
 #ifndef SHIBSP_LITE
     else {
@@ -1085,7 +1074,7 @@ void SSCache::insert(
         if (nameid)
             insert(key.get(), expires, name.get(), index.get());
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error storing back mapping of NameID for logout: %s", ex.what());
     }
 
@@ -1101,7 +1090,7 @@ void SSCache::insert(
                     throw IOException("Duplicate assertion ID ($1)", params(1, tokenid.get()));
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("error storing assertion along with session: %s", ex.what());
         }
     }
@@ -1154,7 +1143,7 @@ bool SSCache::matches(
             }
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error while matching session: %s", ex.what());
     }
     return false;
@@ -1264,7 +1253,7 @@ vector<string>::size_type SSCache::logout(
                 try {
                     session = find(app, key.string());
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("error locating session (%s): %s", key.string(), ex.what());
                 }
 
@@ -1315,7 +1304,7 @@ vector<string>::size_type SSCache::logout(
                 m_log.warn("logout mapping record changed behind us, leaving it alone");
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error updating logout mapping record: %s", ex.what());
     }
 
@@ -1373,7 +1362,7 @@ LogoutEvent* SSCache::newLogoutEvent(const Application& app) const
             m_log.warn("unable to audit event, log event object was of an incorrect type");
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.warn("exception auditing event: %s", ex.what());
     }
     return nullptr;
@@ -1470,7 +1459,7 @@ Session* SSCache::find(const Application& app, const char* key, const char* clie
 
             if (timeout && *timeout > 0 && now - lastAccess >= *timeout) {
                 m_log.info("session timed out (ID: %s)", key);
-                auto_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
+                scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
                 if (logout_event.get()) {
                     logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
                     logout_event->m_sessions.push_back(key);
@@ -1492,7 +1481,7 @@ Session* SSCache::find(const Application& app, const char* key, const char* clie
                 try {
                     m_storage->updateContext(key, now + cacheTimeout);
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     m_log.error("failed to update session expiration: %s", ex.what());
                 }
             }
@@ -1535,7 +1524,7 @@ Session* SSCache::find(const Application& app, const char* key, const char* clie
     }
     catch (...) {
 #ifndef SHIBSP_LITE
-        auto_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
+        scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(app));
         if (logout_event.get()) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
             logout_event->m_session = session;
@@ -1570,7 +1559,7 @@ Session* SSCache::find(const Application& app, HTTPRequest& request, const char*
             response->setCookie(shib_cookie.first.c_str(), exp.c_str());
         }
     }
-    catch (exception&) {
+    catch (std::exception&) {
         HTTPResponse* response = dynamic_cast<HTTPResponse*>(&request);
         if (response) {
             if (!m_outboundHeader.empty())
@@ -1686,7 +1675,7 @@ void* SSCache::cleanup_fn(void* p)
     Thread::mask_all_signals();
 #endif
 
-    auto_ptr<Mutex> mutex(Mutex::create());
+    scoped_ptr<Mutex> mutex(Mutex::create());
 
     // Load our configuration details...
     static const XMLCh cleanupInterval[] = UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l);
@@ -1721,7 +1710,7 @@ void* SSCache::cleanup_fn(void* p)
         pcache->m_log.debug("cleanup thread running");
 
         pcache->m_lock->rdlock();
-        for (map<string,StoredSession*>::const_iterator i=pcache->m_hashtable.begin(); i!=pcache->m_hashtable.end(); ++i) {
+        for (map<string,StoredSession*>::const_iterator i = pcache->m_hashtable.begin(); i != pcache->m_hashtable.end(); ++i) {
             // If the last access was BEFORE the stale timeout...
             i->second->lock();
             time_t last=i->second->getLastAccess();
@@ -1735,8 +1724,7 @@ void* SSCache::cleanup_fn(void* p)
             pcache->m_log.info("purging %d old sessions", stale_keys.size());
 
             // Pass 2: walk through the list of stale entries and remove them from the cache
-            for (vector<string>::const_iterator j = stale_keys.begin(); j != stale_keys.end(); ++j)
-                pcache->dormant(j->c_str());
+            for_each(stale_keys.begin(), stale_keys.end(), boost::bind(&SSCache::dormant, pcache, boost::bind(&string::c_str, _1)));
         }
 
         pcache->m_log.debug("cleanup thread completed");
@@ -1789,7 +1777,7 @@ void SSCache::receive(DDF& in, ostream& out)
 
             if (timeout > 0 && now - lastAccess >= timeout) {
                 m_log.info("session timed out (ID: %s)", key);
-                auto_ptr<LogoutEvent> logout_event(newLogoutEvent(*app));
+                scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(*app));
                 if (logout_event.get()) {
                     logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_INVALID;
                     logout_event->m_sessions.push_back(key);
@@ -1803,7 +1791,7 @@ void SSCache::receive(DDF& in, ostream& out)
             try {
                 m_storage->updateContext(key, now + cacheTimeout);
             }
-            catch (exception& ex) {
+            catch (std::exception& ex) {
                 m_log.error("failed to update session expiration: %s", ex.what());
             }
         }
@@ -1849,7 +1837,7 @@ void SSCache::receive(DDF& in, ostream& out)
         try {
             m_storage->updateContext(key, now + cacheTimeout);
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("failed to update session expiration: %s", ex.what());
         }
 
index fd6d1ed..23463c8 100644 (file)
 #include "attribute/Attribute.h"
 
 #include <algorithm>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lambda/bind.hpp>
+#include <boost/lambda/lambda.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
 #include <xmltooling/unicode.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/Threads.h>
@@ -45,6 +50,8 @@
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost::lambda;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -62,16 +69,14 @@ namespace shibsp {
 
     private:
         string m_alias;
-        vector <string> m_vals;
+        set <string> m_vals;
     };
 
     class RuleRegex : public AccessControl
     {
     public:
         RuleRegex(const DOMElement* e);
-        ~RuleRegex() {
-            delete m_re;
-        }
+        ~RuleRegex() {}
 
         Lockable* lock() {return this;}
         void unlock() {}
@@ -81,14 +86,14 @@ namespace shibsp {
     private:
         string m_alias;
         auto_arrayptr<char> m_exp;
-        RegularExpression* m_re;
+        scoped_ptr<RegularExpression> m_re;
     };
 
     class Operator : public AccessControl
     {
     public:
         Operator(const DOMElement* e);
-        ~Operator();
+        ~Operator() {}
 
         Lockable* lock() {return this;}
         void unlock() {}
@@ -97,7 +102,7 @@ namespace shibsp {
 
     private:
         enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
-        vector<AccessControl*> m_operands;
+        ptr_vector<AccessControl> m_operands;
     };
 
 #if defined (_MSC_VER)
@@ -109,13 +114,12 @@ namespace shibsp {
     {
     public:
         XMLAccessControl(const DOMElement* e)
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(nullptr) {
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")) {
             background_load(); // guarantees an exception or the policy is loaded
         }
 
         ~XMLAccessControl() {
             shutdown();
-            delete m_rootAuthz;
         }
 
         aclresult_t authorized(const SPRequest& request, const Session* session) const;
@@ -124,7 +128,7 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        AccessControl* m_rootAuthz;
+        scoped_ptr<AccessControl> m_rootAuthz;
     };
 
 #if defined (_MSC_VER)
@@ -160,24 +164,12 @@ Rule::Rule(const DOMElement* e) : m_alias(XMLHelper::getAttrString(e, nullptr, r
     bool listflag = XMLHelper::getAttrBool(e, true, _list);
     if (!listflag) {
         if (*vals.get())
-            m_vals.push_back(vals.get());
+            m_vals.insert(vals.get());
         return;
     }
 
-#ifdef HAVE_STRTOK_R
-    char* pos=nullptr;
-    const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
-#else
-    const char* token=strtok(const_cast<char*>(vals.get())," ");
-#endif
-    while (token) {
-        m_vals.push_back(token);
-#ifdef HAVE_STRTOK_R
-        token=strtok_r(nullptr," ",&pos);
-#else
-        token=strtok(nullptr," ");
-#endif
-    }
+    string temp(vals.get());
+    split(m_vals, temp, boost::is_space(), algorithm::token_compress_on);
 }
 
 AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
@@ -199,31 +191,25 @@ AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Sess
         return shib_acl_false;
     }
     if (m_alias == "user") {
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
-            if (*i == request.getRemoteUser()) {
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");
-                return shib_acl_true;
-            }
+        if (m_vals.find(request.getRemoteUser()) != m_vals.end()) {
+            request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + request.getRemoteUser() + "), authz granted");
+            return shib_acl_true;
         }
         return shib_acl_false;
     }
     else if (m_alias == "authnContextClassRef") {
         const char* ref = session->getAuthnContextClassRef();
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
-            if (!strcmp(i->c_str(),ref)) {
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");
-                return shib_acl_true;
-            }
+        if (ref && m_vals.find(ref) != m_vals.end()) {
+            request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + ref + "), authz granted");
+            return shib_acl_true;
         }
         return shib_acl_false;
     }
     else if (m_alias == "authnContextDeclRef") {
         const char* ref = session->getAuthnContextDeclRef();
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
-            if (!strcmp(i->c_str(),ref)) {
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");
-                return shib_acl_true;
-            }
+        if (ref && m_vals.find(ref) != m_vals.end()) {
+            request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + ref + "), authz granted");
+            return shib_acl_true;
         }
         return shib_acl_false;
     }
@@ -241,8 +227,8 @@ AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Sess
 
         // Now we have to intersect the attribute's values against the rule's list.
         const vector<string>& vals = attrs.first->second->getSerializedValues();
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+        for (set<string>::const_iterator i = m_vals.begin(); i != m_vals.end(); ++i) {
+            for (vector<string>::const_iterator j = vals.begin(); j != vals.end(); ++j) {
                 if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {
                     request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");
                     return shib_acl_true;
@@ -263,7 +249,7 @@ RuleRegex::RuleRegex(const DOMElement* e)
 
     bool ignore = XMLHelper::getAttrBool(e, false, ignoreCase);
     try {
-        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+        m_re.reset(new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull)));
     }
     catch (XMLException& ex) {
         auto_ptr_char tmp(ex.getMessage());
@@ -321,7 +307,7 @@ AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const
         for (; attrs.first != attrs.second; ++attrs.first) {
             // Now we have to intersect the attribute's values against the regular expression.
             const vector<string>& vals = attrs.first->second->getSerializedValues();
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+            for (vector<string>::const_iterator j = vals.begin(); j != vals.end(); ++j) {
                 if (m_re->matches(j->c_str())) {
                     request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");
                     return shib_acl_true;
@@ -348,45 +334,34 @@ Operator::Operator(const DOMElement* e)
     else
         throw ConfigurationException("Unrecognized operator in access control rule");
 
-    try {
-        e=XMLHelper::getFirstChildElement(e);
+    e=XMLHelper::getFirstChildElement(e);
+    if (XMLString::equals(e->getLocalName(),_Rule))
+        m_operands.push_back(new Rule(e));
+    else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+        m_operands.push_back(new RuleRegex(e));
+    else
+        m_operands.push_back(new Operator(e));
+
+    if (m_op==OP_NOT)
+        return;
+
+    e=XMLHelper::getNextSiblingElement(e);
+    while (e) {
         if (XMLString::equals(e->getLocalName(),_Rule))
             m_operands.push_back(new Rule(e));
         else if (XMLString::equals(e->getLocalName(),_RuleRegex))
             m_operands.push_back(new RuleRegex(e));
         else
             m_operands.push_back(new Operator(e));
-
-        if (m_op==OP_NOT)
-            return;
-
         e=XMLHelper::getNextSiblingElement(e);
-        while (e) {
-            if (XMLString::equals(e->getLocalName(),_Rule))
-                m_operands.push_back(new Rule(e));
-            else if (XMLString::equals(e->getLocalName(),_RuleRegex))
-                m_operands.push_back(new RuleRegex(e));
-            else
-                m_operands.push_back(new Operator(e));
-            e=XMLHelper::getNextSiblingElement(e);
-        }
-    }
-    catch (exception&) {
-        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
-        throw;
     }
 }
 
-Operator::~Operator()
-{
-    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
-}
-
 AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const
 {
     switch (m_op) {
         case OP_NOT:
-            switch (m_operands.front()->authorized(request,session)) {
+            switch (m_operands.front().authorized(request,session)) {
                 case shib_acl_true:
                     return shib_acl_false;
                 case shib_acl_false:
@@ -397,20 +372,22 @@ AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const
 
         case OP_AND:
         {
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
-                if ((*i)->authorized(request,session) != shib_acl_true)
-                    return shib_acl_false;
-            }
-            return shib_acl_true;
+            // Look for a rule that returns non-true.
+            ptr_vector<AccessControl>::const_iterator i = find_if(
+                m_operands.begin(), m_operands.end(),
+                lambda::bind(&AccessControl::authorized, _1, boost::ref(request), session) != shib_acl_true
+                );
+            return (i != m_operands.end()) ? shib_acl_false : shib_acl_true;
         }
 
         case OP_OR:
         {
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
-                if ((*i)->authorized(request,session) == shib_acl_true)
-                    return shib_acl_true;
-            }
-            return shib_acl_false;
+            // Look for a rule that returns true.
+            ptr_vector<AccessControl>::const_iterator i = find_if(
+                m_operands.begin(), m_operands.end(),
+                lambda::bind(&AccessControl::authorized, _1, boost::ref(request), session) == shib_acl_true
+                );
+            return (i != m_operands.end()) ? shib_acl_true : shib_acl_false;
         }
     }
     request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");
@@ -429,20 +406,19 @@ pair<bool,DOMElement*> XMLAccessControl::background_load()
     if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
         raw.second = XMLHelper::getFirstChildElement(raw.second);
 
-    AccessControl* authz;
+    scoped_ptr<AccessControl> authz;
     if (XMLString::equals(raw.second->getLocalName(),_Rule))
-        authz=new Rule(raw.second);
+        authz.reset(new Rule(raw.second));
     else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))
-        authz=new RuleRegex(raw.second);
+        authz.reset(new RuleRegex(raw.second));
     else
-        authz=new Operator(raw.second);
+        authz.reset(new Operator(raw.second));
 
     // Perform the swap inside a lock.
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_rootAuthz;
-    m_rootAuthz = authz;
+    m_rootAuthz.swap(authz);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
index f0cebd4..48e7969 100644 (file)
 #include "util/SPConstants.h"
 
 #include <algorithm>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/tuple/tuple.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/Threads.h>
@@ -43,6 +49,7 @@
 using shibspconstants::SHIB2SPCONFIG_NS;
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -65,9 +72,9 @@ namespace shibsp {
     class Override : public DOMPropertySet, public DOMNodeFilter
     {
     public:
-        Override(bool unicodeAware=false) : m_unicodeAware(unicodeAware), m_acl(nullptr) {}
+        Override(bool unicodeAware=false) : m_unicodeAware(unicodeAware) {}
         Override(bool unicodeAware, const DOMElement* e, Category& log, const Override* base=nullptr);
-        ~Override();
+        ~Override() {}
 
         // Provides filter to exclude special config elements.
 #ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
@@ -80,18 +87,18 @@ namespace shibsp {
         }
 
         const Override* locate(const HTTPRequest& request) const;
-        AccessControl* getAC() const { return (m_acl ? m_acl : (getParent() ? dynamic_cast<const Override*>(getParent())->getAC() : nullptr)); }
+        AccessControl* getAC() const { return (m_acl ? m_acl.get() : (getParent() ? dynamic_cast<const Override*>(getParent())->getAC() : nullptr)); }
 
     protected:
         void loadACL(const DOMElement* e, Category& log);
 
         bool m_unicodeAware;
-        map<string,Override*> m_map;
-        vector< pair<RegularExpression*,Override*> > m_regexps;
-        vector< pair< pair<string,RegularExpression*>,Override*> > m_queries;
+        map< string,boost::shared_ptr<Override> > m_map;
+        vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > > m_regexps;
+        vector< tuple< string,boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > > m_queries;
 
     private:
-        AccessControl* m_acl;
+        scoped_ptr<AccessControl> m_acl;
     };
 
     class XMLRequestMapperImpl : public Override
@@ -111,7 +118,6 @@ namespace shibsp {
         const Override* findOverride(const char* vhost, const HTTPRequest& request) const;
 
     private:
-        map<string,Override*> m_extras;
         DOMDocument* m_document;
     };
 
@@ -123,13 +129,12 @@ namespace shibsp {
     class XMLRequestMapper : public RequestMapper, public ReloadableXMLFile
     {
     public:
-        XMLRequestMapper(const DOMElement* e) : ReloadableXMLFile(e,Category::getInstance(SHIBSP_LOGCAT".RequestMapper")), m_impl(nullptr) {
+        XMLRequestMapper(const DOMElement* e) : ReloadableXMLFile(e,Category::getInstance(SHIBSP_LOGCAT".RequestMapper")) {
             background_load();
         }
 
         ~XMLRequestMapper() {
             shutdown();
-            delete m_impl;
         }
 
         Settings getSettings(const HTTPRequest& request) const;
@@ -138,7 +143,7 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        XMLRequestMapperImpl* m_impl;
+        scoped_ptr<XMLRequestMapperImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -183,24 +188,24 @@ RequestMapper::~RequestMapper()
 void Override::loadACL(const DOMElement* e, Category& log)
 {
     try {
-        const DOMElement* acl=XMLHelper::getFirstChildElement(e,htaccess);
+        const DOMElement* acl = XMLHelper::getFirstChildElement(e,htaccess);
         if (acl) {
             log.info("building Apache htaccess AccessControl provider...");
-            m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(HT_ACCESS_CONTROL,acl);
+            m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(HT_ACCESS_CONTROL,acl));
         }
         else {
-            acl=XMLHelper::getFirstChildElement(e,_AccessControl);
+            acl = XMLHelper::getFirstChildElement(e,_AccessControl);
             if (acl) {
                 log.info("building XML-based AccessControl provider...");
-                m_acl=SPConfig::getConfig().AccessControlManager.newPlugin(XML_ACCESS_CONTROL,acl);
+                m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(XML_ACCESS_CONTROL,acl));
             }
             else {
-                acl=XMLHelper::getFirstChildElement(e,AccessControlProvider);
+                acl = XMLHelper::getFirstChildElement(e,AccessControlProvider);
                 if (acl) {
                     string t(XMLHelper::getAttrString(acl, nullptr, _type));
                     if (!t.empty()) {
                         log.info("building AccessControl provider of type %s...", t.c_str());
-                        m_acl = SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acl);
+                        m_acl.reset(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acl));
                     }
                     else {
                         throw ConfigurationException("<AccessControlProvider> missing type attribute.");
@@ -209,76 +214,74 @@ void Override::loadACL(const DOMElement* e, Category& log)
             }
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         log.crit("exception building AccessControl provider: %s", ex.what());
-        m_acl = new AccessControlDummy();
+        m_acl.reset(new AccessControlDummy());
     }
 }
 
 Override::Override(bool unicodeAware, const DOMElement* e, Category& log, const Override* base)
-    : m_unicodeAware(unicodeAware), m_acl(nullptr)
+    : m_unicodeAware(unicodeAware)
 {
-    try {
-        // Load the property set.
-        load(e,nullptr,this);
-        setParent(base);
+    // Load the property set.
+    load(e, nullptr, this);
+    setParent(base);
 
-        // Load any AccessControl provider.
-        loadACL(e,log);
+    // Load any AccessControl provider.
+    loadACL(e, log);
 
-        // Handle nested Paths.
-        DOMElement* path = XMLHelper::getFirstChildElement(e,Path);
-        for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Path)) {
-            const XMLCh* n=path->getAttributeNS(nullptr,name);
+    // Handle nested Paths.
+    DOMElement* path = XMLHelper::getFirstChildElement(e, Path);
+    for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, Path)) {
+        const XMLCh* n = path->getAttributeNS(nullptr,name);
 
-            // Skip any leading slashes.
-            while (n && *n==chForwardSlash)
-                n++;
+        // Skip any leading slashes.
+        while (n && *n == chForwardSlash)
+            n++;
 
-            // Check for empty name.
-            if (!n || !*n) {
-                log.warn("skipping Path element (%d) with empty name attribute", i);
-                continue;
-            }
+        // Check for empty name.
+        if (!n || !*n) {
+            log.warn("skipping Path element (%d) with empty name attribute", i);
+            continue;
+        }
 
-            // Check for an embedded slash.
-            int slash=XMLString::indexOf(n,chForwardSlash);
-            if (slash>0) {
-                // Copy the first path segment.
-                XMLCh* namebuf=new XMLCh[slash + 1];
-                for (int pos=0; pos < slash; pos++)
-                    namebuf[pos]=n[pos];
-                namebuf[slash]=chNull;
-
-                // Move past the slash in the original pathname.
-                n=n+slash+1;
-
-                // Skip any leading slashes again.
-                while (*n==chForwardSlash)
-                    n++;
-
-                if (*n) {
-                    // Create a placeholder Path element for the first path segment and replant under it.
-                    DOMElement* newpath=path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,Path);
-                    newpath->setAttributeNS(nullptr,name,namebuf);
-                    path->setAttributeNS(nullptr,name,n);
-                    path->getParentNode()->replaceChild(newpath,path);
-                    newpath->appendChild(path);
-
-                    // Repoint our locals at the new parent.
-                    path=newpath;
-                    n=path->getAttributeNS(nullptr,name);
-                }
-                else {
-                    // All we had was a pathname with trailing slash(es), so just reset it without them.
-                    path->setAttributeNS(nullptr,name,namebuf);
-                    n=path->getAttributeNS(nullptr,name);
-                }
-                delete[] namebuf;
+        // Check for an embedded slash.
+        int slash = XMLString::indexOf(n, chForwardSlash);
+        if (slash > 0) {
+            // Copy the first path segment.
+            xstring namebuf;
+            for (int pos = 0; pos < slash; ++pos)
+                namebuf += n[pos];
+
+            // Move past the slash in the original pathname.
+            n = n + slash + 1;
+
+            // Skip any leading slashes again.
+            while (*n == chForwardSlash)
+                ++n;
+
+            if (*n) {
+                // Create a placeholder Path element for the first path segment and replant under it.
+                DOMElement* newpath = path->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, Path);
+                newpath->setAttributeNS(nullptr, name, namebuf.c_str());
+                path->setAttributeNS(nullptr, name, n);
+                path->getParentNode()->replaceChild(newpath, path);
+                newpath->appendChild(path);
+
+                // Repoint our locals at the new parent.
+                path = newpath;
+                n = path->getAttributeNS(nullptr, name);
+            }
+            else {
+                // All we had was a pathname with trailing slash(es), so just reset it without them.
+                path->setAttributeNS(nullptr, name, namebuf.c_str());
+                n = path->getAttributeNS(nullptr, name);
             }
+        }
 
-            char* dup = nullptr;
-            Override* o = new Override(m_unicodeAware, path, log, this);
+        char* dup = nullptr;
+        try {
+            boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
             if (m_unicodeAware) {
                 dup = toUTF8(o->getXMLString("name").second, true /* use malloc */);
             }
@@ -288,99 +291,71 @@ Override::Override(bool unicodeAware, const DOMElement* e, Category& log, const
                     *pch = tolower(*pch);
             }
             if (m_map.count(dup)) {
-                log.warn("skipping duplicate Path element (%s)",dup);
-                free(dup);
-                delete o;
-                continue;
+                log.warn("skipping duplicate Path element (%s)", dup);
+            }
+            else {
+                m_map[dup] = o;
+                log.debug("added Path mapping (%s)", dup);
             }
-            m_map[dup] = o;
-            log.debug("added Path mapping (%s)", dup);
             free(dup);
         }
-
-        if (!XMLString::equals(e->getLocalName(), PathRegex)) {
-            // Handle nested PathRegexs.
-            path = XMLHelper::getFirstChildElement(e,PathRegex);
-            for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,PathRegex)) {
-                const XMLCh* n=path->getAttributeNS(nullptr,regex);
-                if (!n || !*n) {
-                    log.warn("skipping PathRegex element (%d) with empty regex attribute",i);
-                    continue;
-                }
-
-                auto_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
-
-                const XMLCh* flag=path->getAttributeNS(nullptr,ignoreCase);
-                try {
-                    auto_ptr<RegularExpression> re(
-                        new RegularExpression(n, (flag && (*flag==chLatin_f || *flag==chDigit_0)) ? &chNull : ignoreOption)
-                        );
-                    m_regexps.push_back(make_pair(re.release(), o.release()));
-                }
-                catch (XMLException& ex) {
-                    auto_ptr_char tmp(ex.getMessage());
-                    log.error("caught exception while parsing PathRegex regular expression (%d): %s", i, tmp.get());
-                    throw ConfigurationException("Invalid regular expression in PathRegex element.");
-                }
-
-                if (log.isDebugEnabled())
-                    log.debug("added <PathRegex> mapping (%s)", m_regexps.back().second->getString("regex").second);
-            }
+        catch (std::exception&) {
+            free(dup);
+            throw;
         }
+    }
 
-        // Handle nested Querys.
-        path = XMLHelper::getFirstChildElement(e,Query);
-        for (int i=1; path; ++i, path=XMLHelper::getNextSiblingElement(path,Query)) {
-            const XMLCh* n=path->getAttributeNS(nullptr,name);
+    if (!XMLString::equals(e->getLocalName(), PathRegex)) {
+        // Handle nested PathRegexs.
+        path = XMLHelper::getFirstChildElement(e, PathRegex);
+        for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, PathRegex)) {
+            const XMLCh* n = path->getAttributeNS(nullptr, regex);
             if (!n || !*n) {
-                log.warn("skipping Query element (%d) with empty name attribute",i);
+                log.warn("skipping PathRegex element (%d) with empty regex attribute",i);
                 continue;
             }
-            auto_ptr_char ntemp(n);
-            const XMLCh* v=path->getAttributeNS(nullptr,regex);
 
-            auto_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+            boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+
+            bool flag = XMLHelper::getAttrBool(path, true, ignoreCase);
             try {
-                RegularExpression* re = nullptr;
-                if (v && *v)
-                    re = new RegularExpression(v);
-                m_queries.push_back(make_pair(make_pair(string(ntemp.get()),re), o.release()));
+                boost::shared_ptr<RegularExpression> re(new RegularExpression(n, flag ? &chNull : ignoreOption));
+                m_regexps.push_back(make_pair(re, o));
             }
             catch (XMLException& ex) {
                 auto_ptr_char tmp(ex.getMessage());
-                log.error("caught exception while parsing Query regular expression (%d): %s", i, tmp.get());
-                throw ConfigurationException("Invalid regular expression in Query element.");
+                log.error("caught exception while parsing PathRegex regular expression (%d): %s", i, tmp.get());
+                throw ConfigurationException("Invalid regular expression in PathRegex element.");
             }
 
-            log.debug("added <Query> mapping (%s)", ntemp.get());
+            if (log.isDebugEnabled())
+                log.debug("added <PathRegex> mapping (%s)", o->getString("regex").second);
         }
     }
-    catch (exception&) {
-        delete m_acl;
-        for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
-        for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
-            delete i->first;
-            delete i->second;
+
+    // Handle nested Querys.
+    path = XMLHelper::getFirstChildElement(e, Query);
+    for (int i = 1; path; ++i, path = XMLHelper::getNextSiblingElement(path, Query)) {
+        const XMLCh* n = path->getAttributeNS(nullptr, name);
+        if (!n || !*n) {
+            log.warn("skipping Query element (%d) with empty name attribute",i);
+            continue;
         }
-        for (vector< pair< pair<string,RegularExpression*>,Override*> >::iterator j = m_queries.begin(); j != m_queries.end(); ++j) {
-            delete j->first.second;
-            delete j->second;
+        auto_ptr_char ntemp(n);
+        const XMLCh* v = path->getAttributeNS(nullptr, regex);
+
+        try {
+            boost::shared_ptr<Override> o(new Override(m_unicodeAware, path, log, this));
+            boost::shared_ptr<RegularExpression> re((v && *v) ? new RegularExpression(v) : nullptr);
+            m_queries.push_back(make_tuple(string(ntemp.get()), re, o));
+        }
+        catch (XMLException& ex) {
+            auto_ptr_char tmp(ex.getMessage());
+            log.error("caught exception while parsing Query regular expression (%d): %s", i, tmp.get());
+            throw ConfigurationException("Invalid regular expression in Query element.");
         }
-        throw;
-    }
-}
 
-Override::~Override()
-{
-    delete m_acl;
-    for_each(m_map.begin(),m_map.end(),xmltooling::cleanup_pair<string,Override>());
-    for (vector< pair<RegularExpression*,Override*> >::iterator i = m_regexps.begin(); i != m_regexps.end(); ++i) {
-        delete i->first;
-        delete i->second;
-    }
-    for (vector< pair< pair<string,RegularExpression*>,Override*> >::iterator j = m_queries.begin(); j != m_queries.end(); ++j) {
-        delete j->first.second;
-        delete j->second;
+        log.debug("added <Query> mapping (%s)", ntemp.get());
     }
 }
 
@@ -395,56 +370,43 @@ const Override* Override::locate(const HTTPRequest& request) const
         path++;
 
     // Now we copy the path, chop the query string, and possibly lower case it.
-    char* dup=strdup(path);
-    char* sep=strchr(dup,'?');
-    if (sep)
-        *sep=0;
+    string dup(path);
+    string::size_type sep = dup.find('?');
+    if (sep != string::npos)
+        dup = dup.substr(0, sep);
     if (!m_unicodeAware) {
-        for (char* pch=dup; *pch; pch++)
-            *pch=tolower(*pch);
+        to_lower(dup);
     }
 
     // Default is for the current object to provide settings.
-    const Override* o=this;
+    const Override* o = this;
 
     // Tokenize the path by segment and try and map each segment.
-#ifdef HAVE_STRTOK_R
-    char* pos=nullptr;
-    const char* token=strtok_r(dup,"/",&pos);
-#else
-    const char* token=strtok(dup,"/");
-#endif
-    while (token) {
-        map<string,Override*>::const_iterator i=o->m_map.find(token);
-        if (i==o->m_map.end())
+    tokenizer< char_separator<char> > tokens(dup, char_separator<char>("/"));
+    for (tokenizer< char_separator<char> >::iterator token = tokens.begin(); token != tokens.end(); ++token) {
+        map< string,boost::shared_ptr<Override> >::const_iterator i = o->m_map.find(*token);
+        if (i == o->m_map.end())
             break;  // Once there's no match, we've consumed as much of the path as possible here.
         // We found a match, so reset the settings pointer.
-        o=i->second;
+        o = i->second.get();
 
         // We descended a step down the path, so we need to advance the original
         // parameter for the regex step later.
-        path += strlen(token);
+        path += token->length();
         if (*path == '/')
             path++;
-
-        // Get the next segment, if any.
-#ifdef HAVE_STRTOK_R
-        token=strtok_r(nullptr,"/",&pos);
-#else
-        token=strtok(nullptr,"/");
-#endif
     }
 
-    free(dup);
-
     // If there's anything left, we try for a regex match on the rest of the path minus the query string.
     if (*path) {
         string path2(path);
-        path2 = path2.substr(0,path2.find('?'));
+        sep = path2.find('?');
+        if (sep != string::npos)
+            path2 = path2.substr(0, sep);
 
-        for (vector< pair<RegularExpression*,Override*> >::const_iterator re = o->m_regexps.begin(); re != o->m_regexps.end(); ++re) {
+        for (vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator re = o->m_regexps.begin(); re != o->m_regexps.end(); ++re) {
             if (re->first->matches(path2.c_str())) {
-                o = re->second;
+                o = re->second.get();
                 break;
             }
         }
@@ -457,14 +419,14 @@ const Override* Override::locate(const HTTPRequest& request) const
         CGIParser cgi(request, true);
         do {
             descended = false;
-            for (vector< pair< pair<string,RegularExpression*>,Override*> >::const_iterator q = o->m_queries.begin(); !descended && q != o->m_queries.end(); ++q) {
-                pair<CGIParser::walker,CGIParser::walker> vals = cgi.getParameters(q->first.first.c_str());
+            for (vector< tuple< string,boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator q = o->m_queries.begin(); !descended && q != o->m_queries.end(); ++q) {
+                pair<CGIParser::walker,CGIParser::walker> vals = cgi.getParameters(q->get<0>().c_str());
                 if (vals.first != vals.second) {
-                    if (q->first.second) {
+                    if (q->get<1>()) {
                         // We have to match one of the values.
                         while (vals.first != vals.second) {
-                            if (q->first.second->matches(vals.first->second)) {
-                                o = q->second;
+                            if (q->get<1>()->matches(vals.first->second)) {
+                                o = q->get<2>().get();
                                 descended = true;
                                 break;
                             }
@@ -473,7 +435,7 @@ const Override* Override::locate(const HTTPRequest& request) const
                     }
                     else {
                         // The simple presence of the parameter is sufficient to match.
-                        o = q->second;
+                        o = q->get<2>().get();
                         descended = true;
                     }
                 }
@@ -495,35 +457,35 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
         throw ConfigurationException("XML RequestMapper requires conf:RequestMap at root of configuration.");
 
     // Load the property set.
-    load(e,nullptr,this);
+    load(e, nullptr, this);
 
     // Inject "default" app ID if not explicit.
     if (!getString("applicationId").first)
         setProperty("applicationId", "default");
 
     // Load any AccessControl provider.
-    loadACL(e,log);
+    loadACL(e, log);
 
     pair<bool,bool> unicodeAware = getBool("unicodeAware");
     m_unicodeAware = (unicodeAware.first && unicodeAware.second);
 
     // Loop over the HostRegex elements.
-    const DOMElement* host = XMLHelper::getFirstChildElement(e,HostRegex);
-    for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,HostRegex)) {
-        const XMLCh* n=host->getAttributeNS(nullptr,regex);
+    const DOMElement* host = XMLHelper::getFirstChildElement(e, HostRegex);
+    for (int i = 1; host; ++i, host = XMLHelper::getNextSiblingElement(host, HostRegex)) {
+        const XMLCh* n = host->getAttributeNS(nullptr,regex);
         if (!n || !*n) {
-            log.warn("Skipping HostRegex element (%d) with empty regex attribute",i);
+            log.warn("Skipping HostRegex element (%d) with empty regex attribute", i);
             continue;
         }
 
-        auto_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
+        boost::shared_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
 
-        const XMLCh* flag=host->getAttributeNS(nullptr,ignoreCase);
+        const XMLCh* flag = host->getAttributeNS(nullptr,ignoreCase);
         try {
-            auto_ptr<RegularExpression> re(
+            boost::shared_ptr<RegularExpression> re(
                 new RegularExpression(n, (flag && (*flag==chLatin_f || *flag==chDigit_0)) ? &chNull : ignoreOption)
                 );
-            m_regexps.push_back(make_pair(re.release(), o.release()));
+            m_regexps.push_back(make_pair(re, o));
         }
         catch (XMLException& ex) {
             auto_ptr_char tmp(ex.getMessage());
@@ -534,23 +496,21 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
     }
 
     // Loop over the Host elements.
-    host = XMLHelper::getFirstChildElement(e,Host);
-    for (int i=1; host; ++i, host=XMLHelper::getNextSiblingElement(host,Host)) {
+    host = XMLHelper::getFirstChildElement(e, Host);
+    for (int i = 1; host; ++i, host = XMLHelper::getNextSiblingElement(host, Host)) {
         const XMLCh* n=host->getAttributeNS(nullptr,name);
         if (!n || !*n) {
-            log.warn("Skipping Host element (%d) with empty name attribute",i);
+            log.warn("Skipping Host element (%d) with empty name attribute", i);
             continue;
         }
 
-        Override* o=new Override(m_unicodeAware, host, log, this);
+        boost::shared_ptr<Override> o(new Override(m_unicodeAware, host, log, this));
         pair<bool,const char*> name=o->getString("name");
         pair<bool,const char*> scheme=o->getString("scheme");
         pair<bool,const char*> port=o->getString("port");
 
-        char* dup=strdup(name.second);
-        for (char* pch=dup; *pch; pch++)
-            *pch=tolower(*pch);
-        auto_ptr<char> dupwrap(dup);
+        string dup(name.first ? name.second : "");
+        to_lower(dup);
 
         if (!scheme.first && port.first) {
             // No scheme, but a port, so assume http.
@@ -583,65 +543,61 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
                 (!strcmp(scheme.second,"ldap") && !strcmp(port.second,"389")) ||
                 (!strcmp(scheme.second,"ldaps") && !strcmp(port.second,"636"))) {
                 // First store a port-less version.
-                if (m_map.count(url) || m_extras.count(url)) {
+                if (m_map.count(url)) {
                     log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                    delete o;
                     continue;
                 }
-                m_map[url]=o;
+                m_map[url] = o;
                 log.debug("Added <Host> mapping for %s",url.c_str());
 
-                // Now append the port. We use the extras vector, to avoid double freeing the object later.
+                // Now append the port. The shared_ptr should refcount the Override to avoid double deletes.
                 url=url + ':' + port.second;
-                m_extras[url]=o;
+                m_map[url] = o;
                 log.debug("Added <Host> mapping for %s",url.c_str());
             }
             else {
                 url=url + ':' + port.second;
-                if (m_map.count(url) || m_extras.count(url)) {
+                if (m_map.count(url)) {
                     log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                    delete o;
                     continue;
                 }
-                m_map[url]=o;
+                m_map[url] = o;
                 log.debug("Added <Host> mapping for %s",url.c_str());
             }
         }
         else {
             // No scheme or port, so we enter dual hosts on http:80 and https:443
             string url("http://");
-            url = url + dup;
-            if (m_map.count(url) || m_extras.count(url)) {
+            url += dup;
+            if (m_map.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
-                delete o;
                 continue;
             }
-            m_map[url]=o;
+            m_map[url] = o;
             log.debug("Added <Host> mapping for %s",url.c_str());
 
-            url = url + ":80";
-            if (m_map.count(url) || m_extras.count(url)) {
+            url += ":80";
+            if (m_map.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
                 continue;
             }
-            m_extras[url]=o;
+            m_map[url] = o;
             log.debug("Added <Host> mapping for %s",url.c_str());
 
-            url = "https://";
-            url = url + dup;
-            if (m_map.count(url) || m_extras.count(url)) {
+            url = "https://" + dup;
+            if (m_map.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
                 continue;
             }
-            m_extras[url]=o;
+            m_map[url] = o;
             log.debug("Added <Host> mapping for %s",url.c_str());
 
-            url = url + ":443";
-            if (m_map.count(url) || m_extras.count(url)) {
+            url += ":443";
+            if (m_map.count(url)) {
                 log.warn("Skipping duplicate Host element (%s)",url.c_str());
                 continue;
             }
-            m_extras[url]=o;
+            m_map[url] = o;
             log.debug("Added <Host> mapping for %s",url.c_str());
         }
     }
@@ -649,19 +605,14 @@ XMLRequestMapperImpl::XMLRequestMapperImpl(const DOMElement* e, Category& log) :
 
 const Override* XMLRequestMapperImpl::findOverride(const char* vhost, const HTTPRequest& request) const
 {
-    const Override* o=nullptr;
-    map<string,Override*>::const_iterator i=m_map.find(vhost);
-    if (i!=m_map.end())
-        o=i->second;
+    const Override* o = nullptr;
+    map< string,boost::shared_ptr<Override> >::const_iterator i = m_map.find(vhost);
+    if (i != m_map.end())
+        o = i->second.get();
     else {
-        i=m_extras.find(vhost);
-        if (i!=m_extras.end())
-            o=i->second;
-        else {
-            for (vector< pair<RegularExpression*,Override*> >::const_iterator re = m_regexps.begin(); !o && re != m_regexps.end(); ++re) {
-                if (re->first->matches(vhost))
-                    o=re->second;
-            }
+        for (vector< pair< boost::shared_ptr<RegularExpression>,boost::shared_ptr<Override> > >::const_iterator re = m_regexps.begin(); !o && re != m_regexps.end(); ++re) {
+            if (re->first->matches(vhost))
+                o=re->second.get();
         }
     }
 
@@ -676,7 +627,7 @@ pair<bool,DOMElement*> XMLRequestMapper::background_load()
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLRequestMapperImpl* impl = new XMLRequestMapperImpl(raw.second, m_log);
+    scoped_ptr<XMLRequestMapperImpl> impl(new XMLRequestMapperImpl(raw.second, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -685,8 +636,7 @@ pair<bool,DOMElement*> XMLRequestMapper::background_load()
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
+    m_impl.swap(impl);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
@@ -694,10 +644,9 @@ pair<bool,DOMElement*> XMLRequestMapper::background_load()
 RequestMapper::Settings XMLRequestMapper::getSettings(const HTTPRequest& request) const
 {
     try {
-        ostringstream vhost;
-        vhost << request.getScheme() << "://" << request.getHostname() << ':' << request.getPort();
-        const Override* o=m_impl->findOverride(vhost.str().c_str(), request);
-        return Settings(o,o->getAC());
+        string vhost = string(request.getScheme()) + "://" + request.getHostname() + ':' + lexical_cast<string>(request.getPort());
+        const Override* o=m_impl->findOverride(vhost.c_str(), request);
+        return Settings(o, o->getAC());
     }
     catch (XMLException& ex) {
         auto_ptr_char tmp(ex.getMessage());
index ac31af0..e253ce9 100644 (file)
@@ -33,6 +33,8 @@
 #include "util/SPConstants.h"
 
 #include <map>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
 #include <saml/SAMLConfig.h>
 #include <saml/binding/SecurityPolicyRule.h>
 #include <xmltooling/io/HTTPResponse.h>
@@ -48,6 +50,7 @@ using opensaml::SAMLConfig;
 using opensaml::SecurityPolicyRule;
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -62,10 +65,6 @@ namespace shibsp {
     public:
         XMLSecurityPolicyProviderImpl(const DOMElement* e, Category& log);
         ~XMLSecurityPolicyProviderImpl() {
-            for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i = m_policyMap.begin(); i != m_policyMap.end(); ++i) {
-                delete i->second.first;
-                for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());
-            }
             if (m_document)
                 m_document->release();
         }
@@ -77,8 +76,10 @@ namespace shibsp {
     private:
         DOMDocument* m_document;
         vector<xstring> m_whitelist,m_blacklist;
-        map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
-        map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator m_defaultPolicy;
+        vector< boost::shared_ptr<SecurityPolicyRule> > m_ruleJanitor;   // need this to maintain vector type in API
+        typedef map< string,pair< boost::shared_ptr<PropertySet>,vector<const SecurityPolicyRule*> > > policymap_t;
+        policymap_t m_policyMap;
+        policymap_t::const_iterator m_defaultPolicy;
 
         friend class SHIBSP_DLLLOCAL XMLSecurityPolicyProvider;
     };
@@ -87,28 +88,27 @@ namespace shibsp {
     {
     public:
         XMLSecurityPolicyProvider(const DOMElement* e)
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".SecurityPolicyProvider.XML")), m_impl(nullptr) {
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".SecurityPolicyProvider.XML")) {
             background_load(); // guarantees an exception or the policy is loaded
         }
 
         ~XMLSecurityPolicyProvider() {
             shutdown();
-            delete m_impl;
         }
 
         const PropertySet* getPolicySettings(const char* id=nullptr) const {
             if (!id || !*id)
-                return m_impl->m_defaultPolicy->second.first;
-            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+                return m_impl->m_defaultPolicy->second.first.get();
+            XMLSecurityPolicyProviderImpl::policymap_t::const_iterator i = m_impl->m_policyMap.find(id);
             if (i != m_impl->m_policyMap.end())
-                return i->second.first;
+                return i->second.first.get();
             throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
         }
 
         const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id=nullptr) const {
             if (!id || !*id)
                 return m_impl->m_defaultPolicy->second.second;
-            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
+            XMLSecurityPolicyProviderImpl::policymap_t::const_iterator i = m_impl->m_policyMap.find(id);
             if (i != m_impl->m_policyMap.end())
                 return i->second.second;
             throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
@@ -125,7 +125,7 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        XMLSecurityPolicyProviderImpl* m_impl;
+        scoped_ptr<XMLSecurityPolicyProviderImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -218,11 +218,10 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
     e = XMLHelper::getFirstChildElement(e, Policy);
     while (e) {
         string id(XMLHelper::getAttrString(e, nullptr, _id));
-        pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id];
-        rules.first = nullptr;
-        auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
+        policymap_t::referent_type& rules = m_policyMap[id];
+        boost::shared_ptr<DOMPropertySet> settings(new DOMPropertySet());
         settings->load(e, nullptr, &filter);
-        rules.first = settings.release();
+        rules.first = settings;
 
         // Set default policy if not set, or id is "default".
         if (m_defaultPolicy == m_policyMap.end() || id == "default")
@@ -234,9 +233,11 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
             string t(XMLHelper::getAttrString(rule, nullptr, _type));
             if (!t.empty()) {
                 try {
-                    rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+                    boost::shared_ptr<SecurityPolicyRule> ptr(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+                    m_ruleJanitor.push_back(ptr);
+                    rules.second.push_back(ptr.get());
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());
                 }
             }
@@ -245,15 +246,17 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
 
         if (rules.second.size() == 0) {
             // Process Rule elements.
-            log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");
+            log.warn("detected deprecated Policy configuration, consider converting to new PolicyRule syntax");
             rule = XMLHelper::getFirstChildElement(e, Rule);
             while (rule) {
                 string t(XMLHelper::getAttrString(rule, nullptr, _type));
                 if (!t.empty()) {
                     try {
-                        rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+                        boost::shared_ptr<SecurityPolicyRule> ptr(samlConf.SecurityPolicyRuleManager.newPlugin(t.c_str(), rule));
+                        m_ruleJanitor.push_back(ptr);
+                        rules.second.push_back(ptr.get());
                     }
-                    catch (exception& ex) {
+                    catch (std::exception& ex) {
                         log.crit("error instantiating policy rule (%s) in policy (%s): %s", t.c_str(), id.c_str(), ex.what());
                     }
                 }
@@ -262,7 +265,9 @@ XMLSecurityPolicyProviderImpl::XMLSecurityPolicyProviderImpl(const DOMElement* e
 
             // Manually add a basic Conditions rule.
             log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.c_str());
-            rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));
+            boost::shared_ptr<SecurityPolicyRule> cptr(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, nullptr));
+            m_ruleJanitor.push_back(cptr);
+            rules.second.push_back(cptr.get());
         }
 
         e = XMLHelper::getNextSiblingElement(e, Policy);
@@ -280,7 +285,7 @@ pair<bool,DOMElement*> XMLSecurityPolicyProvider::load(bool backup)
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLSecurityPolicyProviderImpl* impl = new XMLSecurityPolicyProviderImpl(raw.second, m_log);
+    scoped_ptr<XMLSecurityPolicyProviderImpl> impl(new XMLSecurityPolicyProviderImpl(raw.second, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -289,9 +294,7 @@ pair<bool,DOMElement*> XMLSecurityPolicyProvider::load(bool backup)
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
-
+    m_impl.swap(impl);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
@@ -308,7 +311,7 @@ pair<bool,DOMElement*> XMLSecurityPolicyProvider::background_load()
             return load(true);
         throw;
     }
-    catch (exception&) {
+    catch (std::exception&) {
         if (!m_loaded && !m_backing.empty())
             return load(true);
         throw;
index e65dc87..9a6a033 100644 (file)
 # error "Supported logging library not available."
 #endif
 #include <algorithm>
+#include <boost/bind.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/tuple/tuple.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xercesc/util/XMLStringTokenizer.hpp>
 #include <xmltooling/XMLToolingConfig.h>
@@ -91,6 +96,7 @@ using namespace opensaml;
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 #ifndef min
@@ -111,7 +117,7 @@ namespace {
     {
     public:
         XMLApplication(const ServiceProvider*, const ProtocolProvider*, DOMElement*, const XMLApplication* base=nullptr);
-        ~XMLApplication() { cleanup(); }
+        ~XMLApplication();
 
         const char* getHash() const {return m_hash.c_str();}
 
@@ -135,24 +141,24 @@ namespace {
         MetadataProvider* getMetadataProvider(bool required=true) const {
             if (required && !m_base && !m_metadata)
                 throw ConfigurationException("No MetadataProvider available.");
-            return (!m_metadata && m_base) ? m_base->getMetadataProvider(required) : m_metadata;
+            return (!m_metadata && m_base) ? m_base->getMetadataProvider(required) : m_metadata.get();
         }
         TrustEngine* getTrustEngine(bool required=true) const {
             if (required && !m_base && !m_trust)
                 throw ConfigurationException("No TrustEngine available.");
-            return (!m_trust && m_base) ? m_base->getTrustEngine(required) : m_trust;
+            return (!m_trust && m_base) ? m_base->getTrustEngine(required) : m_trust.get();
         }
         AttributeExtractor* getAttributeExtractor() const {
-            return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;
+            return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor.get();
         }
         AttributeFilter* getAttributeFilter() const {
-            return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;
+            return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter.get();
         }
         AttributeResolver* getAttributeResolver() const {
-            return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;
+            return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver.get();
         }
         CredentialResolver* getCredentialResolver() const {
-            return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;
+            return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver.get();
         }
         const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;
         const PropertySet* getRelyingParty(const XMLCh* entityID) const;
@@ -215,27 +221,26 @@ namespace {
         void doLogout(const ProtocolProvider&, set<string>&, DOMElement*, Category&);
         void doNameIDMgmt(const ProtocolProvider&, set<string>&, DOMElement*, Category&);
         void doArtifactResolution(const ProtocolProvider&, const char*, DOMElement*, Category&);
-        void cleanup();
         const XMLApplication* m_base;
         string m_hash;
         std::pair<std::string,std::string> m_attributePrefix;
 #ifndef SHIBSP_LITE
-        void doAttributePlugins(DOMElement* e, Category& log);
-        MetadataProvider* m_metadata;
-        TrustEngine* m_trust;
-        AttributeExtractor* m_attrExtractor;
-        AttributeFilter* m_attrFilter;
-        AttributeResolver* m_attrResolver;
-        CredentialResolver* m_credResolver;
+        void doAttributePlugins(DOMElement*, Category&);
+        scoped_ptr<MetadataProvider> m_metadata;
+        scoped_ptr<TrustEngine> m_trust;
+        scoped_ptr<AttributeExtractor> m_attrExtractor;
+        scoped_ptr<AttributeFilter> m_attrFilter;
+        scoped_ptr<AttributeResolver> m_attrResolver;
+        scoped_ptr<CredentialResolver> m_credResolver;
         vector<const XMLCh*> m_audiences;
 
         // RelyingParty properties
-        map<xstring,PropertySet*> m_partyMap;
+        map< xstring,boost::shared_ptr<PropertySet> > m_partyMap;
 #endif
         vector<string> m_remoteUsers,m_frontLogout,m_backLogout;
 
         // manage handler objects
-        vector<Handler*> m_handlers;
+        vector< boost::shared_ptr<Handler> > m_handlers;
 
         // maps location (path info) to applicable handlers
         map<string,const Handler*> m_handlerMap;
@@ -275,15 +280,18 @@ namespace {
     {
     public:
         XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log);
-        ~XMLConfigImpl();
+        ~XMLConfigImpl() {
+            if (m_document)
+                m_document->release();
+        }
 
-        RequestMapper* m_requestMapper;
-        map<string,Application*> m_appmap;
 #ifndef SHIBSP_LITE
-        TransactionLog* m_tranLog;
-        SecurityPolicyProvider* m_policy;
-        vector< pair< string, pair<string,string> > > m_transportOptions;
+        scoped_ptr<TransactionLog> m_tranLog;
+        scoped_ptr<SecurityPolicyProvider> m_policy;
+        vector< tuple<string,string,string> > m_transportOptions;
 #endif
+        scoped_ptr<RequestMapper> m_requestMapper;
+        map< string,boost::shared_ptr<Application> > m_appmap;
 
         // Provides filter to exclude special config elements.
 #ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
@@ -301,7 +309,6 @@ namespace {
         void doExtensions(const DOMElement*, const char*, Category&);
         void doListener(const DOMElement*, XMLConfig*, Category&);
         void doCaching(const DOMElement*, XMLConfig*, Category&);
-        void cleanup();
 
         DOMDocument* m_document;
     };
@@ -312,9 +319,7 @@ namespace {
 #endif
     {
     public:
-        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),
-            m_impl(nullptr), m_listener(nullptr), m_sessionCache(nullptr) {
-        }
+        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")) {}
 
         void init() {
             background_load();
@@ -322,13 +327,9 @@ namespace {
 
         ~XMLConfig() {
             shutdown();
-            delete m_impl;
-            delete m_sessionCache;
-            delete m_listener;
 #ifndef SHIBSP_LITE
             SAMLConfig::getConfig().setArtifactMap(nullptr);
             XMLToolingConfig::getConfig().setReplayCache(nullptr);
-            for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());
 #endif
         }
 
@@ -366,18 +367,18 @@ namespace {
 
         TransactionLog* getTransactionLog() const {
             if (m_impl->m_tranLog)
-                return m_impl->m_tranLog;
+                return m_impl->m_tranLog.get();
             throw ConfigurationException("No TransactionLog available.");
         }
 
         StorageService* getStorageService(const char* id) const {
             if (id) {
-                map<string,StorageService*>::const_iterator i=m_storage.find(id);
-                if (i!=m_storage.end())
-                    return i->second;
+                map< string,boost::shared_ptr<StorageService> >::const_iterator i = m_storage.find(id);
+                if (i != m_storage.end())
+                    return i->second.get();
             }
             else if (!m_storage.empty())
-                return m_storage.begin()->second;
+                return m_storage.begin()->second.get();
             return nullptr;
         }
 #endif
@@ -385,31 +386,31 @@ namespace {
         ListenerService* getListenerService(bool required=true) const {
             if (required && !m_listener)
                 throw ConfigurationException("No ListenerService available.");
-            return m_listener;
+            return m_listener.get();
         }
 
         SessionCache* getSessionCache(bool required=true) const {
             if (required && !m_sessionCache)
                 throw ConfigurationException("No SessionCache available.");
-            return m_sessionCache;
+            return m_sessionCache.get();
         }
 
         RequestMapper* getRequestMapper(bool required=true) const {
             if (required && !m_impl->m_requestMapper)
                 throw ConfigurationException("No RequestMapper available.");
-            return m_impl->m_requestMapper;
+            return m_impl->m_requestMapper.get();
         }
 
         const Application* getApplication(const char* applicationId) const {
-            map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId ? applicationId : "default");
-            return (i!=m_impl->m_appmap.end()) ? i->second : nullptr;
+            map< string,boost::shared_ptr<Application> >::const_iterator i = m_impl->m_appmap.find(applicationId ? applicationId : "default");
+            return (i != m_impl->m_appmap.end()) ? i->second.get() : nullptr;
         }
 
 #ifndef SHIBSP_LITE
         SecurityPolicyProvider* getSecurityPolicyProvider(bool required=true) const {
             if (required && !m_impl->m_policy)
                 throw ConfigurationException("No SecurityPolicyProvider available.");
-            return m_impl->m_policy;
+            return m_impl->m_policy.get();
         }
 
         const PropertySet* getPolicySettings(const char* id) const {
@@ -422,10 +423,10 @@ namespace {
 
         bool setTransportOptions(SOAPTransport& transport) const {
             bool ret = true;
-            vector< pair< string, pair<string,string> > >::const_iterator opt;
-            for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {
-                if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {
-                    m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());
+            for (vector< tuple<string,string,string> >::const_iterator opt = m_impl->m_transportOptions.begin();
+                    opt != m_impl->m_transportOptions.end(); ++opt) {
+                if (!transport.setProviderOption(opt->get<0>().c_str(), opt->get<1>().c_str(), opt->get<2>().c_str())) {
+                    m_log.error("failed to set SOAPTransport option (%s)", opt->get<1>().c_str());
                     ret = false;
                 }
             }
@@ -438,12 +439,15 @@ namespace {
 
     private:
         friend class XMLConfigImpl;
-        XMLConfigImpl* m_impl;
-        ListenerService* m_listener;
-        SessionCache* m_sessionCache;
+        // The order of these members actually matters. If we want to rely on auto-destruction, then
+        // anything dependent on anything else has to come later in the object so it will pop first.
+        // Storage is the lowest, then remoting, then the cache, and finally the rest.
 #ifndef SHIBSP_LITE
-        map<string,StorageService*> m_storage;
+        map< string,boost::shared_ptr<StorageService> > m_storage;
 #endif
+        scoped_ptr<ListenerService> m_listener;
+        scoped_ptr<SessionCache> m_sessionCache;
+        scoped_ptr<XMLConfigImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -518,162 +522,151 @@ XMLApplication::XMLApplication(
     const ProtocolProvider* pp,
     DOMElement* e,
     const XMLApplication* base
-    ) : Application(sp), m_base(base),
-#ifndef SHIBSP_LITE
-        m_metadata(nullptr), m_trust(nullptr),
-        m_attrExtractor(nullptr), m_attrFilter(nullptr), m_attrResolver(nullptr),
-        m_credResolver(nullptr),
-#endif
-        m_acsDefault(nullptr), m_sessionInitDefault(nullptr), m_artifactResolutionDefault(nullptr)
+    ) : Application(sp), m_base(base), m_acsDefault(nullptr), m_sessionInitDefault(nullptr), m_artifactResolutionDefault(nullptr)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("XMLApplication");
 #endif
     Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");
 
-    try {
-        // First load any property sets.
-        load(e,nullptr,this);
-        if (base)
-            setParent(base);
+    // First load any property sets.
+    load(e, nullptr, this);
+    if (base)
+        setParent(base);
 
-        SPConfig& conf=SPConfig::getConfig();
+    SPConfig& conf=SPConfig::getConfig();
 #ifndef SHIBSP_LITE
-        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
+    XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
 #endif
 
-        // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec dependency.
-        static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-        string tohash=getId();
-        tohash+=getString("entityID").second;
-        for (const char* ch = tohash.c_str(); *ch; ++ch) {
-            m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);
-            m_hash += (DIGITS[0x0F & *ch]);
-        }
-
-        doAttributeInfo();
-
-        if (conf.isEnabled(SPConfig::Handlers))
-            doHandlers(pp, e, log);
-
-        // Notification.
-        DOMNodeList* nlist = e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS, Notify);
-        for (XMLSize_t i = 0; nlist && i < nlist->getLength(); ++i) {
-            if (nlist->item(i)->getParentNode()->isSameNode(e)) {
-                const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(nullptr, Channel);
-                string loc(XMLHelper::getAttrString(static_cast<DOMElement*>(nlist->item(i)), nullptr, Location));
-                if (!loc.empty()) {
-                    if (channel && *channel == chLatin_f)
-                        m_frontLogout.push_back(loc);
-                    else
-                        m_backLogout.push_back(loc);
-                }
+    // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec dependency.
+    static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+    string tohash=getId();
+    tohash+=getString("entityID").second;
+    for (const char* ch = tohash.c_str(); *ch; ++ch) {
+        m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);
+        m_hash += (DIGITS[0x0F & *ch]);
+    }
+
+    doAttributeInfo();
+
+    if (conf.isEnabled(SPConfig::Handlers))
+        doHandlers(pp, e, log);
+
+    // Notification.
+    DOMNodeList* nlist = e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS, Notify);
+    for (XMLSize_t i = 0; nlist && i < nlist->getLength(); ++i) {
+        if (nlist->item(i)->getParentNode()->isSameNode(e)) {
+            const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(nullptr, Channel);
+            string loc(XMLHelper::getAttrString(static_cast<DOMElement*>(nlist->item(i)), nullptr, Location));
+            if (!loc.empty()) {
+                if (channel && *channel == chLatin_f)
+                    m_frontLogout.push_back(loc);
+                else
+                    m_backLogout.push_back(loc);
             }
         }
+    }
 
 #ifndef SHIBSP_LITE
-        nlist = e->getElementsByTagNameNS(samlconstants::SAML20_NS, Audience::LOCAL_NAME);
-        if (nlist && nlist->getLength()) {
-            log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
-            for (XMLSize_t i = 0; i < nlist->getLength(); ++i)
-                if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
-                    m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
-        }
-
-        if (conf.isEnabled(SPConfig::Metadata)) {
-            auto_ptr<MetadataProvider> mp(
-                doChainedPlugins(
-                    SAMLConfig::getConfig().MetadataProviderManager, "MetadataProvider", CHAINING_METADATA_PROVIDER, _MetadataProvider, e, log
-                    )
-                );
-            try {
-                if (mp.get()) {
-                    mp->init();
-                    m_metadata = mp.release();
-                }
-                else if (!m_base) {
-                    log.crit("no MetadataProvider available, configuration is probably unusable");
-                }
-            }
-            catch (exception& ex) {
-                log.crit("error initializing MetadataProvider: %s", ex.what());
-            }
+    nlist = e->getElementsByTagNameNS(samlconstants::SAML20_NS, Audience::LOCAL_NAME);
+    if (nlist && nlist->getLength()) {
+        log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
+        for (XMLSize_t i = 0; i < nlist->getLength(); ++i)
+            if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
+                m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
+    }
+
+    if (conf.isEnabled(SPConfig::Metadata)) {
+        m_metadata.reset(
+            doChainedPlugins(
+                SAMLConfig::getConfig().MetadataProviderManager, "MetadataProvider", CHAINING_METADATA_PROVIDER, _MetadataProvider, e, log
+                )
+            );
+        try {
+            if (m_metadata)
+                m_metadata->init();
+            else if (!m_base)
+                log.crit("no MetadataProvider available, configuration is probably unusable");
+        }
+        catch (std::exception& ex) {
+            log.crit("error initializing MetadataProvider: %s", ex.what());
         }
+    }
 
-        if (conf.isEnabled(SPConfig::Trust)) {
-            m_trust = doChainedPlugins(xmlConf.TrustEngineManager, "TrustEngine", CHAINING_TRUSTENGINE, _TrustEngine, e, log);
-            if (!m_trust && !m_base) {
-                log.info(
-                    "no TrustEngine specified or installed, using default chain {%s, %s}",
-                    EXPLICIT_KEY_TRUSTENGINE, SHIBBOLETH_PKIX_TRUSTENGINE
-                    );
-                m_trust = xmlConf.TrustEngineManager.newPlugin(CHAINING_TRUSTENGINE, nullptr);
-                ChainingTrustEngine* trustchain = dynamic_cast<ChainingTrustEngine*>(m_trust);
-                if (trustchain) {
-                    trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE, nullptr));
-                    trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(SHIBBOLETH_PKIX_TRUSTENGINE, nullptr));
-                }
+    if (conf.isEnabled(SPConfig::Trust)) {
+        m_trust.reset(doChainedPlugins(xmlConf.TrustEngineManager, "TrustEngine", CHAINING_TRUSTENGINE, _TrustEngine, e, log));
+        if (!m_trust && !m_base) {
+            log.info(
+                "no TrustEngine specified or installed, using default chain {%s, %s}",
+                EXPLICIT_KEY_TRUSTENGINE, SHIBBOLETH_PKIX_TRUSTENGINE
+                );
+            m_trust.reset(xmlConf.TrustEngineManager.newPlugin(CHAINING_TRUSTENGINE, nullptr));
+            ChainingTrustEngine* trustchain = dynamic_cast<ChainingTrustEngine*>(m_trust.get());
+            if (trustchain) {
+                trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(EXPLICIT_KEY_TRUSTENGINE, nullptr));
+                trustchain->addTrustEngine(xmlConf.TrustEngineManager.newPlugin(SHIBBOLETH_PKIX_TRUSTENGINE, nullptr));
             }
         }
+    }
 
-        if (conf.isEnabled(SPConfig::AttributeResolution))
-            doAttributePlugins(e, log);
+    if (conf.isEnabled(SPConfig::AttributeResolution)) {
+        doAttributePlugins(e, log);
+    }
 
-        if (conf.isEnabled(SPConfig::Credentials)) {
-            m_credResolver = doChainedPlugins(
-                xmlConf.CredentialResolverManager, "CredentialResolver", CHAINING_CREDENTIAL_RESOLVER, _CredentialResolver, e, log
-                );
-        }
+    if (conf.isEnabled(SPConfig::Credentials)) {
+        m_credResolver.reset(
+            doChainedPlugins(xmlConf.CredentialResolverManager, "CredentialResolver", CHAINING_CREDENTIAL_RESOLVER, _CredentialResolver, e, log)
+            );
+    }
 
-        // Finally, load relying parties.
-        const DOMElement* child = XMLHelper::getFirstChildElement(e, RelyingParty);
+    // Finally, load relying parties.
+    const DOMElement* child = XMLHelper::getFirstChildElement(e, RelyingParty);
+    while (child) {
+        if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
+            boost::shared_ptr<DOMPropertySet> rp(new DOMPropertySet());
+            rp->load(child, nullptr, this);
+            rp->setParent(this);
+            m_partyMap[child->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp;
+        }
+        child = XMLHelper::getNextSiblingElement(child, RelyingParty);
+    }
+    if (base && m_partyMap.empty() && !base->m_partyMap.empty()) {
+        // For inheritance of RPs to work, we have to pull them in to the override by cloning the DOM.
+        child = XMLHelper::getFirstChildElement(base->getElement(), RelyingParty);
         while (child) {
             if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
-                auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
-                rp->load(child, nullptr, this);
+                DOMElement* rpclone = static_cast<DOMElement*>(child->cloneNode(true));
+                boost::shared_ptr<DOMPropertySet> rp(new DOMPropertySet());
+                rp->load(rpclone, nullptr, this);
                 rp->setParent(this);
-                m_partyMap[child->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp.release();
+                m_partyMap[rpclone->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp;
             }
             child = XMLHelper::getNextSiblingElement(child, RelyingParty);
         }
-        if (base && m_partyMap.empty() && !base->m_partyMap.empty()) {
-            // For inheritance of RPs to work, we have to pull them in to the override by cloning the DOM.
-            child = XMLHelper::getFirstChildElement(base->getElement(), RelyingParty);
-            while (child) {
-                if (child->hasAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)) {
-                    DOMElement* rpclone = static_cast<DOMElement*>(child->cloneNode(true));
-                    auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
-                    rp->load(rpclone, nullptr, this);
-                    rp->setParent(this);
-                    m_partyMap[rpclone->getAttributeNS(nullptr, saml2::Attribute::NAME_ATTRIB_NAME)] = rp.release();
-                }
-                child = XMLHelper::getNextSiblingElement(child, RelyingParty);
-            }
-        }
+    }
 #endif
 
-        // Out of process only, we register a listener endpoint.
-        if (!conf.isEnabled(SPConfig::InProcess)) {
-            ListenerService* listener = sp->getListenerService(false);
-            if (listener) {
-                string addr=string(getId()) + "::getHeaders::Application";
-                listener->regListener(addr.c_str(),this);
-            }
-            else {
-                log.info("no ListenerService available, Application remoting disabled");
-            }
+    // Out of process only, we register a listener endpoint.
+    if (!conf.isEnabled(SPConfig::InProcess)) {
+        ListenerService* listener = sp->getListenerService(false);
+        if (listener) {
+            string addr=string(getId()) + "::getHeaders::Application";
+            listener->regListener(addr.c_str(), this);
+        }
+        else {
+            log.info("no ListenerService available, Application remoting disabled");
         }
     }
-    catch (exception&) {
-        cleanup();
-        throw;
-    }
-#ifndef _DEBUG
-    catch (...) {
-        cleanup();
-        throw;
+}
+
+XMLApplication::~XMLApplication()
+{
+    ListenerService* listener=getServiceProvider().getListenerService(false);
+    if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
+        string addr=string(getId()) + "::getHeaders::Application";
+        listener->unregListener(addr.c_str(), this);
     }
-#endif
 }
 
 template <class T> T* XMLApplication::doChainedPlugins(
@@ -715,7 +708,7 @@ template <class T> T* XMLApplication::doChainedPlugins(
                 throw ConfigurationException("$1 element had no type attribute.", params(1, pluginType));
             }
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             log.crit("error building %s: %s", pluginType, ex.what());
             if (dummyType) {
                 // Install a dummy version as a safety valve.
@@ -744,21 +737,8 @@ void XMLApplication::doAttributeInfo()
 
     pair<bool,const char*> attributes = getString("REMOTE_USER");
     if (attributes.first) {
-        char* dup = strdup(attributes.second);
-        char* pos;
-        char* start = dup;
-        while (start && *start) {
-            while (*start && isspace(*start))
-                start++;
-            if (!*start)
-                break;
-            pos = strchr(start,' ');
-            if (pos)
-                *pos=0;
-            m_remoteUsers.push_back(start);
-            start = pos ? pos+1 : nullptr;
-        }
-        free(dup);
+        string dup(attributes.second);
+        split(m_remoteUsers, dup, is_space(), algorithm::token_compress_on);
     }
 
     // Load attribute ID lists for REMOTE_USER and header clearing.
@@ -775,31 +755,21 @@ void XMLApplication::doAttributeInfo()
                     pch++;
                 }
             }
-            char* dup = strdup(attributes.second);
-            char* pos;
-            char* start = dup;
-            while (start && *start) {
-                while (*start && isspace(*start))
-                    start++;
-                if (!*start)
-                    break;
-                pos = strchr(start,' ');
-                if (pos)
-                    *pos=0;
 
+            string dup(attributes.second);
+            vector<string> headerNames;
+            split(headerNames, dup, is_space(), algorithm::token_compress_on);
+            for (vector<string>::const_iterator h = headerNames.begin(); h != headerNames.end(); ++h) {
                 string transformed;
-                pch = start;
+                const char* pch = h->c_str();
                 while (*pch) {
                     transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                     pch++;
                 }
-
-                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *h, m_attributePrefix.second + transformed));
                 if (prefix.first)
-                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
-                start = pos ? pos+1 : nullptr;
+                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *h, transformedprefix + transformed));
             }
-            free(dup);
             m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
         }
     }
@@ -809,7 +779,6 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
 {
     SPConfig& conf = SPConfig::getConfig();
 
-    Handler* handler = nullptr;
     const PropertySet* sessions = getPropertySet("Sessions");
 
     // Process assertion export handler.
@@ -823,10 +792,10 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                 static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);
                 exportElement->setAttributeNS(nullptr,_acl,exportACL.second);
             }
-            handler = conf.HandlerManager.newPlugin(
-                samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())
+            boost::shared_ptr<Handler> exportHandler(
+                conf.HandlerManager.newPlugin(samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId()))
                 );
-            m_handlers.push_back(handler);
+            m_handlers.push_back(exportHandler);
 
             // Insert into location map. If it contains the handlerURL, we skip past that part.
             const char* hurl = sessions->getString("handlerURL").second;
@@ -836,11 +805,11 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
             if (pch)
                 location.second = pch + strlen(hurl);
             if (*location.second == '/')
-                m_handlerMap[location.second]=handler;
+                m_handlerMap[location.second] = exportHandler.get();
             else
-                m_handlerMap[string("/") + location.second]=handler;
+                m_handlerMap[string("/") + location.second] = exportHandler.get();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             log.error("caught exception installing assertion lookup handler: %s", ex.what());
         }
     }
@@ -883,6 +852,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
             continue;
         }
         try {
+            boost::shared_ptr<Handler> handler;
             if (XMLString::equals(child->getLocalName(), _AssertionConsumerService)) {
                 string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
                 if (bindprop.empty()) {
@@ -890,24 +860,24 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
                 // Map by binding and protocol (may be > 1 per protocol and binding)
-                m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+                m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler.get());
                 const XMLCh* protfamily = handler->getProtocolFamily();
                 if (protfamily)
-                    m_acsProtocolMap[protfamily].push_back(handler);
-                m_acsIndexMap[handler->getUnsignedInt("index").second] = handler;
+                    m_acsProtocolMap[protfamily].push_back(handler.get());
+                m_acsIndexMap[handler->getUnsignedInt("index").second] = handler.get();
 
                 if (!hardACS) {
                     pair<bool,bool> defprop = handler->getBool("isDefault");
                     if (defprop.first) {
                         if (defprop.second) {
                             hardACS = true;
-                            m_acsDefault = handler;
+                            m_acsDefault = handler.get();
                         }
                     }
                     else if (!m_acsDefault)
-                        m_acsDefault = handler;
+                        m_acsDefault = handler.get();
                 }
             }
             else if (XMLString::equals(child->getLocalName(), _SessionInitiator)) {
@@ -917,21 +887,23 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                SessionInitiator* sihandler = conf.SessionInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                boost::shared_ptr<SessionInitiator> sihandler(
+                    conf.SessionInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()))
+                    );
                 handler = sihandler;
                 pair<bool,const char*> si_id = handler->getString("id");
                 if (si_id.first && si_id.second)
-                    m_sessionInitMap[si_id.second] = sihandler;
+                    m_sessionInitMap[si_id.second] = sihandler.get();
                 if (!hardSessionInit) {
                     pair<bool,bool> defprop = handler->getBool("isDefault");
                     if (defprop.first) {
                         if (defprop.second) {
                             hardSessionInit = true;
-                            m_sessionInitDefault = sihandler;
+                            m_sessionInitDefault = sihandler.get();
                         }
                     }
                     else if (!m_sessionInitDefault) {
-                        m_sessionInitDefault = sihandler;
+                        m_sessionInitDefault = sihandler.get();
                     }
                 }
             }
@@ -942,7 +914,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.LogoutInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.LogoutInitiatorManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId())));
             }
             else if (XMLString::equals(child->getLocalName(), _ArtifactResolutionService)) {
                 string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
@@ -951,18 +923,18 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.ArtifactResolutionServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.ArtifactResolutionServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
 
                 if (!hardArt) {
                     pair<bool,bool> defprop = handler->getBool("isDefault");
                     if (defprop.first) {
                         if (defprop.second) {
                             hardArt = true;
-                            m_artifactResolutionDefault = handler;
+                            m_artifactResolutionDefault = handler.get();
                         }
                     }
                     else if (!m_artifactResolutionDefault)
-                        m_artifactResolutionDefault = handler;
+                        m_artifactResolutionDefault = handler.get();
                 }
             }
             else if (XMLString::equals(child->getLocalName(), _SingleLogoutService)) {
@@ -972,7 +944,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.SingleLogoutServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.SingleLogoutServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
             }
             else if (XMLString::equals(child->getLocalName(), _ManageNameIDService)) {
                 string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
@@ -981,7 +953,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.ManageNameIDServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.ManageNameIDServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
             }
             else {
                 string t(XMLHelper::getAttrString(child, nullptr, _type));
@@ -990,7 +962,7 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
                     child = XMLHelper::getNextSiblingElement(child);
                     continue;
                 }
-                handler = conf.HandlerManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId()));
+                handler.reset(conf.HandlerManager.newPlugin(t.c_str(), pair<const DOMElement*,const char*>(child, getId())));
             }
 
             m_handlers.push_back(handler);
@@ -998,11 +970,11 @@ void XMLApplication::doHandlers(const ProtocolProvider* pp, const DOMElement* e,
             // Insert into location map.
             location = handler->getString("Location");
             if (location.first && *location.second == '/')
-                m_handlerMap[location.second] = handler;
+                m_handlerMap[location.second] = handler.get();
             else if (location.first)
-                m_handlerMap[string("/") + location.second] = handler;
+                m_handlerMap[string("/") + location.second] = handler.get();
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             log.error("caught exception processing handler element: %s", ex.what());
         }
 
@@ -1061,26 +1033,28 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
                     acsdom->setAttributeNS(nullptr, _index, indexbuf.c_str());
 
                     log.info("adding AssertionConsumerService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
-                    Handler* handler = conf.AssertionConsumerServiceManager.newPlugin(
-                        (*b)->getString("id").second, pair<const DOMElement*,const char*>(acsdom, getId())
+                    boost::shared_ptr<Handler> handler(
+                        conf.AssertionConsumerServiceManager.newPlugin(
+                            (*b)->getString("id").second, pair<const DOMElement*,const char*>(acsdom, getId())
+                            )
                         );
                     m_handlers.push_back(handler);
 
                     // Setup maps and defaults.
-                    m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
+                    m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler.get());
                     const XMLCh* protfamily = handler->getProtocolFamily();
                     if (protfamily)
-                        m_acsProtocolMap[protfamily].push_back(handler);
-                    m_acsIndexMap[handler->getUnsignedInt("index").second] = handler;
+                        m_acsProtocolMap[protfamily].push_back(handler.get());
+                    m_acsIndexMap[handler->getUnsignedInt("index").second] = handler.get();
                     if (!m_acsDefault)
-                        m_acsDefault = handler;
+                        m_acsDefault = handler.get();
 
                     // Insert into location map.
                     pair<bool,const char*> location = handler->getString("Location");
                     if (location.first && *location.second == '/')
-                        m_handlerMap[location.second] = handler;
+                        m_handlerMap[location.second] = handler.get();
                     else if (location.first)
-                        m_handlerMap[string("/") + location.second] = handler;
+                        m_handlerMap[string("/") + location.second] = handler.get();
                 }
                 else {
                     log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
@@ -1121,12 +1095,12 @@ void XMLApplication::doSSO(const ProtocolProvider& pp, set<string>& protocols, D
     e->setAttributeNS(nullptr, Location, _loc);
 
     // Instantiate Chaining initiator around the SSO element.
-    SessionInitiator* chain = conf.SessionInitiatorManager.newPlugin(
-        CHAINING_SESSION_INITIATOR, pair<const DOMElement*,const char*>(e, getId())
+    boost::shared_ptr<SessionInitiator> chain(
+        conf.SessionInitiatorManager.newPlugin(CHAINING_SESSION_INITIATOR, pair<const DOMElement*,const char*>(e, getId()))
         );
     m_handlers.push_back(chain);
-    m_sessionInitDefault = chain;
-    m_handlerMap["/Login"] = chain;
+    m_sessionInitDefault = chain.get();
+    m_handlerMap["/Login"] = chain.get();
 }
 
 void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols, DOMElement* e, Category& log)
@@ -1177,17 +1151,17 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
                     slodom->setAttributeNS(nullptr, Location, pathprop.second);
 
                     log.info("adding SingleLogoutService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
-                    Handler* handler = conf.SingleLogoutServiceManager.newPlugin(
-                        (*b)->getString("id").second, pair<const DOMElement*,const char*>(slodom, getId())
+                    boost::shared_ptr<Handler> handler(
+                        conf.SingleLogoutServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(slodom, getId()))
                         );
                     m_handlers.push_back(handler);
 
                     // Insert into location map.
                     pair<bool,const char*> location = handler->getString("Location");
                     if (location.first && *location.second == '/')
-                        m_handlerMap[location.second] = handler;
+                        m_handlerMap[location.second] = handler.get();
                     else if (location.first)
-                        m_handlerMap[string("/") + location.second] = handler;
+                        m_handlerMap[string("/") + location.second] = handler.get();
                 }
                 else {
                     log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
@@ -1210,11 +1184,11 @@ void XMLApplication::doLogout(const ProtocolProvider& pp, set<string>& protocols
     e->setAttributeNS(nullptr, Location, _loc);
 
     // Instantiate Chaining initiator around the SSO element.
-    Handler* chain = conf.LogoutInitiatorManager.newPlugin(
-        CHAINING_LOGOUT_INITIATOR, pair<const DOMElement*,const char*>(e, getId())
+    boost::shared_ptr<Handler> chain(
+        conf.LogoutInitiatorManager.newPlugin(CHAINING_LOGOUT_INITIATOR, pair<const DOMElement*,const char*>(e, getId()))
         );
     m_handlers.push_back(chain);
-    m_handlerMap["/Logout"] = chain;
+    m_handlerMap["/Logout"] = chain.get();
 }
 
 void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& protocols, DOMElement* e, Category& log)
@@ -1243,17 +1217,17 @@ void XMLApplication::doNameIDMgmt(const ProtocolProvider& pp, set<string>& proto
                     nimdom->setAttributeNS(nullptr, Location, pathprop.second);
 
                     log.info("adding ManageNameIDService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
-                    Handler* handler = conf.ManageNameIDServiceManager.newPlugin(
-                        (*b)->getString("id").second, pair<const DOMElement*,const char*>(nimdom, getId())
+                    boost::shared_ptr<Handler> handler(
+                        conf.ManageNameIDServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(nimdom, getId()))
                         );
                     m_handlers.push_back(handler);
 
                     // Insert into location map.
                     pair<bool,const char*> location = handler->getString("Location");
                     if (location.first && *location.second == '/')
-                        m_handlerMap[location.second] = handler;
+                        m_handlerMap[location.second] = handler.get();
                     else if (location.first)
-                        m_handlerMap[string("/") + location.second] = handler;
+                        m_handlerMap[string("/") + location.second] = handler.get();
                 }
                 else {
                     log.error("missing id or path property on Binding element, check config for protocol (%s)", prot.get());
@@ -1294,20 +1268,20 @@ void XMLApplication::doArtifactResolution(const ProtocolProvider& pp, const char
                 artdom->setAttributeNS(nullptr, _index, indexbuf.c_str());
 
                 log.info("adding ArtifactResolutionService for Binding (%s) at (%s)", (*b)->getString("id").second, (*b)->getString("path").second);
-                Handler* handler = conf.ArtifactResolutionServiceManager.newPlugin(
-                    (*b)->getString("id").second, pair<const DOMElement*,const char*>(artdom, getId())
+                boost::shared_ptr<Handler> handler(
+                    conf.ArtifactResolutionServiceManager.newPlugin((*b)->getString("id").second, pair<const DOMElement*,const char*>(artdom, getId()))
                     );
                 m_handlers.push_back(handler);
 
                 if (!m_artifactResolutionDefault)
-                    m_artifactResolutionDefault = handler;
+                    m_artifactResolutionDefault = handler.get();
 
                 // Insert into location map.
                 pair<bool,const char*> location = handler->getString("Location");
                 if (location.first && *location.second == '/')
-                    m_handlerMap[location.second] = handler;
+                    m_handlerMap[location.second] = handler.get();
                 else if (location.first)
-                    m_handlerMap[string("/") + location.second] = handler;
+                    m_handlerMap[string("/") + location.second] = handler.get();
             }
             else {
                 log.error("missing id or path property on Binding element, check config for protocol (%s)", protocol);
@@ -1321,31 +1295,34 @@ void XMLApplication::doAttributePlugins(DOMElement* e, Category& log)
 {
     SPConfig& conf = SPConfig::getConfig();
 
-    m_attrExtractor =
-        doChainedPlugins(conf.AttributeExtractorManager, "AttributeExtractor", CHAINING_ATTRIBUTE_EXTRACTOR, _AttributeExtractor, e, log);
+    m_attrExtractor.reset(
+        doChainedPlugins(conf.AttributeExtractorManager, "AttributeExtractor", CHAINING_ATTRIBUTE_EXTRACTOR, _AttributeExtractor, e, log)
+        );
 
-    m_attrFilter =
-        doChainedPlugins(conf.AttributeFilterManager, "AttributeFilter", CHAINING_ATTRIBUTE_FILTER, _AttributeFilter, e, log, DUMMY_ATTRIBUTE_FILTER);
+    m_attrFilter.reset(
+        doChainedPlugins(conf.AttributeFilterManager, "AttributeFilter", CHAINING_ATTRIBUTE_FILTER, _AttributeFilter, e, log, DUMMY_ATTRIBUTE_FILTER)
+        );
 
-    m_attrResolver =
-        doChainedPlugins(conf.AttributeResolverManager, "AttributeResolver", CHAINING_ATTRIBUTE_RESOLVER, _AttributeResolver, e, log);
+    m_attrResolver.reset(
+        doChainedPlugins(conf.AttributeResolverManager, "AttributeResolver", CHAINING_ATTRIBUTE_RESOLVER, _AttributeResolver, e, log)
+        );
 
     if (m_unsetHeaders.empty()) {
         vector<string> unsetHeaders;
         if (m_attrExtractor) {
-            Locker extlock(m_attrExtractor);
+            Locker extlock(m_attrExtractor.get());
             m_attrExtractor->getAttributeIds(unsetHeaders);
         }
         else if (m_base && m_base->m_attrExtractor) {
-            Locker extlock(m_base->m_attrExtractor);
+            Locker extlock(m_base->m_attrExtractor.get());
             m_base->m_attrExtractor->getAttributeIds(unsetHeaders);
         }
         if (m_attrResolver) {
-            Locker reslock(m_attrResolver);
+            Locker reslock(m_attrResolver.get());
             m_attrResolver->getAttributeIds(unsetHeaders);
         }
         else if (m_base && m_base->m_attrResolver) {
-            Locker extlock(m_base->m_attrResolver);
+            Locker extlock(m_base->m_attrResolver.get());
             m_base->m_attrResolver->getAttributeIds(unsetHeaders);
         }
         if (!unsetHeaders.empty()) {
@@ -1366,43 +1343,16 @@ void XMLApplication::doAttributePlugins(DOMElement* e, Category& log)
                     transformed += (isalnum(*pch) ? toupper(*pch) : '_');
                     pch++;
                 }
-                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
+                m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
                 if (prefix.first)
-                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
+                    m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
             }
         }
-        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
+        m_unsetHeaders.push_back(make_pair(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
     }
 }
 #endif
 
-void XMLApplication::cleanup()
-{
-    ListenerService* listener=getServiceProvider().getListenerService(false);
-    if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
-        string addr=string(getId()) + "::getHeaders::Application";
-        listener->unregListener(addr.c_str(),this);
-    }
-    for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
-    m_handlers.clear();
-#ifndef SHIBSP_LITE
-    for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());
-    m_partyMap.clear();
-    delete m_credResolver;
-    m_credResolver = nullptr;
-    delete m_attrResolver;
-    m_attrResolver = nullptr;
-    delete m_attrFilter;
-    m_attrFilter = nullptr;
-    delete m_attrExtractor;
-    m_attrExtractor = nullptr;
-    delete m_trust;
-    m_trust = nullptr;
-    delete m_metadata;
-    m_metadata = nullptr;
-#endif
-}
-
 #ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
 short
 #else
@@ -1443,17 +1393,17 @@ const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provi
     if (!provider)
         return this;
 
-    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());
-    if (i!=m_partyMap.end())
-        return i->second;
-    const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
+    map< xstring,boost::shared_ptr<PropertySet> >::const_iterator i = m_partyMap.find(provider->getEntityID());
+    if (i != m_partyMap.end())
+        return i->second.get();
+    const EntitiesDescriptor* group = dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
     while (group) {
         if (group->getName()) {
-            i=m_partyMap.find(group->getName());
-            if (i!=m_partyMap.end())
-                return i->second;
+            i = m_partyMap.find(group->getName());
+            if (i != m_partyMap.end())
+                return i->second.get();
         }
-        group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
+        group = dynamic_cast<const EntitiesDescriptor*>(group->getParent());
     }
     return this;
 }
@@ -1462,11 +1412,8 @@ const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const
 {
     if (!entityID)
         return this;
-
-    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);
-    if (i!=m_partyMap.end())
-        return i->second;
-    return this;
+    map< xstring,boost::shared_ptr<PropertySet> >::const_iterator i = m_partyMap.find(entityID);
+    return (i != m_partyMap.end()) ? i->second.get() : this;
 }
 
 #endif
@@ -1486,7 +1433,7 @@ string XMLApplication::getNotificationURL(const char* resource, bool front, unsi
 #endif
         throw ConfigurationException("Request URL was not absolute.");
 
-    const char* handler=locs[index].c_str();
+    const char* handler = locs[index].c_str();
 
     // Should never happen...
     if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
@@ -1594,8 +1541,8 @@ const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const
 
 const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const
 {
-    map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);
-    if (i!=m_sessionInitMap.end()) return i->second;
+    map<string,const SessionInitiator*>::const_iterator i = m_sessionInitMap.find(id);
+    if (i != m_sessionInitMap.end()) return i->second;
     return m_base ? m_base->getSessionInitiatorById(id) : nullptr;
 }
 
@@ -1607,14 +1554,14 @@ const Handler* XMLApplication::getDefaultAssertionConsumerService() const
 
 const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const
 {
-    map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
+    map<unsigned int,const Handler*>::const_iterator i = m_acsIndexMap.find(index);
     if (i != m_acsIndexMap.end()) return i->second;
     return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : nullptr;
 }
 
 const Handler* XMLApplication::getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding) const
 {
-    ACSProtocolMap::const_iterator i=m_acsProtocolMap.find(protocol);
+    ACSProtocolMap::const_iterator i = m_acsProtocolMap.find(protocol);
     if (i != m_acsProtocolMap.end() && !i->second.empty()) {
         if (!binding || !*binding)
             return i->second.front();
@@ -1628,7 +1575,7 @@ const Handler* XMLApplication::getAssertionConsumerServiceByProtocol(const XMLCh
 
 const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
 {
-    ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
+    ACSBindingMap::const_iterator i = m_acsBindingMap.find(binding);
     if (i != m_acsBindingMap.end())
         return i->second;
     return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
@@ -1637,16 +1584,17 @@ const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBind
 const Handler* XMLApplication::getHandler(const char* path) const
 {
     string wrap(path);
-    wrap = wrap.substr(0,wrap.find(';'));
-    map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
-    if (i!=m_handlerMap.end())
+    wrap = wrap.substr(0, wrap.find(';'));
+    map<string,const Handler*>::const_iterator i = m_handlerMap.find(wrap.substr(0, wrap.find('?')));
+    if (i != m_handlerMap.end())
         return i->second;
     return m_base ? m_base->getHandler(path) : nullptr;
 }
 
 void XMLApplication::getHandlers(vector<const Handler*>& handlers) const
 {
-    handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());
+    static void (vector<const Handler*>::* pb)(const Handler* const&) = &vector<const Handler*>::push_back;
+    for_each(m_handlers.begin(), m_handlers.end(), boost::bind(pb, boost::ref(handlers), boost::bind(&boost::shared_ptr<Handler>::get, _1)));
     if (m_base) {
         for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {
             if (m_handlerMap.count(h->first) == 0)
@@ -1699,7 +1647,7 @@ void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Categor
                     log.debug("loaded %s extension library (%s)", label, path.c_str());
                 }
             }
-            catch (exception& e) {
+            catch (std::exception& e) {
                 if (XMLHelper::getAttrBool(exts, false, _fatal)) {
                     log.fatal("unable to load mandatory %s extension library %s: %s", label, path.c_str(), e.what());
                     throw;
@@ -1738,7 +1686,7 @@ void XMLConfigImpl::doListener(const DOMElement* e, XMLConfig* conf, Category& l
     }
 
     log.info("building ListenerService of type %s...", plugtype.c_str());
-    conf->m_listener = SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child);
+    conf->m_listener.reset(SPConfig::getConfig().ListenerServiceManager.newPlugin(plugtype.c_str(), child));
 }
 
 void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& log)
@@ -1760,9 +1708,9 @@ void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& lo
             if (!t.empty()) {
                 try {
                     log.info("building StorageService (%s) of type %s...", id.c_str(), t.c_str());
-                    conf->m_storage[id] = xmlConf.StorageServiceManager.newPlugin(t.c_str(), child);
+                    conf->m_storage[id] = boost::shared_ptr<StorageService>(xmlConf.StorageServiceManager.newPlugin(t.c_str(), child));
                 }
-                catch (exception& ex) {
+                catch (std::exception& ex) {
                     log.crit("failed to instantiate StorageService (%s): %s", id.c_str(), ex.what());
                 }
             }
@@ -1771,7 +1719,7 @@ void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& lo
 
         if (conf->m_storage.empty()) {
             log.info("no StorageService plugin(s) installed, using (mem) in-memory instance");
-            conf->m_storage["mem"] = xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr);
+            conf->m_storage["mem"] = boost::shared_ptr<StorageService>(xmlConf.StorageServiceManager.newPlugin(MEMORY_STORAGE_SERVICE, nullptr));
         }
 
         // Replay cache.
@@ -1782,21 +1730,21 @@ void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& lo
             if (!ssid.empty()) {
                 if (conf->m_storage.count(ssid)) {
                     log.info("building ReplayCache on top of StorageService (%s)...", ssid.c_str());
-                    replaySS = conf->m_storage[ssid];
+                    replaySS = conf->m_storage[ssid].get();
                 }
                 else {
                     log.error("unable to locate StorageService (%s), using arbitrary instance for ReplayCache", ssid.c_str());
-                    replaySS = conf->m_storage.begin()->second;
+                    replaySS = conf->m_storage.begin()->second.get();
                 }
             }
             else {
                 log.info("no StorageService specified for ReplayCache, using arbitrary instance");
-                replaySS = conf->m_storage.begin()->second;
+                replaySS = conf->m_storage.begin()->second.get();
             }
         }
         else {
             log.info("no ReplayCache specified, using arbitrary StorageService instance");
-            replaySS = conf->m_storage.begin()->second;
+            replaySS = conf->m_storage.begin()->second.get();
         }
         xmlConf.setReplayCache(new ReplayCache(replaySS));
 
@@ -1807,7 +1755,7 @@ void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& lo
             if (!ssid.empty()) {
                 if (conf->m_storage.count(ssid)) {
                     log.info("building ArtifactMap on top of StorageService (%s)...", ssid.c_str());
-                    samlConf.setArtifactMap(new ArtifactMap(child, conf->m_storage[ssid]));
+                    samlConf.setArtifactMap(new ArtifactMap(child, conf->m_storage[ssid].get()));
                 }
                 else {
                     log.error("unable to locate StorageService (%s), using in-memory ArtifactMap", ssid.c_str());
@@ -1831,305 +1779,259 @@ void XMLConfigImpl::doCaching(const DOMElement* e, XMLConfig* conf, Category& lo
         string t(XMLHelper::getAttrString(child, nullptr, _type));
         if (!t.empty()) {
             log.info("building SessionCache of type %s...", t.c_str());
-            conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(t.c_str(), child);
+            conf->m_sessionCache.reset(spConf.SessionCacheManager.newPlugin(t.c_str(), child));
         }
     }
     if (!conf->m_sessionCache) {
         log.info("no SessionCache specified, using StorageService-backed instance");
-        conf->m_sessionCache = spConf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr);
+        conf->m_sessionCache.reset(spConf.SessionCacheManager.newPlugin(STORAGESERVICE_SESSION_CACHE, nullptr));
     }
 }
 
-XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log)
-    : m_requestMapper(nullptr),
-#ifndef SHIBSP_LITE
-        m_tranLog(nullptr),
-        m_policy(nullptr),
-#endif
-        m_document(nullptr)
+XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, XMLConfig* outer, Category& log) : m_document(nullptr)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("XMLConfigImpl");
 #endif
-
-    try {
-        SPConfig& conf=SPConfig::getConfig();
-        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
-        const DOMElement* SHAR=XMLHelper::getFirstChildElement(e, OutOfProcess);
-        const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess);
-
-        // Initialize logging manually in order to redirect log messages as soon as possible.
-        if (conf.isEnabled(SPConfig::Logging)) {
-            string logconf;
-            if (conf.isEnabled(SPConfig::OutOfProcess))
-                logconf = XMLHelper::getAttrString(SHAR, nullptr, logger);
-            else if (conf.isEnabled(SPConfig::InProcess))
-                logconf = XMLHelper::getAttrString(SHIRE, nullptr, logger);
-            if (logconf.empty())
-                logconf = XMLHelper::getAttrString(e, nullptr, logger);
-            if (logconf.empty() && !getenv("SHIBSP_LOGGING")) {
-                // No properties found, so default them.
-                if (conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess))
-                    logconf = "shibd.logger";
-                else if (!conf.isEnabled(SPConfig::OutOfProcess) && conf.isEnabled(SPConfig::InProcess))
-                    logconf = "native.logger";
-                else
-                    logconf = "shibboleth.logger";
-            }
-            if (!logconf.empty()) {
-                log.debug("loading new logging configuration from (%s), check log destination for status of configuration", logconf.c_str());
-                if (!XMLToolingConfig::getConfig().log_config(logconf.c_str()))
-                    log.crit("failed to load new logging configuration from (%s)", logconf.c_str());
-            }
+    SPConfig& conf=SPConfig::getConfig();
+    XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
+    const DOMElement* SHAR=XMLHelper::getFirstChildElement(e, OutOfProcess);
+    const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e, InProcess);
+
+    // Initialize logging manually in order to redirect log messages as soon as possible.
+    if (conf.isEnabled(SPConfig::Logging)) {
+        string logconf;
+        if (conf.isEnabled(SPConfig::OutOfProcess))
+            logconf = XMLHelper::getAttrString(SHAR, nullptr, logger);
+        else if (conf.isEnabled(SPConfig::InProcess))
+            logconf = XMLHelper::getAttrString(SHIRE, nullptr, logger);
+        if (logconf.empty())
+            logconf = XMLHelper::getAttrString(e, nullptr, logger);
+        if (logconf.empty() && !getenv("SHIBSP_LOGGING")) {
+            // No properties found, so default them.
+            if (conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess))
+                logconf = "shibd.logger";
+            else if (!conf.isEnabled(SPConfig::OutOfProcess) && conf.isEnabled(SPConfig::InProcess))
+                logconf = "native.logger";
+            else
+                logconf = "shibboleth.logger";
+        }
+        if (!logconf.empty()) {
+            log.debug("loading new logging configuration from (%s), check log destination for status of configuration", logconf.c_str());
+            if (!XMLToolingConfig::getConfig().log_config(logconf.c_str()))
+                log.crit("failed to load new logging configuration from (%s)", logconf.c_str());
+        }
 
 #ifndef SHIBSP_LITE
-            m_tranLog = new TransactionLog(
+        m_tranLog.reset(
+            new TransactionLog(
                 XMLHelper::getAttrString(SHAR, nullptr, tranLogFormat).c_str(),
                 XMLHelper::getAttrString(SHAR, nullptr, tranLogFiller).c_str()
-                );
+                )
+            );
 #endif
-        }
+    }
 
-        // Re-log library versions now that logging is set up.
-        log.info("Shibboleth SP Version %s", PACKAGE_VERSION);
+    // Re-log library versions now that logging is set up.
+    log.info("Shibboleth SP Version %s", PACKAGE_VERSION);
 #ifndef SHIBSP_LITE
-        log.info(
-            "Library versions: %s %s, Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
+    log.info(
+        "Library versions: %s %s, Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
 # if defined(LOG4SHIB_VERSION)
-        "log4shib", LOG4SHIB_VERSION,
+    "log4shib", LOG4SHIB_VERSION,
 # elif defined(LOG4CPP_VERSION)
-        "log4cpp", LOG4CPP_VERSION,
+    "log4cpp", LOG4CPP_VERSION,
 # else
-        "", "",
+    "", "",
 # endif
-            XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, gXMLToolingDotVersionStr, gOpenSAMLDotVersionStr, gShibSPDotVersionStr
-            );
+        XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, gXMLToolingDotVersionStr, gOpenSAMLDotVersionStr, gShibSPDotVersionStr
+        );
 #else
-        log.info(
-            "Library versions: %s %s, Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
+    log.info(
+        "Library versions: %s %s, Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
 # if defined(LOG4SHIB_VERSION)
-        "log4shib", LOG4SHIB_VERSION,
+    "log4shib", LOG4SHIB_VERSION,
 # elif defined(LOG4CPP_VERSION)
-        "log4cpp", LOG4CPP_VERSION,
+    "log4cpp", LOG4CPP_VERSION,
 # else
-        "", "",
+    "", "",
 # endif
-            XERCES_FULLVERSIONDOT, gXMLToolingDotVersionStr, gShibSPDotVersionStr
-            );
+        XERCES_FULLVERSIONDOT, gXMLToolingDotVersionStr, gShibSPDotVersionStr
+        );
 #endif
 
-        // First load any property sets.
-        load(e,nullptr,this);
-
-        DOMElement* child;
-
-        // Much of the processing can only occur on the first instantiation.
-        if (first) {
-            // Set clock skew.
-            pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
-            if (skew.first)
-                xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
-
-            pair<bool,const char*> unsafe = getString("unsafeChars");
-            if (unsafe.first)
-                TemplateEngine::unsafe_chars = unsafe.second;
-
-            unsafe = getString("allowedSchemes");
-            if (unsafe.first) {
-                HTTPResponse::getAllowedSchemes().clear();
-                string schemes=unsafe.second;
-                unsigned int j_sch=0;
-                for (unsigned int i_sch=0;  i_sch < schemes.length();  i_sch++) {
-                    if (schemes.at(i_sch)==' ') {
-                        HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, i_sch-j_sch));
-                        j_sch = i_sch + 1;
-                    }
-                }
-                HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, schemes.length()-j_sch));
-            }
-
-            // Extensions
-            doExtensions(e, "global", log);
-            if (conf.isEnabled(SPConfig::OutOfProcess))
-                doExtensions(SHAR, "out of process", log);
+    // First load any property sets.
+    load(e, nullptr, this);
 
-            if (conf.isEnabled(SPConfig::InProcess))
-                doExtensions(SHIRE, "in process", log);
+    DOMElement* child;
 
-            // Instantiate the ListenerService and SessionCache objects.
-            if (conf.isEnabled(SPConfig::Listener))
-                doListener(e, outer, log);
+    // Much of the processing can only occur on the first instantiation.
+    if (first) {
+        // Set clock skew.
+        pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
+        if (skew.first)
+            xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
 
-#ifndef SHIBSP_LITE
-            if (outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
-                outer->m_listener->regListener("set::RelayState", outer);
-                outer->m_listener->regListener("get::RelayState", outer);
-                outer->m_listener->regListener("set::PostData", outer);
-                outer->m_listener->regListener("get::PostData", outer);
-            }
-#endif
-            if (conf.isEnabled(SPConfig::Caching))
-                doCaching(e, outer, log);
-        } // end of first-time-only stuff
+        pair<bool,const char*> unsafe = getString("unsafeChars");
+        if (unsafe.first)
+            TemplateEngine::unsafe_chars = unsafe.second;
 
-        // Back to the fully dynamic stuff...next up is the RequestMapper.
-        if (conf.isEnabled(SPConfig::RequestMapping)) {
-            if (child = XMLHelper::getFirstChildElement(e, _RequestMapper)) {
-                string t(XMLHelper::getAttrString(child, nullptr, _type));
-                if (!t.empty()) {
-                    log.info("building RequestMapper of type %s...", t.c_str());
-                    m_requestMapper = conf.RequestMapperManager.newPlugin(t.c_str(), child);
-                }
-            }
-            if (!m_requestMapper) {
-                log.info("no RequestMapper specified, using 'Native' plugin with empty/default map");
-                child = e->getOwnerDocument()->createElementNS(nullptr, _RequestMapper);
-                DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, RequestMap);
-                mapperDummy->setAttributeNS(nullptr, applicationId, _default);
-                child->appendChild(mapperDummy);
-                m_requestMapper = conf.RequestMapperManager.newPlugin(NATIVE_REQUEST_MAPPER, child);
-            }
+        unsafe = getString("allowedSchemes");
+        if (unsafe.first) {
+            HTTPResponse::getAllowedSchemes().clear();
+            string schemes(unsafe.second);
+            split(HTTPResponse::getAllowedSchemes(), schemes, is_space(), algorithm::token_compress_on);
         }
 
+        // Extensions
+        doExtensions(e, "global", log);
+        if (conf.isEnabled(SPConfig::OutOfProcess))
+            doExtensions(SHAR, "out of process", log);
+
+        if (conf.isEnabled(SPConfig::InProcess))
+            doExtensions(SHIRE, "in process", log);
+
+        // Instantiate the ListenerService and SessionCache objects.
+        if (conf.isEnabled(SPConfig::Listener))
+            doListener(e, outer, log);
+
 #ifndef SHIBSP_LITE
-        // Load security policies.
-        if (child = XMLHelper::getLastChildElement(e, _SecurityPolicyProvider)) {
+        if (outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
+            outer->m_listener->regListener("set::RelayState", outer);
+            outer->m_listener->regListener("get::RelayState", outer);
+            outer->m_listener->regListener("set::PostData", outer);
+            outer->m_listener->regListener("get::PostData", outer);
+        }
+#endif
+        if (conf.isEnabled(SPConfig::Caching))
+            doCaching(e, outer, log);
+    } // end of first-time-only stuff
+
+    // Back to the fully dynamic stuff...next up is the RequestMapper.
+    if (conf.isEnabled(SPConfig::RequestMapping)) {
+        if (child = XMLHelper::getFirstChildElement(e, _RequestMapper)) {
             string t(XMLHelper::getAttrString(child, nullptr, _type));
             if (!t.empty()) {
-                log.info("building SecurityPolicyProvider of type %s...", t.c_str());
-                m_policy = conf.SecurityPolicyProviderManager.newPlugin(t.c_str(), child);
-            }
-            else {
-                throw ConfigurationException("can't build SecurityPolicyProvider, no type specified");
+                log.info("building RequestMapper of type %s...", t.c_str());
+                m_requestMapper.reset(conf.RequestMapperManager.newPlugin(t.c_str(), child));
             }
         }
-        else if (child = XMLHelper::getLastChildElement(e, SecurityPolicies)) {
-            // For backward compatibility, wrap in a plugin element.
-            DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, _SecurityPolicyProvider);
-            polwrapper->appendChild(child);
-            log.info("building SecurityPolicyProvider of type %s...", XML_SECURITYPOLICY_PROVIDER);
-            m_policy = conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper);
+        if (!m_requestMapper) {
+            log.info("no RequestMapper specified, using 'Native' plugin with empty/default map");
+            child = e->getOwnerDocument()->createElementNS(nullptr, _RequestMapper);
+            DOMElement* mapperDummy = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS, RequestMap);
+            mapperDummy->setAttributeNS(nullptr, applicationId, _default);
+            child->appendChild(mapperDummy);
+            m_requestMapper.reset(conf.RequestMapperManager.newPlugin(NATIVE_REQUEST_MAPPER, child));
+        }
+    }
+
+#ifndef SHIBSP_LITE
+    // Load security policies.
+    if (child = XMLHelper::getLastChildElement(e, _SecurityPolicyProvider)) {
+        string t(XMLHelper::getAttrString(child, nullptr, _type));
+        if (!t.empty()) {
+            log.info("building SecurityPolicyProvider of type %s...", t.c_str());
+            m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(t.c_str(), child));
         }
         else {
-            log.fatal("can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
-            throw ConfigurationException("Can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+            throw ConfigurationException("can't build SecurityPolicyProvider, no type specified");
         }
+    }
+    else if (child = XMLHelper::getLastChildElement(e, SecurityPolicies)) {
+        // For backward compatibility, wrap in a plugin element.
+        DOMElement* polwrapper = e->getOwnerDocument()->createElementNS(nullptr, _SecurityPolicyProvider);
+        polwrapper->appendChild(child);
+        log.info("building SecurityPolicyProvider of type %s...", XML_SECURITYPOLICY_PROVIDER);
+        m_policy.reset(conf.SecurityPolicyProviderManager.newPlugin(XML_SECURITYPOLICY_PROVIDER, polwrapper));
+    }
+    else {
+        log.fatal("can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+        throw ConfigurationException("Can't build SecurityPolicyProvider, missing conf:SecurityPolicyProvider element?");
+    }
 
-        if (first) {
-            if (!m_policy->getAlgorithmBlacklist().empty()) {
+    if (first) {
+        if (!m_policy->getAlgorithmBlacklist().empty()) {
 #ifdef SHIBSP_XMLSEC_WHITELISTING
-                for (vector<xstring>::const_iterator alg = m_policy->getAlgorithmBlacklist().begin(); alg != m_policy->getAlgorithmBlacklist().end(); ++alg)
-                    XSECPlatformUtils::blacklistAlgorithm(alg->c_str());
+            for_each(
+                m_policy->getAlgorithmBlacklist().begin(), m_policy->getAlgorithmBlacklist().end(),
+                boost::bind(&XSECPlatformUtils::blacklistAlgorithm, boost::bind(&xstring::c_str, _1))
+                );
 #else
-                log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
+            log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
 #endif
-            }
-            else if (!m_policy->getAlgorithmWhitelist().empty()) {
+        }
+        else if (!m_policy->getAlgorithmWhitelist().empty()) {
 #ifdef SHIBSP_XMLSEC_WHITELISTING
-                for (vector<xstring>::const_iterator alg = m_policy->getAlgorithmWhitelist().begin(); alg != m_policy->getAlgorithmWhitelist().end(); ++alg)
-                    XSECPlatformUtils::whitelistAlgorithm(alg->c_str());
+            for_each(
+                m_policy->getAlgorithmWhitelist().begin(), m_policy->getAlgorithmWhitelist().end(),
+                boost::bind(&XSECPlatformUtils::whitelistAlgorithm, boost::bind(&xstring::c_str, _1))
+                );
 #else
-                log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
+            log.crit("XML-Security-C library prior to 1.6.0 does not support algorithm white/blacklists");
 #endif
-            }
         }
+    }
 
-        // Process TransportOption elements.
-        child = XMLHelper::getLastChildElement(e, TransportOption);
-        while (child) {
-            if (child->hasChildNodes()) {
-                string provider(XMLHelper::getAttrString(child, nullptr, _provider));
-                string option(XMLHelper::getAttrString(child, nullptr, _option));
-                auto_ptr_char value(child->getFirstChild()->getNodeValue());
-                if (!provider.empty() && !option.empty() && value.get() && *value.get()) {
-                    m_transportOptions.push_back(make_pair(provider, make_pair(option, string(value.get()))));
-                }
+    // Process TransportOption elements.
+    child = XMLHelper::getLastChildElement(e, TransportOption);
+    while (child) {
+        if (child->hasChildNodes()) {
+            string provider(XMLHelper::getAttrString(child, nullptr, _provider));
+            string option(XMLHelper::getAttrString(child, nullptr, _option));
+            auto_ptr_char value(child->getFirstChild()->getNodeValue());
+            if (!provider.empty() && !option.empty() && value.get() && *value.get()) {
+                m_transportOptions.push_back(make_tuple(provider, option, string(value.get())));
             }
-            child = XMLHelper::getPreviousSiblingElement(child, TransportOption);
         }
+        child = XMLHelper::getPreviousSiblingElement(child, TransportOption);
+    }
 #endif
 
-        ProtocolProvider* pp = nullptr;
-        if (conf.isEnabled(SPConfig::Handlers)) {
-            if (child = XMLHelper::getLastChildElement(e, _ProtocolProvider)) {
-                string t(XMLHelper::getAttrString(child, nullptr, _type));
-                if (!t.empty()) {
-                    log.info("building ProtocolProvider of type %s...", t.c_str());
-                    pp = conf.ProtocolProviderManager.newPlugin(t.c_str(), child);
-                }
+    scoped_ptr<ProtocolProvider> pp;
+    if (conf.isEnabled(SPConfig::Handlers)) {
+        if (child = XMLHelper::getLastChildElement(e, _ProtocolProvider)) {
+            string t(XMLHelper::getAttrString(child, nullptr, _type));
+            if (!t.empty()) {
+                log.info("building ProtocolProvider of type %s...", t.c_str());
+                pp.reset(conf.ProtocolProviderManager.newPlugin(t.c_str(), child));
             }
         }
-        auto_ptr<ProtocolProvider> ppwrapper(pp);
-        Locker pplocker(pp);
+    }
+    Locker pplocker(pp.get());
 
-        // Load the default application.
-        child = XMLHelper::getLastChildElement(e, ApplicationDefaults);
-        if (!child) {
-            log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
-            throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
-        }
-        XMLApplication* defapp = new XMLApplication(outer, pp, child);
-        m_appmap[defapp->getId()] = defapp;
+    // Load the default application.
+    child = XMLHelper::getLastChildElement(e, ApplicationDefaults);
+    if (!child) {
+        log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
+        throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
+    }
+    boost::shared_ptr<XMLApplication> defapp(new XMLApplication(outer, pp.get(), child));
+    m_appmap[defapp->getId()] = defapp;
 
-        // Load any overrides.
-        child = XMLHelper::getFirstChildElement(child, ApplicationOverride);
-        while (child) {
-            auto_ptr<XMLApplication> iapp(new XMLApplication(outer, pp, child, defapp));
-            if (m_appmap.count(iapp->getId()))
-                log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
-            else {
-                const char* iappid=iapp->getId();
-                m_appmap[iappid] = iapp.release();
-            }
+    // Load any overrides.
+    child = XMLHelper::getFirstChildElement(child, ApplicationOverride);
+    while (child) {
+        boost::shared_ptr<XMLApplication> iapp(new XMLApplication(outer, pp.get(), child, defapp.get()));
+        if (m_appmap.count(iapp->getId()))
+            log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
+        else
+            m_appmap[iapp->getId()] = iapp;
 
-            child = XMLHelper::getNextSiblingElement(child, ApplicationOverride);
-        }
-
-        // Check for extra AuthTypes to recognize.
-        if (conf.isEnabled(SPConfig::InProcess)) {
-            const PropertySet* inprocs = getPropertySet("InProcess");
-            if (inprocs) {
-                pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
-                if (extraAuthTypes.first) {
-                    string types=extraAuthTypes.second;
-                    unsigned int j_types=0;
-                    for (unsigned int i_types=0;  i_types < types.length();  i_types++) {
-                        if (types.at(i_types) == ' ') {
-                            outer->m_authTypes.insert(types.substr(j_types, i_types - j_types));
-                            j_types = i_types + 1;
-                        }
-                    }
-                    outer->m_authTypes.insert(types.substr(j_types, types.length() - j_types));
-                }
+        child = XMLHelper::getNextSiblingElement(child, ApplicationOverride);
+    }
+
+    // Check for extra AuthTypes to recognize.
+    if (conf.isEnabled(SPConfig::InProcess)) {
+        const PropertySet* inprocs = getPropertySet("InProcess");
+        if (inprocs) {
+            pair<bool,const char*> extraAuthTypes = inprocs->getString("extraAuthTypes");
+            if (extraAuthTypes.first) {
+                string types(extraAuthTypes.second);
+                split(outer->m_authTypes, types, is_space(), algorithm::token_compress_on);
             }
         }
     }
-    catch (exception&) {
-        cleanup();
-        throw;
-    }
-}
-
-XMLConfigImpl::~XMLConfigImpl()
-{
-    cleanup();
-}
-
-void XMLConfigImpl::cleanup()
-{
-    for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());
-    m_appmap.clear();
-#ifndef SHIBSP_LITE
-    delete m_policy;
-    m_policy = nullptr;
-    delete m_tranLog;
-    m_tranLog = nullptr;
-#endif
-    delete m_requestMapper;
-    m_requestMapper = nullptr;
-    if (m_document)
-        m_document->release();
-    m_document = nullptr;
 }
 
 #ifndef SHIBSP_LITE
@@ -2256,7 +2158,7 @@ pair<bool,DOMElement*> XMLConfig::background_load()
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    XMLConfigImpl* impl = new XMLConfigImpl(raw.second, (m_impl==nullptr), this, m_log);
+    scoped_ptr<XMLConfigImpl> impl(new XMLConfigImpl(raw.second, (m_impl==nullptr), this, m_log));
 
     // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
     impl->setDocument(docjanitor.release());
@@ -2265,8 +2167,7 @@ pair<bool,DOMElement*> XMLConfig::background_load()
     if (m_lock)
         m_lock->wrlock();
     SharedLock locker(m_lock, false);
-    delete m_impl;
-    m_impl = impl;
+    m_impl.swap(impl);
 
     return make_pair(false,(DOMElement*)nullptr);
 }
index a7b299a..d3670ec 100644 (file)
@@ -30,6 +30,8 @@
 #include "ServiceProvider.h"
 #include "metadata/MetadataProviderCriteria.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xercesc/framework/Wrapper4InputSource.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xercesc/util/regx/RegularExpression.hpp>
@@ -58,29 +60,12 @@ using namespace xmltooling;
 using namespace std;
 
 namespace shibsp {
-    class SAML_DLLLOCAL DummyCredentialResolver : public CredentialResolver
-    {
-    public:
-        DummyCredentialResolver() {}
-        ~DummyCredentialResolver() {}
-
-        Lockable* lock() {return this;}
-        void unlock() {}
-
-        const Credential* resolve(const CredentialCriteria* criteria=nullptr) const {return nullptr;}
-        vector<const Credential*>::size_type resolve(
-            vector<const Credential*>& results, const CredentialCriteria* criteria=nullptr
-            ) const {return 0;}
-    };
-
     class SHIBSP_DLLLOCAL DynamicMetadataProvider : public saml2md::DynamicMetadataProvider
     {
     public:
         DynamicMetadataProvider(const xercesc::DOMElement* e=nullptr);
 
-        virtual ~DynamicMetadataProvider() {
-            delete m_trust;
-        }
+        virtual ~DynamicMetadataProvider() {}
 
     protected:
         saml2md::EntityDescriptor* resolve(const saml2md::MetadataProvider::Criteria& criteria) const;
@@ -88,10 +73,10 @@ namespace shibsp {
     private:
         bool m_verifyHost,m_ignoreTransport,m_encoded;
         string m_subst, m_match, m_regex;
-        X509TrustEngine* m_trust;
+        boost::scoped_ptr<X509TrustEngine> m_trust;
+        boost::scoped_ptr<CredentialResolver> m_dummyCR;
     };
 
-
     saml2md::MetadataProvider* SHIBSP_DLLLOCAL DynamicMetadataProviderFactory(const DOMElement* const & e)
     {
         return new DynamicMetadataProvider(e);
@@ -103,7 +88,7 @@ namespace shibsp {
     static const XMLCh Regex[] =            UNICODE_LITERAL_5(R,e,g,e,x);
     static const XMLCh Subst[] =            UNICODE_LITERAL_5(S,u,b,s,t);
     static const XMLCh _TrustEngine[] =     UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
-    static const XMLCh type[] =             UNICODE_LITERAL_4(t,y,p,e);
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
     static const XMLCh verifyHost[] =       UNICODE_LITERAL_10(v,e,r,i,f,y,H,o,s,t);
 };
 
@@ -134,16 +119,18 @@ DynamicMetadataProvider::DynamicMetadataProvider(const DOMElement* e)
 
     if (!m_ignoreTransport) {
         child = XMLHelper::getFirstChildElement(e, _TrustEngine);
-        string t = XMLHelper::getAttrString(child, nullptr, type);
+        string t = XMLHelper::getAttrString(child, nullptr, _type);
         if (!t.empty()) {
             TrustEngine* trust = XMLToolingConfig::getConfig().TrustEngineManager.newPlugin(t.c_str(), child);
-            if (!(m_trust = dynamic_cast<X509TrustEngine*>(trust))) {
+            if (!dynamic_cast<X509TrustEngine*>(trust)) {
                 delete trust;
                 throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin.");
             }
+            m_trust.reset(dynamic_cast<X509TrustEngine*>(trust));
+            m_dummyCR.reset(XMLToolingConfig::getConfig().CredentialResolverManager.newPlugin(DUMMY_CREDENTIAL_RESOLVER, nullptr));
         }
 
-        if (!m_trust)
+        if (!m_trust.get() || !m_dummyCR.get())
             throw ConfigurationException("DynamicMetadataProvider requires an X509TrustEngine plugin unless ignoreTransport is true.");
     }
 }
@@ -171,13 +158,10 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
 
     // Possibly transform the input into a different URL to use.
     if (!m_subst.empty()) {
-        string::size_type pos = m_subst.find("$entityID");
-        if (pos != string::npos) {
-            string name2 = m_subst;
-            name2.replace(pos, 9, m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
-            log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
-            name = name2;
-        }
+        string name2 = boost::replace_first_copy(m_subst, "$entityID",
+            m_encoded ? XMLToolingConfig::getConfig().getURLEncoder()->encode(name.c_str()) : name);
+        log.info("transformed location from (%s) to (%s)", name.c_str(), name2.c_str());
+        name = name2;
     }
     else if (!m_match.empty() && !m_regex.empty()) {
         try {
@@ -220,21 +204,19 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
     if (!pch)
         throw IOException("location was not a URL.");
     string scheme(addr.m_endpoint, pch-addr.m_endpoint);
-    SOAPTransport* transport=nullptr;
+    boost::scoped_ptr<SOAPTransport> transport;
     try {
-        transport = XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr);
+        transport.reset(XMLToolingConfig::getConfig().SOAPTransportManager.newPlugin(scheme.c_str(), addr));
     }
     catch (exception& ex) {
         log.error("exception while building transport object to resolve URL: %s", ex.what());
         throw IOException("Unable to resolve entityID with a known transport protocol.");
     }
-    auto_ptr<SOAPTransport> transportwrapper(transport);
 
     // Apply properties as directed.
     transport->setVerifyHost(m_verifyHost);
-    DummyCredentialResolver dcr;
-    if (m_trust && !transport->setTrustEngine(m_trust, &dcr))
-        throw IOException("Unable to install X509TrustEngine into metadata resolver.");
+    if (m_trust.get() && m_dummyCR.get() && !transport->setTrustEngine(m_trust.get(), m_dummyCR.get()))
+        throw IOException("Unable to install X509TrustEngine into transport object.");
 
     Locker credlocker(nullptr, false);
     CredentialResolver* credResolver = nullptr;
@@ -293,14 +275,13 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
     transport->setTimeout(timeout.first ? timeout.second : 20);
     mpc->application.getServiceProvider().setTransportOptions(*transport);
 
-    HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport);
+    HTTPSOAPTransport* http = dynamic_cast<HTTPSOAPTransport*>(transport.get());
     if (http) {
         pair<bool,bool> flag = relyingParty->getBool("chunkedEncoding");
         http->useChunkedEncoding(flag.first && flag.second);
         http->setRequestHeader("Xerces-C", XERCES_FULLVERSIONDOT);
         http->setRequestHeader("XML-Security-C", XSEC_FULLVERSIONDOT);
-        http->setRequestHeader("OpenSAML-C", OPENSAML_FULLVERSIONDOT);
-        http->setRequestHeader("User-Agent", PACKAGE_NAME);
+        http->setRequestHeader("OpenSAML-C", gOpenSAMLDotVersionStr);
         http->setRequestHeader(PACKAGE_NAME, PACKAGE_VERSION);
     }
 
index 73170c2..2e24af0 100644 (file)
@@ -30,7 +30,6 @@
 
 #include <boost/lexical_cast.hpp>
 #include <boost/lambda/bind.hpp>
-#include <boost/lambda/casts.hpp>
 #include <boost/lambda/if.hpp>
 #include <boost/lambda/lambda.hpp>
 #include <xmltooling/AbstractComplexElement.h>
index e7f4754..ad3c525 100644 (file)
@@ -117,7 +117,7 @@ namespace shibsp {
         DDF getmember(const char* path) const;
     
         // debugging
-        void dump(FILE* f=nullptr, int indent=0) const;
+        void dump(std::FILE* f=nullptr, int indent=0) const;
     
         // serialization functions need private access
         friend SHIBSP_API std::ostream& operator<<(std::ostream& os, const DDF& obj);
index 5553dbf..a09bda2 100644 (file)
@@ -68,7 +68,7 @@ namespace shibsp {
 
         Category& m_log;
         const SocketListener* m_listener;
-        auto_ptr<Mutex> m_lock;
+        boost::scoped_ptr<Mutex> m_lock;
         stack<SocketListener::ShibSocket> m_pool;
     };
 
@@ -160,23 +160,22 @@ SocketListener::ShibSocket SocketPool::get()
 
 void SocketPool::put(SocketListener::ShibSocket s)
 {
-    m_lock->lock();
+    Lock lock(m_lock);
     m_pool.push(s);
-    m_lock->unlock();
 }
 
 SocketListener::SocketListener(const DOMElement* e)
-    : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")), m_socketpool(nullptr),
-        m_shutdown(nullptr), m_child_lock(nullptr), m_child_wait(nullptr), m_stackSize(0), m_socket((ShibSocket)0)
+    : m_catchAll(false), log(&Category::getInstance(SHIBSP_LOGCAT".Listener")),
+        m_shutdown(nullptr), m_stackSize(0), m_socket((ShibSocket)0)
 {
     // Are we a client?
     if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
-        m_socketpool=new SocketPool(*log,this);
+        m_socketpool.reset(new SocketPool(*log,this));
     }
     // Are we a server?
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        m_child_lock = Mutex::create();
-        m_child_wait = CondWait::create();
+        m_child_lock.reset(Mutex::create());
+        m_child_wait.reset(CondWait::create());
 
         static const XMLCh stackSize[] = UNICODE_LITERAL_9(s,t,a,c,k,S,i,z,e);
         m_stackSize = XMLHelper::getAttrInt(e, 0, stackSize) * 1024;
@@ -185,9 +184,6 @@ SocketListener::SocketListener(const DOMElement* e)
 
 SocketListener::~SocketListener()
 {
-    delete m_socketpool;
-    delete m_child_wait;
-    delete m_child_lock;
 }
 
 bool SocketListener::init(bool force)
@@ -225,7 +221,7 @@ bool SocketListener::run(bool* shutdown)
     NDC ndc("run");
 #endif
     // Save flag to monitor for shutdown request.
-    m_shutdown=shutdown;
+    m_shutdown = shutdown;
     unsigned long count = 0;
 
     while (!*m_shutdown) {
@@ -261,7 +257,7 @@ bool SocketListener::run(bool* shutdown)
 
                 // We throw away the result because the children manage themselves...
                 try {
-                    new ServerThread(newsock,this,++count);
+                    new ServerThread(newsock, this, ++count);
                 }
                 catch (exception& ex) {
                     log->crit("exception starting new server thread to service incoming request: %s", ex.what());
@@ -279,7 +275,7 @@ bool SocketListener::run(bool* shutdown)
     // Wait for all children to exit.
     m_child_lock->lock();
     while (!m_children.empty())
-        m_child_wait->wait(m_child_lock);
+        m_child_wait->wait(m_child_lock.get());
     m_child_lock->unlock();
 
     return true;
@@ -383,7 +379,7 @@ DDF SocketListener::send(const DDF& in)
             throw ListenerException("Remote call failed with an unparsable exception.");
         }
 
-        auto_ptr<XMLToolingException> wrapper(except);
+        boost::scoped_ptr<XMLToolingException> wrapper(except);
         wrapper->raise();
     }
 
@@ -459,8 +455,8 @@ void ServerThread::run()
 
     // Before starting up, make sure we fully "own" this socket.
     m_listener->m_child_lock->lock();
-    while (m_listener->m_children.find(m_sock)!=m_listener->m_children.end())
-        m_listener->m_child_wait->wait(m_listener->m_child_lock);
+    while (m_listener->m_children.find(m_sock) != m_listener->m_children.end())
+        m_listener->m_child_wait->wait(m_listener->m_child_lock.get());
     m_listener->m_children[m_sock] = m_child;
     m_listener->m_child_lock->unlock();
 
index e6b4fed..5c6e34b 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <shibsp/remoting/ListenerService.h>
 
+#include <boost/scoped_ptr.hpp>
 #include <xercesc/dom/DOM.hpp>
 #include <xmltooling/logging.h>
 #include <xmltooling/util/Threads.h>
@@ -83,14 +84,14 @@ namespace shibsp {
         /// @endcond
 
     private:
-        mutable SocketPool* m_socketpool;
+        boost::scoped_ptr<SocketPool> m_socketpool;
         bool* m_shutdown;
 
         // Manage child threads
         friend class ServerThread;
         std::map<ShibSocket,xmltooling::Thread*> m_children;
-        xmltooling::Mutex* m_child_lock;
-        xmltooling::CondWait* m_child_wait;
+        boost::scoped_ptr<xmltooling::Mutex> m_child_lock;
+        boost::scoped_ptr<xmltooling::CondWait> m_child_wait;
 
         unsigned int m_stackSize;
 
index 5e048d6..0cd15fd 100644 (file)
@@ -29,6 +29,8 @@
 #include "remoting/impl/SocketListener.h"
 #include "util/IPRange.h"
 
+#include <boost/bind.hpp>
+#include <boost/algorithm/string.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/unicode.h>
 #include <xmltooling/util/XMLHelper.h>
@@ -56,6 +58,7 @@
 using namespace shibsp;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -118,24 +121,16 @@ TCPListener::TCPListener(const DOMElement* e)
             m_port = 1600;
     }
 
-    int j = 0;
+    vector<string> rawacls;
     string aclbuf = XMLHelper::getAttrString(e, "127.0.0.1", acl);
-    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) {
-                log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, i-j).c_str(), ex.what());
-            }
-            j = i + 1;
+    boost::split(rawacls, aclbuf, boost::is_space(), algorithm::token_compress_on);
+    for (vector<string>::const_iterator i = rawacls.begin();  i < rawacls.end();  ++i) {
+        try {
+            m_acl.push_back(IPRange::parseCIDRBlock(i->c_str()));
+        }
+        catch (std::exception& ex) {
+            log->error("invalid CIDR block (%s): %s", i->c_str(), ex.what());
         }
-    }
-    try {
-        m_acl.push_back(IPRange::parseCIDRBlock(aclbuf.substr(j, aclbuf.length()-j).c_str()));
-    }
-    catch (exception& ex) {
-        log->error("invalid CIDR block (%s): %s", aclbuf.substr(j, aclbuf.length()-j).c_str(), ex.what());
     }
 
     if (m_acl.empty()) {
@@ -262,11 +257,9 @@ bool TCPListener::accept(ShibSocket& listener, ShibSocket& s) const
     if (s < 0)
 #endif
         return log_error("accept");
-    bool found = false;
-    for (vector<IPRange>::const_iterator acl = m_acl.begin(); !found && acl != m_acl.end(); ++acl) {
-        found = acl->contains((const struct sockaddr*)&addr);
-    }
-    if (!found) {
+
+    static bool (IPRange::* contains)(const struct sockaddr*) const = &IPRange::contains;
+    if (find_if(m_acl.begin(), m_acl.end(), boost::bind(contains, _1, (const struct sockaddr*)&addr)) == m_acl.end()) {
         close(s);
         s = -1;
         log->error("accept() rejected client with invalid address");
index 6da3947..3c63a12 100644 (file)
 #include "internal.h"
 #include "remoting/ddf.h"
 
-#ifdef WIN32
-# define snprintf _snprintf
-#endif
-
 #include <stdexcept>
+#include <boost/lexical_cast.hpp>
 #include <xercesc/dom/DOM.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/XMLToolingConfig.h>
@@ -385,18 +382,14 @@ DDF& DDF::unsafe_string(const char* val)
 
 DDF& DDF::string(long val)
 {
-    char buf[20];
-
-    sprintf(buf,"%ld",val);
-    return string(buf);
+    std::string buf = boost::lexical_cast<std::string>(val);
+    return string(buf.c_str());
 }
 
 DDF& DDF::string(double val)
 {
-    char buf[40];
-
-    snprintf(buf,39,"%f",val);
-    return string(buf);
+    std::string buf = boost::lexical_cast<std::string>(val);
+    return string(buf.c_str());
 }
 
 DDF& DDF::integer(long val)
index c391a3e..7811e42 100644 (file)
@@ -28,6 +28,8 @@
 #include "metadata/MetadataExt.h"
 #include "security/PKIXTrustEngine.h"
 
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/saml2/metadata/ObservableMetadataProvider.h>
@@ -41,6 +43,7 @@ using namespace shibsp;
 using namespace opensaml::saml2md;
 using namespace xmlsignature;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -53,10 +56,7 @@ namespace shibsp {
         virtual ~PKIXTrustEngine() {
             for (map<const ObservableMetadataProvider*,credmap_t>::iterator i=m_credentialMap.begin(); i!=m_credentialMap.end(); ++i) {
                 i->first->removeObserver(this);
-                for (credmap_t::iterator creds = i->second.begin(); creds!=i->second.end(); ++creds)
-                    for_each(creds->second.begin(), creds->second.end(), xmltooling::cleanup<X509Credential>());
             }
-            delete m_credLock;
         }
         
         AbstractPKIXTrustEngine::PKIXValidationInfoIterator* getPKIXValidationInfoIterator(
@@ -66,11 +66,8 @@ namespace shibsp {
         void onEvent(const ObservableMetadataProvider& metadata) const {
             // Destroy credentials we cached from this provider.
             m_credLock->wrlock();
-            credmap_t& cmap = m_credentialMap[&metadata];
-            for (credmap_t::iterator creds = cmap.begin(); creds!=cmap.end(); ++creds)
-                for_each(creds->second.begin(), creds->second.end(), xmltooling::cleanup<X509Credential>());
-            cmap.clear();
-            m_credLock->unlock();
+            SharedLock locker(m_credLock, false);
+            m_credentialMap[&metadata].clear();
         }
 
         const KeyInfoResolver* getKeyInfoResolver() const {
@@ -79,8 +76,8 @@ namespace shibsp {
 
     private:
         friend class SHIBSP_DLLLOCAL MetadataPKIXIterator;
-        mutable RWLock* m_credLock;
-        typedef map< const KeyAuthority*,vector<X509Credential*> > credmap_t;
+        scoped_ptr<RWLock> m_credLock;
+        typedef map< const KeyAuthority*,vector< boost::shared_ptr<X509Credential> > > credmap_t;
         mutable map<const ObservableMetadataProvider*,credmap_t> m_credentialMap;
     };
     
@@ -99,7 +96,6 @@ namespace shibsp {
         virtual ~MetadataPKIXIterator() {
             if (m_caching)
                 m_engine.m_credLock->unlock();
-            for_each(m_ownedCreds.begin(), m_ownedCreds.end(), xmltooling::cleanup<Credential>());
         }
 
         bool next();
@@ -128,7 +124,7 @@ namespace shibsp {
         vector<XMLObject*>::const_iterator m_iter;
         vector<XSECCryptoX509*> m_certs;
         vector<XSECCryptoX509CRL*> m_crls;
-        vector<X509Credential*> m_ownedCreds;
+        vector< boost::shared_ptr<X509Credential> > m_ownedCreds;
     };
 };
 
@@ -162,19 +158,25 @@ MetadataPKIXIterator::MetadataPKIXIterator(
     // While holding read lock, see if this metadata plugin has been seen before.
     m_engine.m_credLock->rdlock();
     m_credCache = m_engine.m_credentialMap.find(observable);
-    if (m_credCache==m_engine.m_credentialMap.end()) {
+    if (m_credCache == m_engine.m_credentialMap.end()) {
 
         // We need to elevate the lock and retry.
         m_engine.m_credLock->unlock();
         m_engine.m_credLock->wrlock();
         m_credCache = m_engine.m_credentialMap.find(observable);
-        if (m_credCache==m_engine.m_credentialMap.end()) {
+        if (m_credCache == m_engine.m_credentialMap.end()) {
+            try {
+                // It's still brand new, so hook it for cache activation.
+                observable->addObserver(&m_engine);
 
-            // It's still brand new, so hook it for cache activation.
-            observable->addObserver(&m_engine);
-
-            // Prime the map reference with an empty credential map.
-            m_credCache = m_engine.m_credentialMap.insert(make_pair(observable,PKIXTrustEngine::credmap_t())).first;
+                // Prime the map reference with an empty credential map.
+                m_credCache = m_engine.m_credentialMap.insert(make_pair(observable,PKIXTrustEngine::credmap_t())).first;
+            }
+            catch (std::exception&) {
+                // The destructor won't run if we throw here, so we need to unlock.
+                m_engine.m_credLock->unlock();
+                throw;
+            }
             
             // Downgrade the lock.
             // We don't have to recheck because we never erase the master map entry entirely, even on changes.
@@ -239,14 +241,14 @@ void MetadataPKIXIterator::populate()
     // Dump anything old.
     m_certs.clear();
     m_crls.clear();
-    for_each(m_ownedCreds.begin(), m_ownedCreds.end(), xmltooling::cleanup<Credential>());
+    m_ownedCreds.clear();
 
     if (m_caching) {
         // We're holding a read lock. Search for "resolved" creds.
         PKIXTrustEngine::credmap_t::iterator cached = m_credCache->second.find(m_current);
-        if (cached!=m_credCache->second.end()) {
+        if (cached != m_credCache->second.end()) {
             // Copy over the information.
-            for (vector<X509Credential*>::const_iterator c=cached->second.begin(); c!=cached->second.end(); ++c) {
+            for (vector< boost::shared_ptr<X509Credential> >::const_iterator c = cached->second.begin(); c != cached->second.end(); ++c) {
                 m_certs.insert(m_certs.end(), (*c)->getEntityCertificateChain().begin(), (*c)->getEntityCertificateChain().end());
                 if ((*c)->getCRL())
                     m_crls.push_back((*c)->getCRL());
@@ -257,17 +259,15 @@ void MetadataPKIXIterator::populate()
 
     // We're either not caching or didn't find the results we need, so we have to resolve them.
     const vector<KeyInfo*>& keyInfos = m_current->getKeyInfos();
-    for (vector<KeyInfo*>::const_iterator k = keyInfos.begin(); k!=keyInfos.end(); ++k) {
-        auto_ptr<Credential> cred (m_engine.getKeyInfoResolver()->resolve(*k, X509Credential::RESOLVE_CERTS | X509Credential::RESOLVE_CRLS));
-        X509Credential* xcred = dynamic_cast<X509Credential*>(cred.get());
-        if (xcred) {
+    for (vector<KeyInfo*>::const_iterator k = keyInfos.begin(); k != keyInfos.end(); ++k) {
+        boost::shared_ptr<Credential> cred(m_engine.getKeyInfoResolver()->resolve(*k, X509Credential::RESOLVE_CERTS | X509Credential::RESOLVE_CRLS));
+        boost::shared_ptr<X509Credential> xcred = boost::dynamic_pointer_cast<X509Credential>(cred);
+        if (xcred)
             m_ownedCreds.push_back(xcred);
-            cred.release();
-        }
     }
 
     // Copy over the new information.
-    for (vector<X509Credential*>::const_iterator c=m_ownedCreds.begin(); c!=m_ownedCreds.end(); ++c) {
+    for (vector< boost::shared_ptr<X509Credential> >::const_iterator c = m_ownedCreds.begin(); c != m_ownedCreds.end(); ++c) {
         m_certs.insert(m_certs.end(), (*c)->getEntityCertificateChain().begin(), (*c)->getEntityCertificateChain().end());
         if ((*c)->getCRL())
             m_crls.push_back((*c)->getCRL());
@@ -277,7 +277,7 @@ void MetadataPKIXIterator::populate()
     if (m_caching) {
         m_engine.m_credLock->unlock();
         m_engine.m_credLock->wrlock();
-        if (m_credCache->second.count(m_current)==0) {
+        if (m_credCache->second.count(m_current) == 0) {
             // Transfer objects into cache.
             m_credCache->second[m_current] = m_ownedCreds;
             m_ownedCreds.clear();
index 27f4dc5..8336474 100644 (file)
 #include "internal.h"
 #include "util/CGIParser.h"
 
+#include <boost/bind.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/io/HTTPRequest.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 namespace {
@@ -107,8 +109,7 @@ CGIParser::CGIParser(const HTTPRequest& request, bool queryOnly)
 
 CGIParser::~CGIParser()
 {
-    for (multimap<string,char*>::iterator i=kvp_map.begin(); i!=kvp_map.end(); i++)
-        free(i->second);
+    for_each(kvp_map.begin(), kvp_map.end(), boost::bind(&free, boost::bind(&multimap<string,char*>::value_type::second, _1)));
 }
 
 void CGIParser::parse(const char* pch)
index 4231132..dc17b35 100644 (file)
@@ -50,9 +50,8 @@ DOMPropertySet::DOMPropertySet() : m_parent(nullptr), m_root(nullptr)
 
 DOMPropertySet::~DOMPropertySet()
 {
-    for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
+    for (map<string,pair<char*,const XMLCh*> >::iterator i = m_map.begin(); i != m_map.end(); ++i)
         XMLString::release(&(i->second.first));
-    for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
 }
 
 const PropertySet* DOMPropertySet::getParent() const
@@ -120,41 +119,41 @@ void DOMPropertySet::load(
     }
     
     // Process non-excluded elements as nested sets.
-    DOMTreeWalker* walker=
+    DOMTreeWalker* walker =
         static_cast<DOMDocumentTraversal*>(
             m_root->getOwnerDocument())->createTreeWalker(const_cast<DOMElement*>(m_root),DOMNodeFilter::SHOW_ELEMENT,filter,false
             );
-    e=static_cast<DOMElement*>(walker->firstChild());
+    e = static_cast<DOMElement*>(walker->firstChild());
     while (e) {
         auto_ptr_char ns(e->getNamespaceURI());
         auto_ptr_char name(e->getLocalName());
         const char* realname=name.get();
         map<string,string>::const_iterator remap;
         if (remapper) {
-            remap=remapper->find(realname);
-            if (remap!=remapper->end()) {
-                log->warn("deprecation - remapping nested property set (%s) to (%s)",realname,remap->second.c_str());
-                realname=remap->second.c_str();
+            remap = remapper->find(realname);
+            if (remap != remapper->end()) {
+                log->warn("deprecation - remapping nested property set (%s) to (%s)", realname, remap->second.c_str());
+                realname = remap->second.c_str();
             }
         }
         string key;
         if (ns.get()) {
-            if (remapper && (remap=remapper->find(ns.get()))!=remapper->end())
-                key=string("{") + remap->second.c_str() + '}' + realname;
+            if (remapper && (remap = remapper->find(ns.get())) != remapper->end())
+                key = string("{") + remap->second.c_str() + '}' + realname;
             else
-                key=string("{") + ns.get() + '}' + realname;
+                key = string("{") + ns.get() + '}' + realname;
         }
         else
-            key=realname;
-        if (m_nested.find(key)!=m_nested.end())
-            log->warn("load() skipping duplicate property set: %s",key.c_str());
+            key = realname;
+        if (m_nested.find(key) != m_nested.end())
+            log->warn("load() skipping duplicate property set: %s", key.c_str());
         else {
-            DOMPropertySet* set=new DOMPropertySet();
-            set->load(e,log,filter,remapper);
-            m_nested[key]=set;
-            log->debug("added nested property set: %s",key.c_str());
+            boost::shared_ptr<DOMPropertySet> newset(new DOMPropertySet());
+            newset->load(e,log,filter,remapper);
+            m_nested[key] = newset;
+            log->debug("added nested property set: %s", key.c_str());
         }
-        e=static_cast<DOMElement*>(walker->nextSibling());
+        e = static_cast<DOMElement*>(walker->nextSibling());
     }
     walker->release();
 }
@@ -250,14 +249,14 @@ void DOMPropertySet::getAll(std::map<std::string,const char*>& properties) const
 
 const PropertySet* DOMPropertySet::getPropertySet(const char* name, const char* ns) const
 {
-    map<string,DOMPropertySet*>::const_iterator i;
+    map<string,boost::shared_ptr<DOMPropertySet>>::const_iterator i;
 
     if (ns)
-        i=m_nested.find(string("{") + ns + '}' + name);
+        i = m_nested.find(string("{") + ns + '}' + name);
     else
-        i=m_nested.find(name);
+        i = m_nested.find(name);
 
-    return (i!=m_nested.end()) ? i->second : (m_parent ? m_parent->getPropertySet(name,ns) : nullptr);
+    return (i != m_nested.end()) ? i->second.get() : (m_parent ? m_parent->getPropertySet(name,ns) : nullptr);
 }
 
 bool DOMPropertySet::setProperty(const char* name, const char* val, const char* ns)
index 4de32c0..5d51a1b 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <shibsp/util/PropertySet.h>
 
+#include <boost/shared_ptr.hpp>
 #include <xmltooling/logging.h>
 
 namespace shibsp {
@@ -84,7 +85,7 @@ namespace shibsp {
         const PropertySet* m_parent;
         const xercesc::DOMElement* m_root;
         std::map<std::string,std::pair<char*,const XMLCh*> > m_map;
-        std::map<std::string,DOMPropertySet*> m_nested;
+        std::map<std::string,boost::shared_ptr<DOMPropertySet>> m_nested;
         std::vector<xmltooling::xstring> m_injected;
     };
 
index 56761ea..726fb55 100644 (file)
@@ -107,7 +107,7 @@ string TemplateParameters::toQueryString() const
     string q;
 
     const URLEncoder* enc = XMLToolingConfig::getConfig().getURLEncoder();
-    for (map<string,string>::const_iterator i=m_map.begin(); i!=m_map.end(); i++)
+    for (map<string,string>::const_iterator i = m_map.begin(); i != m_map.end(); ++i)
         q = q + '&' + i->first + '=' + enc->encode(i->second.c_str());
 
     // Add in the exception content.