Boost changes to rest of project
authorScott Cantor <cantor.2@osu.edu>
Fri, 13 Jan 2012 23:45:55 +0000 (23:45 +0000)
committerScott Cantor <cantor.2@osu.edu>
Fri, 13 Jan 2012 23:45:55 +0000 (23:45 +0000)
adfs/adfs.cpp
apache/mod_apache.cpp
fastcgi/shibresponder.cpp
isapi_shib/isapi_shib.cpp
nsapi_shib/nsapi_shib.cpp
odbc-store/odbc-store.cpp
plugins/GSSAPIAttributeExtractor.cpp
shibsp/util/DOMPropertySet.cpp
util/resolvertest.cpp

index c282eab..e84729e 100644 (file)
@@ -49,6 +49,7 @@
 #include <shibsp/handler/AssertionConsumerService.h>
 #include <shibsp/handler/LogoutInitiator.h>
 #include <shibsp/handler/SessionInitiator.h>
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/logging.h>
 #include <xmltooling/util/DateTime.h>
 #include <xmltooling/util/NDC.h>
@@ -80,6 +81,7 @@ using namespace opensaml;
 using namespace xmltooling::logging;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 #define WSFED_NS "http://schemas.xmlsoap.org/ws/2003/07/secext"
@@ -336,13 +338,13 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
 {
     // We have to know the IdP to function.
     if (entityID.empty() || !checkCompatibility(request, isHandler))
-        return make_pair(false,0L);
+        return make_pair(false, 0L);
 
     string target;
     pair<bool,const char*> prop;
     pair<bool,const char*> acClass;
-    const Handler* ACS=nullptr;
-    const Application& app=request.getApplication();
+    const Handler* ACS = nullptr;
+    const Application& app = request.getApplication();
 
     if (isHandler) {
         prop.second = request.getParameter("acsIndex");
@@ -390,7 +392,7 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
 
     // Since we're not passing by index, we need to fully compute the return URL.
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
-    string ACSloc=request.getHandlerURL(target.c_str());
+    string ACSloc = request.getHandlerURL(target.c_str());
     prop = ACS->getString("Location");
     if (prop.first)
         ACSloc += prop.second;
@@ -442,8 +444,8 @@ pair<bool,long> ADFSSessionInitiator::unwrap(SPRequest& request, DDF& out) const
 void ADFSSessionInitiator::receive(DDF& in, ostream& out)
 {
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) to generate ADFS request", aid ? aid : "(missing)");
@@ -459,14 +461,14 @@ void ADFSSessionInitiator::receive(DDF& in, ostream& out)
     DDFJanitor jout(ret);
 
     // Wrap the outgoing object with a Response facade.
-    auto_ptr<HTTPResponse> http(getResponse(ret));
+    scoped_ptr<HTTPResponse> http(getResponse(ret));
 
     string relayState(in["RelayState"].string() ? in["RelayState"].string() : "");
 
     // Since we're remoted, the result should either be a throw, which we pass on,
     // a false/0 return, which we just return as an empty structure, or a response/redirect,
     // which we capture in the facade and send back.
-    doRequest(*app, nullptr, *http.get(), entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
+    doRequest(*app, nullptr, *http, entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
     if (!ret.isstruct())
         ret.structure();
     ret.addmember("RelayState").unsafe_string(relayState.c_str());
@@ -485,10 +487,10 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
 {
 #ifndef SHIBSP_LITE
     // Use metadata to invoke the SSO service directly.
-    MetadataProvider* m=app.getMetadataProvider();
+    MetadataProvider* m = app.getMetadataProvider();
     Locker locker(m);
     MetadataProviderCriteria mc(app, entityID, &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
-    pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
+    pair<const EntityDescriptor*,const RoleDescriptor*> entity = m->getEntityDescriptor(mc);
     if (!entity.first) {
         m_log.warn("unable to locate metadata for provider (%s)", entityID);
         throw MetadataException("Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", entityID));
@@ -496,7 +498,7 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
     else if (!entity.second) {
         m_log.log(getParent() ? Priority::INFO : Priority::WARN, "unable to locate ADFS-aware identity provider role for provider (%s)", entityID);
         if (getParent())
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         throw MetadataException("Unable to locate ADFS-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
     }
     const EndpointType* ep = EndpointManager<SingleSignOnService>(
@@ -505,13 +507,13 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
     if (!ep) {
         m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
         if (getParent())
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
     }
 
     preserveRelayState(app, httpResponse, relayState);
 
-    auto_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
+    scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
     if (ar_event.get()) {
         ar_event->m_binding = WSFED_NS;
         ar_event->m_protocol = WSFED_NS;
@@ -547,7 +549,7 @@ pair<bool,long> ADFSSessionInitiator::doRequest(
 
     return make_pair(true, httpResponse.sendRedirect(req.c_str()));
 #else
-    return make_pair(false,0L);
+    return make_pair(false, 0L);
 #endif
 }
 
@@ -650,7 +652,7 @@ void ADFSConsumer::implementProtocol(
 
     const saml1::NameIdentifier* saml1name=nullptr;
     const saml1::AuthenticationStatement* saml1statement=nullptr;
-    saml2::NameID* saml2name=nullptr;
+    const saml2::NameID* saml2name=nullptr;
     const saml2::AuthnStatement* saml2statement=nullptr;
     const XMLCh* authMethod=nullptr;
     const XMLCh* authInstant=nullptr;
@@ -749,7 +751,7 @@ void ADFSConsumer::implementProtocol(
     // To complete processing, we need to extract and resolve attributes and then create the session.
 
     // Normalize a SAML 1.x NameIdentifier...
-    auto_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
+    scoped_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
     if (saml1name) {
         nameid->setName(saml1name->getName());
         nameid->setFormat(saml1name->getFormat());
@@ -758,7 +760,7 @@ void ADFSConsumer::implementProtocol(
 
     // The context will handle deleting attributes and new tokens.
     vector<const Assertion*> tokens(1,token);
-    auto_ptr<ResolutionContext> ctx(
+    scoped_ptr<ResolutionContext> ctx(
         resolveAttributes(
             application,
             policy.getIssuerMetadata(),
@@ -793,11 +795,11 @@ void ADFSConsumer::implementProtocol(
         authMethod,
         nullptr,
         &tokens,
-        ctx.get() ? &ctx->getResolvedAttributes() : nullptr
+        ctx ? &ctx->getResolvedAttributes() : nullptr
         );
 
-    auto_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
-    if (login_event.get()) {
+    scoped_ptr<LoginEvent> login_event(newLoginEvent(application, httpRequest));
+    if (login_event) {
         login_event->m_sessionID = session_id.c_str();
         login_event->m_peer = entity;
         login_event->m_protocol = WSFED_NS;
@@ -805,7 +807,7 @@ void ADFSConsumer::implementProtocol(
         login_event->m_saml1AuthnStatement = saml1statement;
         login_event->m_nameID = (saml1name ? nameid.get() : saml2name);
         login_event->m_saml2AuthnStatement = saml2statement;
-        if (ctx.get())
+        if (ctx)
             login_event->m_attributes = &ctx->getResolvedAttributes();
         application.getServiceProvider().getTransactionLog()->write(*login_event);
     }
@@ -825,21 +827,19 @@ pair<bool,long> ADFSLogoutInitiator::run(SPRequest& request, bool isHandler) con
     try {
         session = request.getSession(false, true, false);  // don't cache it and ignore all checks
         if (!session)
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
 
         // We only handle ADFS sessions.
         if (!XMLString::equals(session->getProtocol(), WSFED_NS) || !session->getEntityID()) {
             session->unlock();
-            return make_pair(false,0L);
+            return make_pair(false, 0L);
         }
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error accessing current session: %s", ex.what());
         return make_pair(false,0L);
     }
 
-    session->unlock();
-
     if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
         // When out of process, we run natively.
         return doRequest(request.getApplication(), request, request, session);
@@ -849,7 +849,7 @@ pair<bool,long> ADFSLogoutInitiator::run(SPRequest& request, bool isHandler) con
         session->unlock();
         vector<string> headers(1,"Cookie");
         headers.push_back("User-Agent");
-        DDF out,in = wrap(request,&headers);
+        DDF out,in = wrap(request, &headers);
         DDFJanitor jin(in), jout(out);
         out=request.getServiceProvider().getListenerService()->send(in);
         return unwrap(request, out);
@@ -864,8 +864,8 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
         return LogoutHandler::receive(in, out);
 
     // Find application.
-    const char* aid=in["application_id"].string();
-    const Application* app=aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
+    const char* aid = in["application_id"].string();
+    const Application* app = aid ? SPConfig::getConfig().getServiceProvider()->getApplication(aid) : nullptr;
     if (!app) {
         // Something's horribly wrong.
         m_log.error("couldn't find application (%s) for logout", aid ? aid : "(missing)");
@@ -873,18 +873,18 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
     }
 
     // Unpack the request.
-    auto_ptr<HTTPRequest> req(getRequest(in));
+    scoped_ptr<HTTPRequest> req(getRequest(in));
 
     // Set up a response shim.
     DDF ret(nullptr);
     DDFJanitor jout(ret);
-    auto_ptr<HTTPResponse> resp(getResponse(ret));
+    scoped_ptr<HTTPResponse> resp(getResponse(ret));
 
     Session* session = nullptr;
     try {
-         session = app->getServiceProvider().getSessionCache()->find(*app, *req.get(), nullptr, nullptr);
+         session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error accessing current session: %s", ex.what());
     }
 
@@ -894,12 +894,12 @@ void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
             // Since we're remoted, the result should either be a throw, which we pass on,
             // a false/0 return, which we just return as an empty structure, or a response/redirect,
             // which we capture in the facade and send back.
-            doRequest(*app, *req.get(), *resp.get(), session);
+            doRequest(*app, *req, *resp, session);
         }
         else {
             m_log.error("no issuing entityID found in session");
             session->unlock();
-            app->getServiceProvider().getSessionCache()->remove(*app, *req.get(), resp.get());
+            app->getServiceProvider().getSessionCache()->remove(*app, *req, resp.get());
         }
     }
     out << ret;
@@ -912,27 +912,30 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
     const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session
     ) const
 {
+    Locker sessionLocker(session, false);
+
     // Do back channel notification.
     vector<string> sessions(1, session->getID());
     if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
 #ifndef SHIBSP_LITE
-        auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
-        if (logout_event.get()) {
+        scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_PARTIAL;
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
         }
 #endif
-        session->unlock();
+        sessionLocker.assign();
+        session = nullptr;
         application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
         return sendLogoutPage(application, httpRequest, httpResponse, "partial");
     }
 
 #ifndef SHIBSP_LITE
-    pair<bool,long> ret = make_pair(false,0L);
+    pair<bool,long> ret = make_pair(false, 0L);
 
     try {
         // With a session in hand, we can create a request message, if we can find a compatible endpoint.
-        MetadataProvider* m=application.getMetadataProvider();
+        MetadataProvider* m = application.getMetadataProvider();
         Locker metadataLocker(m);
         MetadataProviderCriteria mc(application, session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
         pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
@@ -958,8 +961,8 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
         }
 
         // Log the request.
-        auto_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
-        if (logout_event.get()) {
+        scoped_ptr<LogoutEvent> logout_event(newLogoutEvent(application, &httpRequest, session));
+        if (logout_event) {
             logout_event->m_logoutType = LogoutEvent::LOGOUT_EVENT_UNKNOWN;
             application.getServiceProvider().getTransactionLog()->write(*logout_event);
         }
@@ -974,7 +977,7 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
         ret.first = true;
 
         if (session) {
-            session->unlock();
+            sessionLocker.assign();
             session = nullptr;
             application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
         }
@@ -983,13 +986,10 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
         // Less noise for IdPs that don't support logout
         m_log.info("unable to issue ADFS logout request: %s", mex.what());
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         m_log.error("error issuing ADFS logout request: %s", ex.what());
     }
 
-    if (session)
-        session->unlock();
-
     return ret;
 #else
     throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
@@ -1039,7 +1039,7 @@ pair<bool,long> ADFSLogout::run(SPRequest& request, bool isHandler) const
         try {
             app.getServiceProvider().getSessionCache()->remove(app, request, &request);
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
         }
     }
index 8f04472..c7f449c 100644 (file)
 
 #undef _XPG4_2
 
+#include <set>
+#include <memory>
+#include <fstream>
+#include <stdexcept>
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+
 // Apache specific header files
 #include <httpd.h>
 #include <http_config.h>
 #include <apr_pools.h>
 #endif
 
-#include <set>
-#include <memory>
-#include <fstream>
-#include <sstream>
-#include <stdexcept>
-
 #include <cstddef>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>            // for getpid()
@@ -89,6 +90,7 @@
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 using xercesc::RegularExpression;
 using xercesc::XMLException;
@@ -632,9 +634,9 @@ extern "C" int shib_check_user(request_rec* r)
 
   ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_check_user(%d): ENTER", (int)getpid());
 
-  ostringstream threadid;
-  threadid << "[" << getpid() << "] shib_check_user" << '\0';
-  xmltooling::NDC ndc(threadid.str().c_str());
+  string threadid("[");
+  threadid += lexical_cast<string>(getpid()) + "] shib_check_user";
+  xmltooling::NDC ndc(threadid.c_str());
 
   try {
     ShibTargetApache sta(r,false,true);
@@ -654,7 +656,7 @@ extern "C" int shib_check_user(request_rec* r)
     // export happened successfully..  this user is ok.
     return OK;
   }
-  catch (exception& e) {
+  catch (std::exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_check_user threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -672,9 +674,9 @@ extern "C" int shib_handler(request_rec* r)
   if (((shib_dir_config*)ap_get_module_config(r->per_dir_config, &mod_shib))->bOff==1)
     return DECLINED;
 
-  ostringstream threadid;
-  threadid << "[" << getpid() << "] shib_handler" << '\0';
-  xmltooling::NDC ndc(threadid.str().c_str());
+  string threadid("[");
+  threadid += lexical_cast<string>(getpid()) + "] shib_handler";
+  xmltooling::NDC ndc(threadid.c_str());
 
 #ifndef SHIB_APACHE_13
   // With 2.x, this handler always runs, though last.
@@ -699,7 +701,7 @@ extern "C" int shib_handler(request_rec* r)
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "doHandler() did not do anything.");
     return SERVER_ERROR;
   }
-  catch (exception& e) {
+  catch (std::exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_handler threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -723,9 +725,9 @@ extern "C" int shib_auth_checker(request_rec* r)
 
   ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO,SH_AP_R(r), "shib_auth_checker(%d): ENTER", (int)getpid());
 
-  ostringstream threadid;
-  threadid << "[" << getpid() << "] shib_auth_checker" << '\0';
-  xmltooling::NDC ndc(threadid.str().c_str());
+  string threadid("[");
+  threadid += lexical_cast<string>(getpid()) + "] shib_auth_checker";
+  xmltooling::NDC ndc(threadid.c_str());
 
   try {
     ShibTargetApache sta(r,false,false);
@@ -737,7 +739,7 @@ extern "C" int shib_auth_checker(request_rec* r)
     // Just let Apache (or some other module) decide what to do.
     return DECLINED;
   }
-  catch (exception& e) {
+  catch (std::exception& e) {
     ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, SH_AP_R(r), "shib_auth_checker threw an exception: %s", e.what());
     return SERVER_ERROR;
   }
@@ -771,7 +773,7 @@ class ApacheRequestMapper : public virtual RequestMapper, public virtual Propert
 {
 public:
     ApacheRequestMapper(const xercesc::DOMElement* e);
-    ~ApacheRequestMapper() { delete m_mapper; delete m_htaccess; delete m_staKey; delete m_propsKey; }
+    ~ApacheRequestMapper() {}
     Lockable* lock() { return m_mapper->lock(); }
     void unlock() { m_staKey->setData(nullptr); m_propsKey->setData(nullptr); m_mapper->unlock(); }
     Settings getSettings(const HTTPRequest& request) const;
@@ -788,10 +790,9 @@ public:
     const xercesc::DOMElement* getElement() const;
 
 private:
-    RequestMapper* m_mapper;
-    ThreadKey* m_staKey;
-    ThreadKey* m_propsKey;
-    AccessControl* m_htaccess;
+    scoped_ptr<RequestMapper> m_mapper;
+    scoped_ptr<ThreadKey> m_staKey,m_propsKey;
+    mutable htAccessControl m_htaccess;
 };
 
 RequestMapper* ApacheRequestMapFactory(const xercesc::DOMElement* const & e)
@@ -799,20 +800,18 @@ RequestMapper* ApacheRequestMapFactory(const xercesc::DOMElement* const & e)
     return new ApacheRequestMapper(e);
 }
 
-ApacheRequestMapper::ApacheRequestMapper(const xercesc::DOMElement* e) : m_mapper(nullptr), m_staKey(nullptr), m_propsKey(nullptr), m_htaccess(nullptr)
+ApacheRequestMapper::ApacheRequestMapper(const xercesc::DOMElement* e)
+    : m_mapper(SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e)),
+        m_staKey(ThreadKey::create(nullptr)), m_propsKey(ThreadKey::create(nullptr))
 {
-    m_mapper=SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e);
-    m_htaccess=new htAccessControl();
-    m_staKey=ThreadKey::create(nullptr);
-    m_propsKey=ThreadKey::create(nullptr);
 }
 
 RequestMapper::Settings ApacheRequestMapper::getSettings(const HTTPRequest& request) const
 {
-    Settings s=m_mapper->getSettings(request);
+    Settings s = m_mapper->getSettings(request);
     m_staKey->setData((void*)dynamic_cast<const ShibTargetApache*>(&request));
     m_propsKey->setData((void*)s.first);
-    return pair<const PropertySet*,AccessControl*>(this,s.second ? s.second : m_htaccess);
+    return pair<const PropertySet*,AccessControl*>(this, s.second ? s.second : &m_htaccess);
 }
 
 pair<bool,bool> ApacheRequestMapper::getBool(const char* name, const char* ns) const
@@ -1007,7 +1006,7 @@ bool htAccessControl::checkAttribute(const SPRequest& request, const Attribute*
 {
     bool caseSensitive = attr->isCaseSensitive();
     const vector<string>& vals = attr->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 (re) {
             auto_arrayptr<XMLCh> trans(fromUTF8(v->c_str()));
             if (re->matches(trans.get())) {
@@ -1054,11 +1053,11 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
             string t(XMLHelper::getAttrString(acldoc ? acldoc->getDocumentElement() : nullptr, nullptr, _type));
             if (t.empty())
                 throw ConfigurationException("Missing type attribute in AccessControl plugin configuration.");
-            auto_ptr<AccessControl> aclplugin(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acldoc->getDocumentElement()));
+            scoped_ptr<AccessControl> aclplugin(SPConfig::getConfig().AccessControlManager.newPlugin(t.c_str(), acldoc->getDocumentElement()));
                        Locker acllock(aclplugin.get());
                        result = aclplugin->authorized(request, session);
                }
-               catch (exception& ex) {
+               catch (std::exception& ex) {
                        request.log(SPRequest::SPError, ex.what());
                }
 
@@ -1254,12 +1253,10 @@ AccessControl::aclresult_t htAccessControl::authorized(const SPRequest& request,
                 }
 
                 try {
-                    auto_ptr<RegularExpression> re;
+                    scoped_ptr<RegularExpression> re;
                     if (regexp) {
-                        delete re.release();
                         auto_arrayptr<XMLCh> trans(fromUTF8(w));
-                        auto_ptr<xercesc::RegularExpression> temp(new xercesc::RegularExpression(trans.get()));
-                        re=temp;
+                        re.reset(new xercesc::RegularExpression(trans.get()));
                     }
                     
                     pair<multimap<string,const Attribute*>::const_iterator,multimap<string,const Attribute*>::const_iterator> attrs2(attrs);
@@ -1420,7 +1417,7 @@ extern "C" void shib_child_init(apr_pool_t* p, server_rec* s)
         if (!g_Config->instantiate(g_szSHIBConfig, true))
             throw runtime_error("unknown error");
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"%s",ex.what());
         ap_log_error(APLOG_MARK,APLOG_CRIT|APLOG_NOERRNO,SH_AP_R(s),"shib_child_init() failed to load configuration");
         exit(1);
index 030d6cb..5783f4b 100644 (file)
@@ -343,8 +343,9 @@ int main(void)
         // Although FastCGI supports writing before reading,
         // many http clients (browsers) don't support it (so
         // the connection deadlocks until a timeout expires!).
-        char* content;
+        char* content = nullptr;
         gstdin(&request, &content);
+        auto_arrayptr<char> wrapper(content);
 
         try {
             xmltooling::NDC ndc("FastCGI shibresponder");
@@ -384,8 +385,6 @@ int main(void)
             print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");
         }
 
-        delete[] content;
-
         // If the output streambufs had non-zero bufsizes and
         // were constructed outside of the accept loop (i.e.
         // their destructor won't be called here), they would
index e8e9d93..40a248c 100644 (file)
 #include <shibsp/ServiceProvider.h>
 
 #include <set>
-#include <sstream>
 #include <fstream>
 #include <stdexcept>
 #include <process.h>
+#include <boost/lexical_cast.hpp>
 #include <xmltooling/unicode.h>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
@@ -56,6 +56,7 @@
 using namespace shibsp;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 // globals
@@ -72,19 +73,15 @@ namespace {
 
     struct site_t {
         site_t(const DOMElement* e)
+            : m_name(XMLHelper::getAttrString(e, "", name)),
+                m_scheme(XMLHelper::getAttrString(e, "", scheme)),
+                m_port(XMLHelper::getAttrString(e, "", port)),
+                m_sslport(XMLHelper::getAttrString(e, "", sslport))
         {
-            auto_ptr_char n(e->getAttributeNS(nullptr,name));
-            auto_ptr_char s(e->getAttributeNS(nullptr,scheme));
-            auto_ptr_char p(e->getAttributeNS(nullptr,port));
-            auto_ptr_char p2(e->getAttributeNS(nullptr,sslport));
-            if (n.get()) m_name=n.get();
-            if (s.get()) m_scheme=s.get();
-            if (p.get()) m_port=p.get();
-            if (p2.get()) m_sslport=p2.get();
             e = XMLHelper::getFirstChildElement(e, Alias);
             while (e) {
                 if (e->hasChildNodes()) {
-                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());
+                    auto_ptr_char alias(e->getTextContent());
                     m_aliases.insert(alias.get());
                 }
                 e = XMLHelper::getNextSiblingElement(e, Alias);
@@ -132,8 +129,8 @@ void _my_invalid_parameter_handler(
 
 extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
 {
-    if (fdwReason==DLL_PROCESS_ATTACH)
-        g_hinstDLL=hinstDLL;
+    if (fdwReason == DLL_PROCESS_ATTACH)
+        g_hinstDLL = hinstDLL;
     return TRUE;
 }
 
@@ -148,7 +145,7 @@ extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
         return FALSE;
     }
 
-    pVer->dwExtensionVersion=HSE_VERSION;
+    pVer->dwExtensionVersion = HSE_VERSION;
     strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);
     return TRUE;
 }
@@ -168,7 +165,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
         return TRUE;
     }
 
-    g_Config=&SPConfig::getConfig();
+    g_Config = &SPConfig::getConfig();
     g_Config->setFeatures(
         SPConfig::Listener |
         SPConfig::Caching |
@@ -178,7 +175,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
         SPConfig::Handlers
         );
     if (!g_Config->init()) {
-        g_Config=nullptr;
+        g_Config = nullptr;
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr,
                 "Filter startup failed during library initialization, check native log for help.");
         return FALSE;
@@ -188,7 +185,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
         if (!g_Config->instantiate(nullptr, true))
             throw runtime_error("unknown error");
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         g_Config->term();
         g_Config=nullptr;
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, ex.what());
@@ -198,16 +195,16 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
     }
 
     // Access implementation-specifics and site mappings.
-    ServiceProvider* sp=g_Config->getServiceProvider();
+    ServiceProvider* sp = g_Config->getServiceProvider();
     Locker locker(sp);
-    const PropertySet* props=sp->getPropertySet("InProcess");
+    const PropertySet* props = sp->getPropertySet("InProcess");
     if (props) {
-        pair<bool,bool> flag=props->getBool("checkSpoofing");
+        pair<bool,bool> flag = props->getBool("checkSpoofing");
         g_checkSpoofing = !flag.first || flag.second;
-        flag=props->getBool("catchAll");
+        flag = props->getBool("catchAll");
         g_catchAll = flag.first && flag.second;
 
-        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
+        pair<bool,const char*> unsetValue = props->getString("unsetHeaderValue");
         if (unsetValue.first)
             g_unsetHeaderValue = unsetValue.second;
         if (g_checkSpoofing) {
@@ -219,9 +216,8 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
                 unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
                 if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
                     _set_invalid_parameter_handler(old);
-                    ostringstream keystr;
-                    keystr << randkey << randkey2 << randkey3 << randkey4;
-                    g_spoofKey = keystr.str();
+                    g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
+                        lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
                 }
                 else {
                     _set_invalid_parameter_handler(old);
@@ -229,7 +225,7 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
                             "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
                     locker.assign();    // pops lock on SP config
                     g_Config->term();
-                    g_Config=nullptr;
+                    g_Config = nullptr;
                     return FALSE;
                 }
             }
@@ -241,18 +237,18 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
             g_bNormalizeRequest = !flag.first || flag.second;
             flag = props->getBool("safeHeaderNames");
             g_bSafeHeaderNames = flag.first && flag.second;
-            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
+            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(), Site);
             while (child) {
-                auto_ptr_char id(child->getAttributeNS(nullptr,id));
-                if (id.get())
-                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
-                child=XMLHelper::getNextSiblingElement(child,Site);
+                string id(XMLHelper::getAttrString(child, "", id));
+                if (!id.empty())
+                    g_Sites.insert(make_pair(id, site_t(child)));
+                child = XMLHelper::getNextSiblingElement(child, Site);
             }
         }
     }
 
-    pVer->dwFilterVersion=HTTP_FILTER_REVISION;
-    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
+    pVer->dwFilterVersion = HTTP_FILTER_REVISION;
+    strncpy(pVer->lpszFilterDesc, "Shibboleth ISAPI Filter", SF_MAX_FILTER_DESC_LEN);
     pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
                    SF_NOTIFY_SECURE_PORT |
                    SF_NOTIFY_NONSECURE_PORT |
@@ -374,8 +370,8 @@ public:
     }
     else {
         m_hostname = var;
-        if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
-            m_hostname=site.m_name;
+        if (site.m_name != m_hostname && site.m_aliases.find(m_hostname) == site.m_aliases.end())
+            m_hostname = site.m_name;
     }
 
     if (!g_spoofKey.empty()) {
@@ -504,7 +500,7 @@ public:
   }
   long sendResponse(istream& in, long status) {
     string hdr = string("Connection: close\r\n");
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+    for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
         hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     const char* codestr="200 OK";
@@ -531,7 +527,7 @@ public:
       "Content-Length: 40\r\n"
       "Expires: Wed, 01 Jan 1997 12:00:00 GMT\r\n"
       "Cache-Control: private,no-store,no-cache,max-age=0\r\n";
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+    for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
         hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (ULONG_PTR)hdr.c_str(), 0);
@@ -562,8 +558,8 @@ public:
 
     while (!m_pfc->GetServerVariable(m_pfc,lpszVariable,s,&size)) {
         // Grumble. Check the error.
-        DWORD e=GetLastError();
-        if (e==ERROR_INSUFFICIENT_BUFFER)
+        DWORD e = GetLastError();
+        if (e == ERROR_INSUFFICIENT_BUFFER)
             s.reserve(size);
         else
             break;
@@ -579,8 +575,8 @@ public:
 
     while (!m_pn->GetHeader(m_pfc,lpszName,s,&size)) {
         // Grumble. Check the error.
-        DWORD e=GetLastError();
-        if (e==ERROR_INSUFFICIENT_BUFFER)
+        DWORD e = GetLastError();
+        if (e == ERROR_INSUFFICIENT_BUFFER)
             s.reserve(size);
         else
             break;
@@ -631,15 +627,14 @@ void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s,
 extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
 {
     // Is this a log notification?
-    if (notificationType==SF_NOTIFY_LOG) {
+    if (notificationType == SF_NOTIFY_LOG) {
         if (pfc->pFilterContext)
-               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);
+               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName = reinterpret_cast<char*>(pfc->pFilterContext);
         return SF_STATUS_REQ_NEXT_NOTIFICATION;
     }
 
     PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;
-    try
-    {
+    try {
         // Determine web site number. This can't really fail, I don't think.
         dynabuf buf(128);
         GetServerVariable(pfc,"INSTANCE_ID",buf,10);
@@ -647,13 +642,13 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
             return WriteClientError(pfc, "Shibboleth Filter failed to obtain INSTANCE_ID server variable.");
 
         // Match site instance to host name, skip if no match.
-        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
-        if (map_i==g_Sites.end())
+        map<string,site_t>::const_iterator map_i = g_Sites.find(static_cast<char*>(buf));
+        if (map_i == g_Sites.end())
             return SF_STATUS_REQ_NEXT_NOTIFICATION;
 
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
+        string threadid("[");
+        threadid += lexical_cast<string>(getpid()) + "] isapi_shib";
+        xmltooling::NDC ndc(threadid.c_str());
 
         ShibTargetIsapiF stf(pfc, pn, map_i->second);
 
@@ -671,26 +666,26 @@ extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificat
         return SF_STATUS_REQ_NEXT_NOTIFICATION;
     }
     catch(bad_alloc) {
-        return WriteClientError(pfc,"Out of Memory");
+        return WriteClientError(pfc, "Out of Memory");
     }
     catch(long e) {
         if (e==ERROR_NO_DATA)
-            return WriteClientError(pfc,"A required variable or header was empty.");
+            return WriteClientError(pfc, "A required variable or header was empty.");
         else
-            return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");
+            return WriteClientError(pfc, "Shibboleth Filter detected unexpected IIS error.");
     }
-    catch (exception& e) {
+    catch (std::exception& e) {
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, e.what());
-        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
+        return WriteClientError(pfc, "Shibboleth Filter caught an exception, check Event Log for details.");
     }
     catch(...) {
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, "Shibboleth Filter threw an unknown exception.");
         if (g_catchAll)
-            return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");
+            return WriteClientError(pfc, "Shibboleth Filter threw an unknown exception.");
         throw;
     }
 
-    return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");
+    return WriteClientError(pfc, "Shibboleth Filter reached unreachable code, save my walrus!");
 }
 
 
@@ -733,7 +728,7 @@ public:
     bool SSL=(ssl=="on" || ssl=="ON");
 
     // Scheme may come from site def or be derived from IIS.
-    m_scheme=site.m_scheme;
+    m_scheme = site.m_scheme;
     if (m_scheme.empty() || !g_bNormalizeRequest)
         m_scheme = SSL ? "https" : "http";
 
@@ -767,8 +762,8 @@ public:
     else {
         // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
         m_hostname=var;
-        if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
-            m_hostname=site.m_name;
+        if (site.m_name != m_hostname && site.m_aliases.find(m_hostname) == site.m_aliases.end())
+            m_hostname = site.m_name;
     }
 
     /*
@@ -813,7 +808,7 @@ public:
 
     setRequestURI(uri.c_str());
   }
-  ~ShibTargetIsapiE() { }
+  ~ShibTargetIsapiE() {}
 
   const char* getScheme() const {
     return m_scheme.c_str();
@@ -860,7 +855,7 @@ public:
   string getHeader(const char* name) const {
     string hdr("HTTP_");
     for (; *name; ++name) {
-        if (*name=='-')
+        if (*name == '-')
             hdr += '_';
         else
             hdr += toupper(*name);
@@ -915,7 +910,7 @@ public:
   }
   long sendResponse(istream& in, long status) {
     string hdr = string("Connection: close\r\n");
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+    for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
         hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     const char* codestr="200 OK";
@@ -942,7 +937,7 @@ public:
       "Content-Length: 40\r\n"
       "Expires: Wed, 01 Jan 1997 12:00:00 GMT\r\n"
       "Cache-Control: private,no-store,no-cache,max-age=0\r\n";
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)
+    for (multimap<string,string>::const_iterator i = m_headers.begin(); i != m_headers.end(); ++i)
         hdr += i->first + ": " + i->second + "\r\n";
     hdr += "\r\n";
     m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());
@@ -951,7 +946,7 @@ public:
     m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
     return HSE_STATUS_SUCCESS;
   }
-  // Decline happens in the POST processor if this isn't the shire url
+  // Decline happens in the POST processor if this isn't the handler url
   // Note that it can also happen with HTAccess, but we don't support that, yet.
   long returnDecline() {
     return WriteClientError(
@@ -1034,9 +1029,9 @@ void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dyna
 extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
 {
     try {
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
+        string threadid("[");
+        threadid += lexical_cast<string>(getpid()) + "] isapi_shib_extension";
+        xmltooling::NDC ndc(threadid.c_str());
 
         // Determine web site number. This can't really fail, I don't think.
         dynabuf buf(128);
@@ -1045,8 +1040,8 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
             return WriteClientError(lpECB, "Shibboleth Extension failed to obtain INSTANCE_ID server variable.");
 
         // Match site instance to host name, skip if no match.
-        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));
-        if (map_i==g_Sites.end())
+        map<string,site_t>::const_iterator map_i = g_Sites.find(static_cast<char*>(buf));
+        if (map_i == g_Sites.end())
             return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check ISAPI mappings in SP configuration).");
 
         ShibTargetIsapiE ste(lpECB, map_i->second);
@@ -1057,22 +1052,22 @@ extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
 
     }
     catch(bad_alloc) {
-        return WriteClientError(lpECB,"Out of Memory");
+        return WriteClientError(lpECB, "Out of Memory");
     }
     catch(long e) {
         if (e==ERROR_NO_DATA)
-            return WriteClientError(lpECB,"A required variable or header was empty.");
+            return WriteClientError(lpECB, "A required variable or header was empty.");
         else
-            return WriteClientError(lpECB,"Server detected unexpected IIS error.");
+            return WriteClientError(lpECB, "Server detected unexpected IIS error.");
     }
-    catch (exception& e) {
+    catch (std::exception& e) {
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, e.what());
-        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
+        return WriteClientError(lpECB, "Shibboleth Extension caught an exception, check Event Log for details.");
     }
     catch(...) {
         LogEvent(nullptr, EVENTLOG_ERROR_TYPE, 2100, nullptr, "Shibboleth Extension threw an unknown exception.");
         if (g_catchAll)
-            return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");
+            return WriteClientError(lpECB, "Shibboleth Extension threw an unknown exception.");
         throw;
     }
 
index 77fa654..75c7f85 100644 (file)
@@ -47,8 +47,9 @@
 #include <set>
 #include <memory>
 #include <fstream>
-#include <sstream>
 #include <stdexcept>
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
@@ -73,6 +74,7 @@ extern "C"
 
 using namespace shibsp;
 using namespace xmltooling;
+using namespace boost;
 using namespace std;
 
 // macros to output text to client
@@ -159,7 +161,7 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
         if (!g_Config->instantiate(pblock_findval("shib-config",pb), true))
             throw runtime_error("unknown error");
     }
-    catch (exception& ex) {
+    catch (std::exception& ex) {
         pblock_nvinsert("error",ex.what(),pb);
         g_Config->term();
         g_Config=nullptr;
@@ -190,9 +192,8 @@ extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request*
                 unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;
                 if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {
                     _set_invalid_parameter_handler(old);
-                    ostringstream keystr;
-                    keystr << randkey << randkey2 << randkey3 << randkey4;
-                    g_spoofKey = keystr.str();
+                    g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
+                        lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
                 }
                 else {
                     _set_invalid_parameter_handler(old);
@@ -481,9 +482,9 @@ int WriteClientError(::Session* sn, Request* rq, char* func, char* msg)
 #define FUNC "shibboleth"
 extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
 {
-  ostringstream threadid;
-  threadid << "[" << getpid() << "] nsapi_shib" << '\0';
-  xmltooling::NDC ndc(threadid.str().c_str());
+  string threadid("[");
+  threadid += lexical_cast<string>(getpid()) + "] nsapi_shib";
+  xmltooling::NDC ndc(threadid.c_str());
 
   try {
     ShibTargetNSAPI stn(pb, sn, rq);
@@ -510,7 +511,7 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
     // this user is ok.
     return REQ_PROCEED;
   }
-  catch (exception& e) {
+  catch (std::exception& e) {
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
     return WriteClientError(sn, rq, FUNC, "Shibboleth module threw an exception, see web server log for error.");
   }
@@ -527,9 +528,9 @@ extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
 #define FUNC "shib_handler"
 extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
 {
-  ostringstream threadid;
-  threadid << "[" << getpid() << "] shib_handler" << '\0';
-  xmltooling::NDC ndc(threadid.str().c_str());
+  string threadid("[");
+  threadid += lexical_cast<string>(getpid()) + "] shib_handler";
+  xmltooling::NDC ndc(threadid.c_str());
 
   try {
     ShibTargetNSAPI stn(pb, sn, rq);
@@ -539,7 +540,7 @@ extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
 
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler did not do anything.");
   }
-  catch (exception& e) {
+  catch (std::exception& e) {
     log_error(LOG_FAILURE,FUNC,sn,rq,const_cast<char*>(e.what()));
     return WriteClientError(sn, rq, FUNC, "Shibboleth handler threw an exception, see web server log for error.");
   }
@@ -556,7 +557,7 @@ class SunRequestMapper : public virtual RequestMapper, public virtual PropertySe
 {
 public:
     SunRequestMapper(const xercesc::DOMElement* e);
-    ~SunRequestMapper() { delete m_mapper; delete m_stKey; delete m_propsKey; }
+    ~SunRequestMapper() {}
     Lockable* lock() { return m_mapper->lock(); }
     void unlock() { m_stKey->setData(nullptr); m_propsKey->setData(nullptr); m_mapper->unlock(); }
     Settings getSettings(const HTTPRequest& request) const;
@@ -573,9 +574,8 @@ public:
     const xercesc::DOMElement* getElement() const;
 
 private:
-    RequestMapper* m_mapper;
-    ThreadKey* m_stKey;
-    ThreadKey* m_propsKey;
+    scoped_ptr<RequestMapper> m_mapper;
+    scoped_ptr<ThreadKey> m_stKey, m_propsKey;
 };
 
 RequestMapper* SunRequestMapFactory(const xercesc::DOMElement* const & e)
@@ -583,11 +583,11 @@ RequestMapper* SunRequestMapFactory(const xercesc::DOMElement* const & e)
     return new SunRequestMapper(e);
 }
 
-SunRequestMapper::SunRequestMapper(const xercesc::DOMElement* e) : m_mapper(nullptr), m_stKey(nullptr), m_propsKey(nullptr)
+SunRequestMapper::SunRequestMapper(const xercesc::DOMElement* e)
+    : m_mapper(SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e)),
+        m_stKey(ThreadKey::create(nullptr)),
+        m_propsKey(ThreadKey::create(nullptr))
 {
-    m_mapper = SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e);
-    m_stKey=ThreadKey::create(nullptr);
-    m_propsKey=ThreadKey::create(nullptr);
 }
 
 RequestMapper::Settings SunRequestMapper::getSettings(const HTTPRequest& request) const
@@ -641,8 +641,14 @@ pair<bool,unsigned int> SunRequestMapper::getUnsignedInt(const char* name, const
     if (stn && !ns && name) {
         // Override int properties.
         const char* param=pblock_findval(name,stn->m_pb);
-        if (param)
-            return pair<bool,unsigned int>(true,strtol(param,nullptr,10));
+        if (param) {
+            try {
+                return pair<bool,unsigned int>(true,lexical_cast<unsigned int>(param));
+            }
+            catch (bad_lexical_cast&) {
+                return pair<bool,unsigned int>(false,0);
+            }
+        }
     }
     return s ? s->getUnsignedInt(name,ns) : pair<bool,unsigned int>(false,0);
 }
index 6f7aede..6460068 100644 (file)
@@ -41,7 +41,6 @@
 # define ODBCSTORE_EXPORTS
 #endif
 
-#include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/logging.h>
 #include <xmltooling/unicode.h>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/StorageService.h>
 #include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
 
 #include <sql.h>
 #include <sqlext.h>
 
+#include <boost/lexical_cast.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
+
 using namespace xmltooling::logging;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 #define PLUGIN_VER_MAJOR 1
@@ -185,7 +190,7 @@ namespace {
 
         SQLHDBC getHDBC();
         SQLHSTMT getHSTMT(SQLHDBC);
-        pair<int,int> getVersion(SQLHDBC);
+        pair<SQLINTEGER,SQLINTEGER> getVersion(SQLHDBC);
         pair<bool,bool> log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor=nullptr);
 
         static void* cleanup_fn(void*); 
@@ -194,7 +199,7 @@ namespace {
         Category& m_log;
         Capabilities m_caps;
         int m_cleanupInterval;
-        CondWait* shutdown_wait;
+        scoped_ptr<CondWait> shutdown_wait;
         Thread* cleanup_thread;
         bool shutdown;
 
@@ -241,61 +246,46 @@ namespace {
         strftime(ret,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
     }
 
-    // make a string safe for SQL command
-    // result to be free'd only if it isn't the input
-    static char *makeSafeSQL(const char *src)
-    {
-       int ns = 0;
-       int nc = 0;
-       char *s;
-    
-       // see if any conversion needed
-       for (s=(char*)src; *s; nc++,s++) if (*s=='\'') ns++;
-       if (ns==0) return ((char*)src);
-    
-       char *safe = new char[(nc+2*ns+1)];
-       for (s=safe; *src; src++) {
-           if (*src=='\'') *s++ = '\'';
-           *s++ = (char)*src;
-       }
-       *s = '\0';
-       return (safe);
-    }
+    class SQLString {
+        const char* m_src;
+        string m_copy;
+    public:
+        SQLString(const char* src) : m_src(src) {
+            if (strchr(src, '\'')) {
+                m_copy = src;
+                replace_all(m_copy, "'", "''");
+            }
+        }
 
-    void freeSafeSQL(char *safe, const char *src)
-    {
-        if (safe!=src)
-            delete[](safe);
-    }
+        operator const char*() const {
+            return tostr();
+        }
+
+        const char* tostr() const {
+            return m_copy.empty() ? m_src : m_copy.c_str();
+        }
+    };
 };
 
 ODBCStorageService::ODBCStorageService(const DOMElement* e) : m_log(Category::getInstance("XMLTooling.StorageService")),
     m_caps(XMLHelper::getAttrInt(e, 255, contextSize), XMLHelper::getAttrInt(e, 255, keySize), XMLHelper::getAttrInt(e, 255, stringSize)),
-    m_cleanupInterval(900), shutdown_wait(nullptr), cleanup_thread(nullptr), shutdown(false), m_henv(SQL_NULL_HANDLE), m_isolation(SQL_TXN_SERIALIZABLE)
+    m_cleanupInterval(XMLHelper::getAttrInt(e, 900, cleanupInterval)),
+    cleanup_thread(nullptr), shutdown(false), m_henv(SQL_NULL_HANDLE), m_isolation(SQL_TXN_SERIALIZABLE)
 {
 #ifdef _DEBUG
     xmltooling::NDC ndc("ODBCStorageService");
 #endif
-
-    const XMLCh* tag=e ? e->getAttributeNS(nullptr,cleanupInterval) : nullptr;
-    if (tag && *tag)
-        m_cleanupInterval = XMLString::parseInt(tag);
-    if (!m_cleanupInterval)
-        m_cleanupInterval = 900;
-
-    auto_ptr_char iso(e ? e->getAttributeNS(nullptr,isolationLevel) : nullptr);
-    if (iso.get() && *iso.get()) {
-        if (!strcmp(iso.get(),"SERIALIZABLE"))
-            m_isolation = SQL_TXN_SERIALIZABLE;
-        else if (!strcmp(iso.get(),"REPEATABLE_READ"))
-            m_isolation = SQL_TXN_REPEATABLE_READ;
-        else if (!strcmp(iso.get(),"READ_COMMITTED"))
-            m_isolation = SQL_TXN_READ_COMMITTED;
-        else if (!strcmp(iso.get(),"READ_UNCOMMITTED"))
-            m_isolation = SQL_TXN_READ_UNCOMMITTED;
-        else
-            throw XMLToolingException("Unknown transaction isolationLevel property.");
-    }
+    string iso(XMLHelper::getAttrString(e, "SERIALIZABLE", isolationLevel));
+    if (iso == "SERIALIZABLE")
+        m_isolation = SQL_TXN_SERIALIZABLE;
+    else if (iso == "REPEATABLE_READ")
+        m_isolation = SQL_TXN_REPEATABLE_READ;
+    else if (iso == "READ_COMMITTED")
+        m_isolation = SQL_TXN_READ_COMMITTED;
+    else if (iso == "READ_UNCOMMITTED")
+        m_isolation = SQL_TXN_READ_UNCOMMITTED;
+    else
+        throw XMLToolingException("Unknown transaction isolationLevel property.");
 
     if (m_henv == SQL_NULL_HANDLE) {
         // Enable connection pooling.
@@ -312,17 +302,17 @@ ODBCStorageService::ODBCStorageService(const DOMElement* e) : m_log(Category::ge
     }
 
     // Grab connection string from the configuration.
-    e = e ? XMLHelper::getFirstChildElement(e,ConnectionString) : nullptr;
-    if (!e || !e->hasChildNodes()) {
+    e = e ? XMLHelper::getFirstChildElement(e, ConnectionString) : nullptr;
+    auto_ptr_char arg(e ? e->getTextContent() : nullptr);
+    if (!arg.get() || !*arg.get()) {
         SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
         throw XMLToolingException("ODBC StorageService requires ConnectionString element in configuration.");
     }
-    auto_ptr_char arg(e->getFirstChild()->getNodeValue());
-    m_connstring=arg.get();
+    m_connstring = arg.get();
 
     // Connect and check version.
     ODBCConn conn(getHDBC());
-    pair<int,int> v=getVersion(conn);
+    pair<SQLINTEGER,SQLINTEGER> v = getVersion(conn);
 
     // Make sure we've got the right version.
     if (v.first != PLUGIN_VER_MAJOR) {
@@ -332,17 +322,17 @@ ODBCStorageService::ODBCStorageService(const DOMElement* e) : m_log(Category::ge
     }
 
     // Load any retry errors to check.
-    e = XMLHelper::getNextSiblingElement(e,RetryOnError);
+    e = XMLHelper::getNextSiblingElement(e, RetryOnError);
     while (e) {
         if (e->hasChildNodes()) {
-            m_retries.push_back(XMLString::parseInt(e->getFirstChild()->getNodeValue()));
+            m_retries.push_back(XMLString::parseInt(e->getTextContent()));
             m_log.info("will retry operations when native ODBC error (%ld) is returned", m_retries.back());
         }
-        e = XMLHelper::getNextSiblingElement(e,RetryOnError);
+        e = XMLHelper::getNextSiblingElement(e, RetryOnError);
     }
 
     // Initialize the cleanup thread
-    shutdown_wait = CondWait::create();
+    shutdown_wait.reset(CondWait::create());
     cleanup_thread = Thread::create(&cleanup_fn, (void*)this);
 }
 
@@ -351,7 +341,6 @@ ODBCStorageService::~ODBCStorageService()
     shutdown = true;
     shutdown_wait->signal();
     cleanup_thread->join(nullptr);
-    delete shutdown_wait;
     if (m_henv != SQL_NULL_HANDLE)
         SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
 }
@@ -411,7 +400,7 @@ SQLHDBC ODBCStorageService::getHDBC()
 SQLHSTMT ODBCStorageService::getHSTMT(SQLHDBC conn)
 {
     SQLHSTMT hstmt;
-    SQLRETURN sr=SQLAllocHandle(SQL_HANDLE_STMT,conn,&hstmt);
+    SQLRETURN sr = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
     if (!SQL_SUCCEEDED(sr)) {
         m_log.error("failed to allocate statement handle");
         log_error(conn, SQL_HANDLE_DBC);
@@ -420,12 +409,12 @@ SQLHSTMT ODBCStorageService::getHSTMT(SQLHDBC conn)
     return hstmt;
 }
 
-pair<int,int> ODBCStorageService::getVersion(SQLHDBC conn)
+pair<SQLINTEGER,SQLINTEGER> ODBCStorageService::getVersion(SQLHDBC conn)
 {
     // Grab the version number from the database.
     SQLHSTMT stmt = getHSTMT(conn);
     
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)"SELECT major,minor FROM version", SQL_NTS);
+    SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)"SELECT major,minor FROM version", SQL_NTS);
     if (!SQL_SUCCEEDED(sr)) {
         m_log.error("failed to read version from database");
         log_error(stmt, SQL_HANDLE_STMT);
@@ -434,11 +423,11 @@ pair<int,int> ODBCStorageService::getVersion(SQLHDBC conn)
 
     SQLINTEGER major;
     SQLINTEGER minor;
-    SQLBindCol(stmt,1,SQL_C_SLONG,&major,0,nullptr);
-    SQLBindCol(stmt,2,SQL_C_SLONG,&minor,0,nullptr);
+    SQLBindCol(stmt, 1, SQL_C_SLONG, &major, 0, nullptr);
+    SQLBindCol(stmt, 2, SQL_C_SLONG, &minor, 0, nullptr);
 
-    if ((sr=SQLFetch(stmt)) != SQL_NO_DATA)
-        return pair<int,int>(major,minor);
+    if ((sr = SQLFetch(stmt)) != SQL_NO_DATA)
+        return make_pair(major,minor);
 
     m_log.error("no rows returned in version query");
     throw IOException("ODBC StorageService failed to read version from database.");
@@ -457,10 +446,6 @@ bool ODBCStorageService::createRow(const char* table, const char* context, const
     ODBCConn conn(getHDBC());
     SQLHSTMT stmt = getHSTMT(conn);
 
-    // Prepare and exectute insert statement.
-    //char *scontext = makeSafeSQL(context);
-    //char *skey = makeSafeSQL(key);
-    //char *svalue = makeSafeSQL(value);
     string q  = string("INSERT INTO ") + table + " VALUES (?,?," + timebuf + ",1,?)";
 
     SQLRETURN sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
@@ -499,17 +484,12 @@ bool ODBCStorageService::createRow(const char* table, const char* context, const
     }
     m_log.debug("SQLBindParam succeeded (value = %s)", value);
     
-    //freeSafeSQL(scontext, context);
-    //freeSafeSQL(skey, key);
-    //freeSafeSQL(svalue, value);
-    //m_log.debug("SQL: %s", q.c_str());
-
     int attempts = 3;
     pair<bool,bool> logres;
     do {
         logres = make_pair(false,false);
         attempts--;
-        sr=SQLExecute(stmt);
+        sr = SQLExecute(stmt);
         if (SQL_SUCCEEDED(sr)) {
             m_log.debug("SQLExecute of insert succeeded");
             return true;
@@ -538,21 +518,18 @@ int ODBCStorageService::readRow(
     // Prepare and exectute select statement.
     char timebuf[32];
     timestampFromTime(time(nullptr), timebuf);
-    char *scontext = makeSafeSQL(context);
-    char *skey = makeSafeSQL(key);
-    ostringstream q;
-    q << "SELECT version";
+    SQLString scontext(context);
+    SQLString skey(key);
+    string q("SELECT version");
     if (pexpiration)
-        q << ",expires";
+        q += ",expires";
     if (pvalue)
-        q << ",CASE version WHEN " << version << " THEN null ELSE value END";
-    q << " FROM " << table << " WHERE context='" << scontext << "' AND id='" << skey << "' AND expires > " << timebuf;
-    freeSafeSQL(scontext, context);
-    freeSafeSQL(skey, key);
+        q = q + ",CASE version WHEN " + lexical_cast<string>(version) + " THEN null ELSE value END";
+    q = q + " FROM " + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "' AND expires > " + timebuf;
     if (m_log.isDebugEnabled())
-        m_log.debug("SQL: %s", q.str().c_str());
+        m_log.debug("SQL: %s", q.c_str());
 
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.str().c_str(), SQL_NTS);
+    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
     if (!SQL_SUCCEEDED(sr)) {
         m_log.error("error searching for (t=%s, c=%s, k=%s)", table, context, key);
         log_error(stmt, SQL_HANDLE_STMT);
@@ -562,11 +539,11 @@ int ODBCStorageService::readRow(
     SQLSMALLINT ver;
     SQL_TIMESTAMP_STRUCT expiration;
 
-    SQLBindCol(stmt,1,SQL_C_SSHORT,&ver,0,nullptr);
+    SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
     if (pexpiration)
-        SQLBindCol(stmt,2,SQL_C_TYPE_TIMESTAMP,&expiration,0,nullptr);
+        SQLBindCol(stmt, 2, SQL_C_TYPE_TIMESTAMP, &expiration, 0, nullptr);
 
-    if ((sr=SQLFetch(stmt)) == SQL_NO_DATA)
+    if ((sr = SQLFetch(stmt)) == SQL_NO_DATA)
         return 0;
 
     if (pexpiration)
@@ -578,7 +555,7 @@ int ODBCStorageService::readRow(
     if (pvalue) {
         SQLLEN len;
         SQLCHAR buf[LONGDATA_BUFLEN];
-        while ((sr=SQLGetData(stmt,pexpiration ? 3 : 2,SQL_C_CHAR,buf,sizeof(buf),&len)) != SQL_NO_DATA) {
+        while ((sr = SQLGetData(stmt, (pexpiration ? 3 : 2), SQL_C_CHAR, buf, sizeof(buf), &len)) != SQL_NO_DATA) {
             if (!SQL_SUCCEEDED(sr)) {
                 m_log.error("error while reading text field from result set");
                 log_error(stmt, SQL_HANDLE_STMT);
@@ -611,34 +588,28 @@ int ODBCStorageService::updateRow(const char *table, const char* context, const
     // First, fetch the current version for later, which also ensures the record still exists.
     char timebuf[32];
     timestampFromTime(time(nullptr), timebuf);
-    char *scontext = makeSafeSQL(context);
-    char *skey = makeSafeSQL(key);
+    SQLString scontext(context);
+    SQLString skey(key);
     string q("SELECT version FROM ");
-    q = q + table + " WHERE context='" + scontext + "' AND id='" + skey + "' AND expires > " + timebuf;
+    q = q + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "' AND expires > " + timebuf;
 
     m_log.debug("SQL: %s", q.c_str());
 
-    sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+    sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
     if (!SQL_SUCCEEDED(sr)) {
-        freeSafeSQL(scontext, context);
-        freeSafeSQL(skey, key);
         m_log.error("error searching for (t=%s, c=%s, k=%s)", table, context, key);
         log_error(stmt, SQL_HANDLE_STMT);
         throw IOException("ODBC StorageService search failed.");
     }
 
     SQLSMALLINT ver;
-    SQLBindCol(stmt,1,SQL_C_SSHORT,&ver,0,nullptr);
-    if ((sr=SQLFetch(stmt)) == SQL_NO_DATA) {
-        freeSafeSQL(scontext, context);
-        freeSafeSQL(skey, key);
+    SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
+    if ((sr = SQLFetch(stmt)) == SQL_NO_DATA) {
         return 0;
     }
 
     // Check version?
     if (version > 0 && version != ver) {
-        freeSafeSQL(scontext, context);
-        freeSafeSQL(skey, key);
         return -1;
     }
 
@@ -658,9 +629,7 @@ int ODBCStorageService::updateRow(const char *table, const char* context, const
         q = q + "expires = " + timebuf;
     }
 
-    q = q + " WHERE context='" + scontext + "' AND id='" + skey + "'";
-    freeSafeSQL(scontext, context);
-    freeSafeSQL(skey, key);
+    q = q + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "'";
 
     sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
     if (!SQL_SUCCEEDED(sr)) {
@@ -689,8 +658,8 @@ int ODBCStorageService::updateRow(const char *table, const char* context, const
     do {
         logres = make_pair(false,false);
         attempts--;
-        sr=SQLExecute(stmt);
-        if (sr==SQL_NO_DATA)
+        sr = SQLExecute(stmt);
+        if (sr == SQL_NO_DATA)
             return 0;   // went missing?
         else if (SQL_SUCCEEDED(sr)) {
             m_log.debug("SQLExecute of update succeeded");
@@ -715,15 +684,13 @@ bool ODBCStorageService::deleteRow(const char *table, const char *context, const
     SQLHSTMT stmt = getHSTMT(conn);
 
     // Prepare and execute delete statement.
-    char *scontext = makeSafeSQL(context);
-    char *skey = makeSafeSQL(key);
-    string q = string("DELETE FROM ") + table + " WHERE context='" + scontext + "' AND id='" + skey + "'";
-    freeSafeSQL(scontext, context);
-    freeSafeSQL(skey, key);
+    SQLString scontext(context);
+    SQLString skey(key);
+    string q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "'";
     m_log.debug("SQL: %s", q.c_str());
 
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-     if (sr==SQL_NO_DATA)
+    SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+     if (sr == SQL_NO_DATA)
         return false;
     else if (!SQL_SUCCEEDED(sr)) {
         m_log.error("error deleting record (t=%s, c=%s, k=%s)", table, context, key);
@@ -741,20 +708,20 @@ void ODBCStorageService::cleanup()
     xmltooling::NDC ndc("cleanup");
 #endif
 
-    Mutex* mutex = Mutex::create();
+    scoped_ptr<Mutex> mutex(Mutex::create());
 
     mutex->lock();
 
     m_log.info("cleanup thread started... running every %d secs", m_cleanupInterval);
 
     while (!shutdown) {
-        shutdown_wait->timedwait(mutex, m_cleanupInterval);
+        shutdown_wait->timedwait(mutex.get(), m_cleanupInterval);
         if (shutdown)
             break;
         try {
             reap(nullptr);
         }
-        catch (exception& ex) {
+        catch (std::exception& ex) {
             m_log.error("cleanup thread swallowed exception: %s", ex.what());
         }
     }
@@ -762,7 +729,6 @@ void ODBCStorageService::cleanup()
     m_log.info("cleanup thread exiting...");
 
     mutex->unlock();
-    delete mutex;
     Thread::exit(nullptr);
 }
 
@@ -796,15 +762,13 @@ void ODBCStorageService::updateContext(const char *table, const char* context, t
     char nowbuf[32];
     timestampFromTime(time(nullptr), nowbuf);
 
-    char *scontext = makeSafeSQL(context);
-    string q("UPDATE ");
-    q = q + table + " SET expires = " + timebuf + " WHERE context='" + scontext + "' AND expires > " + nowbuf;
-    freeSafeSQL(scontext, context);
+    SQLString scontext(context);
+    string q = string("UPDATE ") + table + " SET expires = " + timebuf + " WHERE context='" + scontext.tostr() + "' AND expires > " + nowbuf;
 
     m_log.debug("SQL: %s", q.c_str());
 
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-    if ((sr!=SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
+    SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+    if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
         m_log.error("error updating records (t=%s, c=%s)", table, context ? context : "all");
         log_error(stmt, SQL_HANDLE_STMT);
         throw IOException("ODBC StorageService failed to update context expiration.");
@@ -826,17 +790,16 @@ void ODBCStorageService::reap(const char *table, const char* context)
     timestampFromTime(time(nullptr), nowbuf);
     string q;
     if (context) {
-        char *scontext = makeSafeSQL(context);
-        q = string("DELETE FROM ") + table + " WHERE context='" + scontext + "' AND expires <= " + nowbuf;
-        freeSafeSQL(scontext, context);
+        SQLString scontext(context);
+        q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "' AND expires <= " + nowbuf;
     }
     else {
         q = string("DELETE FROM ") + table + " WHERE expires <= " + nowbuf;
     }
     m_log.debug("SQL: %s", q.c_str());
 
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-    if ((sr!=SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
+    SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+    if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
         m_log.error("error expiring records (t=%s, c=%s)", table, context ? context : "all");
         log_error(stmt, SQL_HANDLE_STMT);
         throw IOException("ODBC StorageService failed to purge expired records.");
@@ -854,13 +817,12 @@ void ODBCStorageService::deleteContext(const char *table, const char* context)
     SQLHSTMT stmt = getHSTMT(conn);
 
     // Prepare and execute delete statement.
-    char *scontext = makeSafeSQL(context);
-    string q = string("DELETE FROM ") + table + " WHERE context='" + scontext + "'";
-    freeSafeSQL(scontext, context);
+    SQLString scontext(context);
+    string q = string("DELETE FROM ") + table + " WHERE context='" + scontext.tostr() + "'";
     m_log.debug("SQL: %s", q.c_str());
 
-    SQLRETURN sr=SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-    if ((sr!=SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
+    SQLRETURN sr = SQLExecDirect(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
+    if ((sr != SQL_NO_DATA) && !SQL_SUCCEEDED(sr)) {
         m_log.error("error deleting context (t=%s, c=%s)", table, context);
         log_error(stmt, SQL_HANDLE_STMT);
         throw IOException("ODBC StorageService failed to delete context.");
index 0ed36bc..33ae337 100644 (file)
@@ -47,6 +47,8 @@
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/Base64.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/algorithm/string.hpp>
 
 #ifdef SHIBSP_HAVE_GSSGNU
 # include <gss.h>
@@ -62,6 +64,7 @@ using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 namespace shibsp {
@@ -109,7 +112,7 @@ namespace shibsp {
     {
     public:
         GSSAPIExtractor(const DOMElement* e)
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.GSSAPI")), m_impl(nullptr) {
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AttributeExtractor.GSSAPI")) {
             background_load();
         }
         ~GSSAPIExtractor() {
@@ -133,7 +136,7 @@ namespace shibsp {
         pair<bool,DOMElement*> background_load();
 
     private:
-        GSSAPIExtractorImpl* m_impl;
+        scoped_ptr<GSSAPIExtractorImpl> m_impl;
     };
 
 #if defined (_MSC_VER)
@@ -204,25 +207,15 @@ GSSAPIExtractorImpl::GSSAPIExtractorImpl(const DOMElement* e, Category& log)
         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.ids.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());
         }
 
         decl.authenticated = XMLHelper::getAttrBool(child, true, _authenticated);
@@ -307,18 +300,22 @@ void GSSAPIExtractorImpl::extractAttributes(
                 m_log.warn("ignoring unscoped value");
             }
         }
-        if (!scoped->getValues().empty())
-            attributes.push_back(scoped.release());
+        if (!scoped->getValues().empty()) {
+            attributes.push_back(scoped.get());
+            scoped.release();
+        }
     }
     else if (rule->second.binary) {
         auto_ptr<BinaryAttribute> binary(new BinaryAttribute(rule->second.ids));
         binary->getValues() = values;
-        attributes.push_back(binary.release());
+        attributes.push_back(binary.get());
+        binary.release();
     }
     else {
         auto_ptr<SimpleAttribute> simple(new SimpleAttribute(rule->second.ids));
         simple->getValues() = values;
-        attributes.push_back(simple.release());
+        attributes.push_back(simple.get());
+        simple.release();
     }
 }
 
@@ -414,7 +411,7 @@ pair<bool,DOMElement*> GSSAPIExtractor::background_load()
     // If we own it, wrap it.
     XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : nullptr);
 
-    GSSAPIExtractorImpl* impl = new GSSAPIExtractorImpl(raw.second, m_log);
+    scoped_ptr<GSSAPIExtractorImpl> impl(new GSSAPIExtractorImpl(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());
@@ -423,8 +420,7 @@ pair<bool,DOMElement*> GSSAPIExtractor::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 7ec1f49..3ee7a94 100644 (file)
 #include "util/DOMPropertySet.h"
 
 #include <algorithm>
+#include <boost/lexical_cast.hpp>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLConstants.h>
 
 using namespace shibsp;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 PropertySet::PropertySet()
@@ -209,15 +211,21 @@ pair<bool,const XMLCh*> DOMPropertySet::getXMLString(const char* name, const cha
 
 pair<bool,unsigned int> DOMPropertySet::getUnsignedInt(const char* name, const char* ns) const
 {
-    map<string,pair<char*,const XMLCh*> >::const_iterator i;
+    map< string,pair<char*,const XMLCh*> >::const_iterator i;
 
     if (ns)
         i=m_map.find(string("{") + ns + '}' + name);
     else
         i=m_map.find(name);
 
-    if (i!=m_map.end())
-        return pair<bool,unsigned int>(true,strtol(i->second.first,nullptr,10));
+    if (i!=m_map.end()) {
+        try {
+            return pair<bool,unsigned int>(true,lexical_cast<unsigned int>(i->second.first));
+        }
+        catch (bad_lexical_cast&) {
+            return pair<bool,unsigned int>(false,0);
+        }
+    }
     else if (m_parent)
         return m_parent->getUnsignedInt(name,ns);
     return pair<bool,unsigned int>(false,0);
index ad3b032..26b2325 100644 (file)
 #include <saml/saml2/core/Assertions.h>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
-#include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/ParserPool.h>
 #include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <boost/scoped_ptr.hpp>
+#include <boost/iterator/indirect_iterator.hpp>
 
 using namespace shibsp;
 using namespace opensaml::saml2md;
@@ -60,6 +62,7 @@ using namespace opensaml;
 using namespace xmltooling::logging;
 using namespace xmltooling;
 using namespace xercesc;
+using namespace boost;
 using namespace std;
 
 #if defined (_MSC_VER)
@@ -190,46 +193,40 @@ int main(int argc,char* argv[])
     }
 
     try {
-        ResolutionContext* ctx;
+        scoped_ptr<ResolutionContext> ctx;
 
         if (n_param) {
             auto_ptr_XMLCh issuer(i_param);
             auto_ptr_XMLCh name(n_param);
             auto_ptr_XMLCh format(f_param);
 
-            MetadataProvider* m=app->getMetadataProvider();
-            xmltooling::Locker mlocker(m);
+            MetadataProvider* m = app->getMetadataProvider();
+            Locker mlocker(m);
             MetadataProviderCriteria mc(*app, i_param, &IDPSSODescriptor::ELEMENT_QNAME, protocol);
-            pair<const EntityDescriptor*,const RoleDescriptor*> site=m->getEntityDescriptor(mc);
+            pair<const EntityDescriptor*,const RoleDescriptor*> site = m->getEntityDescriptor(mc);
             if (!site.first)
                 throw MetadataException("Unable to locate metadata for IdP ($1).", params(1,i_param));
 
             // Build NameID(s).
-            auto_ptr<saml2::NameID> v2name(saml2::NameIDBuilder::buildNameID());
+            scoped_ptr<saml1::NameIdentifier> v1name;
+            scoped_ptr<saml2::NameID> v2name(saml2::NameIDBuilder::buildNameID());
             v2name->setName(name.get());
             v2name->setFormat(format.get());
-            saml1::NameIdentifier* v1name = nullptr;
             if (!XMLString::equals(protocol, samlconstants::SAML20P_NS)) {
-                v1name = saml1::NameIdentifierBuilder::buildNameIdentifier();
+                v1name.reset(saml1::NameIdentifierBuilder::buildNameIdentifier());
                 v1name->setName(name.get());
                 v1name->setFormat(format.get());
                 v1name->setNameQualifier(issuer.get());
             }
 
             ResolverTest rt(nullptr, a_param);
-            try {
-                ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name.get(), nullptr, nullptr, nullptr);
-            }
-            catch (...) {
-                delete v1name;
-                throw;
-            }
+            ctx.reset(rt.resolveAttributes(*app, site.second, protocol, v1name.get(), v2name.get(), nullptr, nullptr, nullptr));
         }
         else {
             // Try and load assertion from stdin.
             DOMDocument* doc = XMLToolingConfig::getConfig().getParser().parse(cin);
             XercesJanitor<DOMDocument> docjan(doc);
-            auto_ptr<XMLObject> token(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
+            scoped_ptr<XMLObject> token(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
             docjan.release();
 
             // Get the issuer and protocol and NameIDs.
@@ -267,15 +264,15 @@ int main(int argc,char* argv[])
                 throw FatalProfileException("Unknown assertion type.");
             }
 
-            auto_ptr<saml2::NameID> nameidwrapper(v1name ? v2name : nullptr);
+            scoped_ptr<saml2::NameID> nameidwrapper(v1name ? v2name : nullptr);
 
             if (!issuer)
                 throw FatalProfileException("Unable to determine issuer.");
 
-            MetadataProvider* m=app->getMetadataProvider();
-            xmltooling::Locker mlocker(m);
+            MetadataProvider* m = app->getMetadataProvider();
+            Locker mlocker(m);
             MetadataProviderCriteria mc(*app, issuer, &IDPSSODescriptor::ELEMENT_QNAME, protocol);
-            pair<const EntityDescriptor*,const RoleDescriptor*> site=m->getEntityDescriptor(mc);
+            pair<const EntityDescriptor*,const RoleDescriptor*> site = m->getEntityDescriptor(mc);
             if (!site.first) {
                 auto_ptr_char temp(issuer);
                 throw MetadataException("Unable to locate metadata for IdP ($1).", params(1,temp.get()));
@@ -283,15 +280,15 @@ int main(int argc,char* argv[])
             
             vector<const Assertion*> tokens(1, dynamic_cast<Assertion*>(token.get()));
             ResolverTest rt(nullptr, a_param);
-            ctx = rt.resolveAttributes(*app, site.second, protocol, v1name, v2name, nullptr, nullptr, &tokens);
+            ctx.reset(rt.resolveAttributes(*app, site.second, protocol, v1name, v2name, nullptr, nullptr, &tokens));
         }
 
-        auto_ptr<ResolutionContext> wrapper(ctx);
-        for (vector<Attribute*>::const_iterator a = ctx->getResolvedAttributes().begin(); a != ctx->getResolvedAttributes().end(); ++a) {
-            for (vector<string>::const_iterator s = (*a)->getAliases().begin(); s != (*a)->getAliases().end(); ++s) {
+        for (indirect_iterator<vector<Attribute*>::const_iterator> a = make_indirect_iterator(ctx->getResolvedAttributes().begin());
+                a != make_indirect_iterator(ctx->getResolvedAttributes().end()); ++a) {
+            for (vector<string>::const_iterator s = a->getAliases().begin(); s != a->getAliases().end(); ++s) {
                 cout << *s << ": ";
-                for (vector<string>::const_iterator v = (*a)->getSerializedValues().begin(); v != (*a)->getSerializedValues().end(); ++v) {
-                    if (v != (*a)->getSerializedValues().begin())
+                for (vector<string>::const_iterator v = a->getSerializedValues().begin(); v != a->getSerializedValues().end(); ++v) {
+                    if (v != a->getSerializedValues().begin())
                         cout << ';';
                     cout << *v;
                 }
@@ -300,7 +297,7 @@ int main(int argc,char* argv[])
         }
         cout << endl;
     }
-    catch(exception& ex) {
+    catch (std::exception& ex) {
         log.error(ex.what());
         sp->unlock();
         conf.term();