[cpp-sp] branch main updated: Initial purge of code from next-gen SP.

Scott Cantor cantor.2 at osu.edu
Tue Oct 29 14:40:38 UTC 2024


This is an automated email from the git hooks/post-receive script.

scantor pushed a commit to branch main
in repository cpp-sp.

View the commit online:
http://git.shibboleth.net/view/?p=cpp-sp.git;a=commit;h=d1c57b40a17cf48c820d10ee1e730e5a798d1788

The following commit(s) were added to refs/heads/main by this push:
     new d1c57b40 Initial purge of code from next-gen SP.
d1c57b40 is described below

commit d1c57b40a17cf48c820d10ee1e730e5a798d1788
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Tue Oct 29 10:40:33 2024 -0400

    Initial purge of code from next-gen SP.
---
 Makefile.am                       |   20 -
 adfs/Makefile.am                  |   47 --
 adfs/adfs.cpp                     | 1118 -------------------------------------
 adfs/adfs.rc                      |  109 ----
 adfs/resource.h                   |   35 --
 configure.ac                      |  228 +-------
 doc/api/.gitkeep                  |    0
 doxygen.am                        |  186 ------
 doxygen.cfg                       |  255 ---------
 isapi_shib/isapi_shib.cpp         | 1105 ------------------------------------
 isapi_shib/isapi_shib.rc          |   96 ----
 isapi_shib/resource.h             |   35 --
 m4/ax_cxx_compile_stdcxx.m4       | 1071 +++++++++++++++++++++++++++++++++++
 m4/doxygen.m4                     |  537 ------------------
 memcache-store/Makefile.am        |   29 -
 memcache-store/memcache-store.cpp |  630 ---------------------
 memcache-store/memcache-store.rc  |   97 ----
 memcache-store/resource.h         |   34 --
 nsapi_shib/Makefile.am            |   23 -
 nsapi_shib/nsapi_shib.cpp         |  696 -----------------------
 nsapi_shib/nsapi_shib.rc          |  101 ----
 nsapi_shib/resource.h             |   35 --
 odbc-store/Makefile.am            |   30 -
 odbc-store/odbc-store.cpp         |  897 -----------------------------
 odbc-store/odbc-store.rc          |   97 ----
 odbc-store/resource.h             |   34 --
 selinux/Makefile.am               |   25 -
 selinux/shibshar.fc.in            |    4 -
 selinux/shibshar.te               |   33 --
 shibboleth.spec.in                |  646 ---------------------
 shibd/Makefile.am                 |   22 -
 shibd/resource.h                  |   35 --
 shibd/shibd.cpp                   |  484 ----------------
 shibd/shibd.rc                    |  101 ----
 shibd/shibd_win32.cpp             |  550 ------------------
 35 files changed, 1076 insertions(+), 8369 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index cb551cfb..49de98a3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,10 +1,6 @@
 AUTOMAKE_OPTIONS = foreign dist-zip dist-bzip2
 ACLOCAL_AMFLAGS = -I m4
 
-include doxygen.am
-
-MOSTLYCLEANFILES = $(DX_CLEANFILES)
-
 WANT_SUBDIRS = @WANT_SUBDIRS@
 
 SUBDIRS = $(WANT_SUBDIRS)
@@ -14,30 +10,14 @@ DIST_SUBDIRS = \
 	schemas \
 	configs \
 	shibsp \
-	shibd \
-	adfs \
-	plugins \
 	util \
 	apache \
-	nsapi_shib \
 	fastcgi \
-	odbc-store \
-	memcache-store \
-	selinux \
 	unittests
 
-if DX_COND_doc
-all-local: doxygen-doc
-else
-all-local:
-endif
-
 pkgconfig_DATA = shibsp.pc shibsp-lite.pc
 
-GENFILES = @PACKAGE_NAME at .spec
-
 EXTRA_DIST = $(DX_CONFIG) \
-	isapi_shib \
 	iis7_shib \
 	Projects \
 	pkgconfig-workarounds \
diff --git a/adfs/Makefile.am b/adfs/Makefile.am
deleted file mode 100644
index 17c94162..00000000
--- a/adfs/Makefile.am
+++ /dev/null
@@ -1,47 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = adfs.la adfs-lite.la
-
-adfs_la_CXXFLAGS = \
-	$(AM_CXXFLAGS) \
-	$(BOOST_CPPFLAGS) \
-	$(PTHREAD_CFLAGS) \
-	$(log4cpp_CFLAGS) \
-	$(log4shib_CFLAGS) \
-	$(opensaml_CFLAGS) \
-	$(xmltooling_CFLAGS) \
-	$(xerces_CFLAGS)
-adfs_la_LIBADD = \
-	$(top_builddir)/shibsp/libshibsp.la \
-	$(PTHREAD_LIBS) \
-	$(log4cpp_LIBS) \
-	$(log4shib_LIBS) \
-	$(opensaml_LIBS) \
-	$(xmltooling_LIBS) \
-	$(xerces_LIBS)
-adfs_la_LDFLAGS = -module -avoid-version
-
-adfs_la_SOURCES = \
-	adfs.cpp
-
-adfs_lite_la_SOURCES = \
-	adfs.cpp
-
-adfs_lite_la_CXXFLAGS = -DSHIBSP_LITE \
-	$(AM_CXXFLAGS) \
-	$(BOOST_CPPFLAGS) \
-	$(PTHREAD_CFLAGS) \
-	$(log4cpp_CFLAGS) \
-	$(log4shib_CFLAGS) \
-	$(xmltooling_lite_CFLAGS) \
-	$(xerces_CFLAGS)
-adfs_lite_la_LIBADD = $(top_builddir)/shibsp/libshibsp-lite.la \
-	$(PTHREAD_LIBS) \
-	$(log4cpp_LIBS) \
-	$(log4shib_LIBS) \
-	$(xmltooling_lite_LIBS) \
-	$(xerces_LIBS)
-adfs_lite_la_LDFLAGS = -module -avoid-version
-
-EXTRA_DIST = resource.h adfs.rc
diff --git a/adfs/adfs.cpp b/adfs/adfs.cpp
deleted file mode 100644
index a3f7ee52..00000000
--- a/adfs/adfs.cpp
+++ /dev/null
@@ -1,1118 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/**
- * adfs.cpp
- *
- * ADFSv1 extension library.
- */
-
-#if defined (_MSC_VER) || defined(__BORLANDC__)
-# include "config_win32.h"
-#else
-# include "config.h"
-#endif
-
-#ifdef WIN32
-# define _CRT_NONSTDC_NO_DEPRECATE 1
-# define _CRT_SECURE_NO_DEPRECATE 1
-# define ADFS_EXPORTS __declspec(dllexport)
-#else
-# define ADFS_EXPORTS
-#endif
-
-#include <shibsp/base.h>
-#include <shibsp/exceptions.h>
-#include <shibsp/Application.h>
-#include <shibsp/ServiceProvider.h>
-#include <shibsp/SessionCache.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/SPRequest.h>
-#include <shibsp/TransactionLog.h>
-#include <shibsp/handler/AssertionConsumerService.h>
-#include <shibsp/handler/LogoutInitiator.h>
-#include <shibsp/handler/SessionInitiator.h>
-#include <xmltooling/logging.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/URLEncoder.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <memory>
-
-#ifndef SHIBSP_LITE
-# include <shibsp/attribute/resolver/ResolutionContext.h>
-# include <shibsp/metadata/MetadataProviderCriteria.h>
-# include <saml/SAMLConfig.h>
-# include <saml/exceptions.h>
-# include <saml/binding/SecurityPolicy.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/EndpointManager.h>
-# include <xmltooling/XMLToolingConfig.h>
-# include <xmltooling/impl/AnyElement.h>
-# include <xmltooling/util/ParserPool.h>
-# include <xmltooling/validation/ValidatorSuite.h>
-using namespace opensaml::saml2md;
-# ifndef min
-#  define min(a,b)            (((a) < (b)) ? (a) : (b))
-# endif
-#endif
-using namespace shibsp;
-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"
-#define WSTRUST_NS "http://schemas.xmlsoap.org/ws/2005/02/trust"
-
-namespace {
-
-#ifndef SHIBSP_LITE
-    class SHIBSP_DLLLOCAL ADFSDecoder : public MessageDecoder
-    {
-        auto_ptr_XMLCh m_ns;
-    public:
-        ADFSDecoder() : m_ns(WSTRUST_NS) {}
-        virtual ~ADFSDecoder() {}
-
-        const XMLCh* getProtocolFamily() const {
-            return m_ns.get();
-        }
-
-        XMLObject* decode(
-            string& relayState,
-            const GenericRequest& genericRequest,
-            const GenericResponse* genericResponse,
-            SecurityPolicy& policy
-        ) const;
-
-    protected:
-        void extractMessageDetails(
-            const XMLObject& message, const GenericRequest& req, const XMLCh* protocol, SecurityPolicy& policy
-            ) const {
-        }
-    };
-
-    MessageDecoder* ADFSDecoderFactory(const DOMElement* const &, bool)
-    {
-        return new ADFSDecoder();
-    }
-#endif
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
-
-    class SHIBSP_DLLLOCAL ADFSSessionInitiator : public SessionInitiator, public AbstractHandler, public RemotedHandler
-    {
-    public:
-        ADFSSessionInitiator(const DOMElement* e, const char* appId)
-            : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".SessionInitiator.ADFS"), nullptr, this), m_appId(appId), m_binding(WSFED_NS) {
-            SPConfig::getConfig().deprecation().warn("ADFS SessionInitiator");
-
-            // If Location isn't set, defer address registration until the setParent call.
-            pair<bool,const char*> loc = getString("Location");
-            if (loc.first) {
-                string address = m_appId + loc.second + "::run::ADFSSI";
-                setAddress(address.c_str());
-            }
-        }
-        virtual ~ADFSSessionInitiator() {}
-
-        void setParent(const PropertySet* parent) {
-            DOMPropertySet::setParent(parent);
-            pair<bool,const char*> loc = getString("Location");
-            if (loc.first) {
-                string address = m_appId + loc.second + "::run::ADFSSI";
-                setAddress(address.c_str());
-            }
-            else {
-                m_log.warn("no Location property in ADFS SessionInitiator (or parent), can't register as remoted handler");
-            }
-        }
-
-        void receive(DDF& in, ostream& out);
-        pair<bool,long> unwrap(SPRequest& request, DDF& out) const;
-        pair<bool,long> run(SPRequest& request, string& entityID, bool isHandler=true) const;
-
-        const XMLCh* getProtocolFamily() const {
-            return m_binding.get();
-        }
-
-#ifndef SHIBSP_LITE
-        void generateMetadata(saml2md::SPSSODescriptor& role, const char* handlerURL) const {
-            doGenerateMetadata(role, handlerURL);
-        }
-#endif
-
-    private:
-        pair<bool,long> doRequest(
-            const Application& application,
-            const HTTPRequest* httpRequest,
-            HTTPResponse& httpResponse,
-            const char* entityID,
-            const char* acsLocation,
-            const char* authnContextClassRef,
-            string& relayState
-            ) const;
-        string m_appId;
-        auto_ptr_XMLCh m_binding;
-    };
-
-    class SHIBSP_DLLLOCAL ADFSConsumer : public shibsp::AssertionConsumerService
-    {
-        auto_ptr_XMLCh m_protocol;
-    public:
-        ADFSConsumer(const DOMElement* e, const char* appId, bool deprecationSupport)
-            : shibsp::AssertionConsumerService(e, appId, Category::getInstance(SHIBSP_LOGCAT ".SSO.ADFS"), nullptr, nullptr, deprecationSupport),
-                m_protocol(WSFED_NS) {
-            SPConfig::getConfig().deprecation().warn("ADFS AssertionConsumerService");
-        }
-        virtual ~ADFSConsumer() {}
-
-#ifndef SHIBSP_LITE
-        void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
-            AssertionConsumerService::generateMetadata(role, handlerURL);
-            role.addSupport(m_protocol.get());
-        }
-
-    private:
-        const char* getProfile() const {
-            return WSFED_NS;
-        }
-
-        void implementProtocol(
-            const Application& application,
-            const HTTPRequest& httpRequest,
-            HTTPResponse& httpResponse,
-            SecurityPolicy& policy,
-            const PropertySet*,
-            const XMLObject& xmlObject
-            ) const;
-#else
-        const XMLCh* getProtocolFamily() const {
-            return m_protocol.get();
-        }
-#endif
-    };
-
-    class SHIBSP_DLLLOCAL ADFSLogoutInitiator : public AbstractHandler, public LogoutInitiator
-    {
-    public:
-        ADFSLogoutInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".LogoutInitiator.ADFS")), m_appId(appId), m_binding(WSFED_NS) {
-
-            SPConfig::getConfig().deprecation().warn("ADFS LogoutInitiator");
-
-            // If Location isn't set, defer address registration until the setParent call.
-            pair<bool,const char*> loc = getString("Location");
-            if (loc.first) {
-                string address = m_appId + loc.second + "::run::ADFSLI";
-                setAddress(address.c_str());
-            }
-        }
-        virtual ~ADFSLogoutInitiator() {}
-
-        void setParent(const PropertySet* parent) {
-            DOMPropertySet::setParent(parent);
-            pair<bool,const char*> loc = getString("Location");
-            if (loc.first) {
-                string address = m_appId + loc.second + "::run::ADFSLI";
-                setAddress(address.c_str());
-            }
-            else {
-                m_log.warn("no Location property in ADFS LogoutInitiator (or parent), can't register as remoted handler");
-            }
-        }
-
-        void receive(DDF& in, ostream& out);
-        pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
-        const XMLCh* getProtocolFamily() const {
-            return m_binding.get();
-        }
-
-    private:
-        pair<bool,long> doRequest(const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, Session* session) const;
-
-        string m_appId;
-        auto_ptr_XMLCh m_binding;
-    };
-
-    class SHIBSP_DLLLOCAL ADFSLogout : public AbstractHandler, public LogoutHandler
-    {
-    public:
-        ADFSLogout(const DOMElement* e, const char* appId, bool deprecationSupport)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT ".Logout.ADFS")), m_login(e, appId, deprecationSupport) {
-
-            SPConfig::getConfig().deprecation().warn("ADFS Logout handler");
-
-            m_initiator = false;
-#ifndef SHIBSP_LITE
-            m_preserve.push_back("wreply");
-            string address = string(appId) + getString("Location").second + "::run::ADFSLO";
-            setAddress(address.c_str());
-#endif
-        }
-        virtual ~ADFSLogout() {}
-
-        pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
-
-#ifndef SHIBSP_LITE
-        void generateMetadata(SPSSODescriptor& role, const char* handlerURL) const {
-            m_login.generateMetadata(role, handlerURL);
-            const char* loc = getString("Location").second;
-            string hurl(handlerURL);
-            if (*loc != '/')
-                hurl += '/';
-            hurl += loc;
-            auto_ptr_XMLCh widen(hurl.c_str());
-            SingleLogoutService* ep = SingleLogoutServiceBuilder::buildSingleLogoutService();
-            ep->setLocation(widen.get());
-            ep->setBinding(m_login.getProtocolFamily());
-            role.getSingleLogoutServices().push_back(ep);
-        }
-
-        const char* getType() const {
-            return m_login.getType();
-        }
-#endif
-        const XMLCh* getProtocolFamily() const {
-            return m_login.getProtocolFamily();
-        }
-
-    private:
-        ADFSConsumer m_login;
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    SessionInitiator* ADFSSessionInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
-    {
-        return new ADFSSessionInitiator(p.first, p.second);
-    }
-
-    Handler* ADFSLogoutFactory(const pair<const DOMElement*,const char*>& p, bool deprecationSupport)
-    {
-        return new ADFSLogout(p.first, p.second, deprecationSupport);
-    }
-
-    Handler* ADFSLogoutInitiatorFactory(const pair<const DOMElement*,const char*>& p, bool)
-    {
-        return new ADFSLogoutInitiator(p.first, p.second);
-    }
-
-    const XMLCh RequestedSecurityToken[] =      UNICODE_LITERAL_22(R,e,q,u,e,s,t,e,d,S,e,c,u,r,i,t,y,T,o,k,e,n);
-    const XMLCh RequestSecurityTokenResponse[] =UNICODE_LITERAL_28(R,e,q,u,e,s,t,S,e,c,u,r,i,t,y,T,o,k,e,n,R,e,s,p,o,n,s,e);
-};
-
-extern "C" int ADFS_EXPORTS xmltooling_extension_init(void*)
-{
-    SPConfig& conf=SPConfig::getConfig();
-    conf.SessionInitiatorManager.registerFactory("ADFS", ADFSSessionInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory("ADFS", ADFSLogoutInitiatorFactory);
-    conf.AssertionConsumerServiceManager.registerFactory("ADFS", ADFSLogoutFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(WSFED_NS, ADFSLogoutFactory);
-#ifndef SHIBSP_LITE
-    SAMLConfig::getConfig().MessageDecoderManager.registerFactory(WSFED_NS, ADFSDecoderFactory);
-    XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestedSecurityToken"), new AnyElementBuilder());
-    XMLObjectBuilder::registerBuilder(xmltooling::QName(WSTRUST_NS,"RequestSecurityTokenResponse"), new AnyElementBuilder());
-#endif
-    return 0;
-}
-
-extern "C" void ADFS_EXPORTS xmltooling_extension_term()
-{
-    /* should get unregistered during normal shutdown...
-    SPConfig& conf=SPConfig::getConfig();
-    conf.SessionInitiatorManager.deregisterFactory("ADFS");
-    conf.LogoutInitiatorManager.deregisterFactory("ADFS");
-    conf.AssertionConsumerServiceManager.deregisterFactory("ADFS");
-    conf.AssertionConsumerServiceManager.deregisterFactory(WSFED_NS);
-#ifndef SHIBSP_LITE
-    SAMLConfig::getConfig().MessageDecoderManager.deregisterFactory(WSFED_NS);
-#endif
-    */
-}
-
-pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID, bool isHandler) const
-{
-    // We have to know the IdP to function.
-    if (entityID.empty() || !checkCompatibility(request, isHandler))
-        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();
-
-    if (isHandler) {
-        prop.second = request.getParameter("acsIndex");
-        if (prop.second && *prop.second) {
-            SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
-            ACS = app.getAssertionConsumerServiceByIndex(atoi(prop.second));
-            if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
-        }
-
-        prop = getString("target", request);
-        if (prop.first)
-            target = prop.second;
-
-        // Since we're passing the ACS by value, we need to compute the return URL,
-        // so we'll need the target resource for real.
-        recoverRelayState(app, request, request, target, false);
-        app.limitRedirect(request, target.c_str());
-
-        // Default is to allow externally supplied settings.
-        pair<bool,bool> externalInput = getBool("externalInput");
-        unsigned int settingMask = HANDLER_PROPERTY_MAP | HANDLER_PROPERTY_FIXED;
-        if (!externalInput.first || externalInput.second)
-            settingMask |= HANDLER_PROPERTY_REQUEST;
-
-        acClass = getString("authnContextClassRef", request, settingMask);
-    }
-    else {
-        // Check for a hardwired target value in the map or handler.
-        prop = getString("target", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
-        if (prop.first)
-            target = prop.second;
-        else
-            target = request.getRequestURL();
-
-        acClass = getString("authnContextClassRef", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
-    }
-
-    if (!ACS) {
-        pair<bool,unsigned int> index = getUnsignedInt("acsIndex", request, HANDLER_PROPERTY_MAP|HANDLER_PROPERTY_FIXED);
-        if (index.first) {
-            SPConfig::getConfig().deprecation().warn("Use of acsIndex when specifying response endpoint");
-            ACS = app.getAssertionConsumerServiceByIndex(index.second);
-        }
-    }
-
-    // Validate the ACS for use with this protocol.
-    if (!ACS || !XMLString::equals(getProtocolFamily(), ACS->getProtocolFamily())) {
-        if (ACS)
-            request.log(SPRequest::SPWarn, "invalid acsIndex property, or non-ADFS ACS, using default ADFS ACS");
-        ACS = app.getAssertionConsumerServiceByProtocol(getProtocolFamily());
-        if (!ACS)
-            throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration.");
-    }
-
-    // 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());
-    prop = ACS->getString("Location");
-    if (prop.first)
-        ACSloc += prop.second;
-
-    if (isHandler) {
-        // We may already have RelayState set if we looped back here,
-        // but we've turned it back into a resource by this point, so if there's
-        // a target on the URL, reset to that value.
-        prop.second = request.getParameter("target");
-        if (prop.second && *prop.second)
-            target = prop.second;
-    }
-
-    m_log.debug("attempting to initiate session using ADFS with provider (%s)", entityID.c_str());
-
-    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        // Out of process means the POST data via the request can be exposed directly to the private method.
-        // The method will handle POST preservation if necessary *before* issuing the response, but only if
-        // it dispatches to an IdP.
-        return doRequest(app, &request, request, entityID.c_str(), ACSloc.c_str(), (acClass.first ? acClass.second : nullptr), target);
-    }
-
-    // Remote the call.
-    DDF out,in = DDF(m_address.c_str()).structure();
-    DDFJanitor jin(in), jout(out);
-    in.addmember("application_id").string(app.getId());
-    in.addmember("entity_id").string(entityID.c_str());
-    in.addmember("acsLocation").string(ACSloc.c_str());
-    if (!target.empty())
-        in.addmember("RelayState").unsafe_string(target.c_str());
-    if (acClass.first)
-        in.addmember("authnContextClassRef").string(acClass.second);
-
-    // Remote the processing.
-    out = send(request, in);
-    return unwrap(request, out);
-}
-
-pair<bool,long> ADFSSessionInitiator::unwrap(SPRequest& request, DDF& out) const
-{
-    // See if there's any response to send back.
-    if (!out["redirect"].isnull() || !out["response"].isnull()) {
-        // If so, we're responsible for handling the POST data, probably by dropping a cookie.
-        preservePostData(request.getApplication(), request, request, out["RelayState"].string());
-    }
-    return RemotedHandler::unwrap(request, out);
-}
-
-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;
-    if (!app) {
-        // Something's horribly wrong.
-        m_log.error("couldn't find application (%s) to generate ADFS request", aid ? aid : "(missing)");
-        throw ConfigurationException("Unable to locate application for new session, deleted?");
-    }
-
-    const char* entityID = in["entity_id"].string();
-    const char* acsLocation = in["acsLocation"].string();
-    if (!entityID || !acsLocation)
-        throw ConfigurationException("No entityID or acsLocation parameter supplied to remoted SessionInitiator.");
-
-    DDF ret(nullptr);
-    DDFJanitor jout(ret);
-
-    // Wrap the outgoing object with a Response facade.
-    scoped_ptr<HTTPResponse> http(getResponse(*app, 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, entityID, acsLocation, in["authnContextClassRef"].string(), relayState);
-    if (!ret.isstruct())
-        ret.structure();
-    ret.addmember("RelayState").unsafe_string(relayState.c_str());
-    out << ret;
-}
-
-pair<bool,long> ADFSSessionInitiator::doRequest(
-    const Application& app,
-    const HTTPRequest* httpRequest,
-    HTTPResponse& httpResponse,
-    const char* entityID,
-    const char* acsLocation,
-    const char* authnContextClassRef,
-    string& relayState
-    ) const
-{
-#ifndef SHIBSP_LITE
-    // Use metadata to invoke the SSO service directly.
-    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);
-    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));
-    }
-    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);
-        throw MetadataException("Unable to locate ADFS-aware identity provider role for provider ($entityID)", namedparams(1, "entityID", entityID));
-    }
-    const EndpointType* ep = EndpointManager<SingleSignOnService>(
-        dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleSignOnServices()
-        ).getByBinding(m_binding.get());
-    if (!ep) {
-        m_log.warn("unable to locate compatible SSO service for provider (%s)", entityID);
-        if (getParent())
-            return make_pair(false, 0L);
-        throw MetadataException("Unable to locate compatible SSO service for provider ($entityID)", namedparams(1, "entityID", entityID));
-    }
-
-    preserveRelayState(app, httpResponse, relayState);
-
-    scoped_ptr<AuthnRequestEvent> ar_event(newAuthnRequestEvent(app, httpRequest));
-    if (ar_event.get()) {
-        ar_event->m_binding = WSFED_NS;
-        ar_event->m_protocol = WSFED_NS;
-        ar_event->m_peer = entity.first;
-        app.getServiceProvider().getTransactionLog()->write(*ar_event);
-    }
-
-    // UTC timestamp
-    time_t epoch=time(nullptr);
-#ifndef HAVE_GMTIME_R
-    struct tm* ptime=gmtime(&epoch);
-#else
-    struct tm res;
-    struct tm* ptime=gmtime_r(&epoch,&res);
-#endif
-    char timebuf[32];
-    strftime(timebuf,32,"%Y-%m-%dT%H:%M:%SZ",ptime);
-
-    auto_ptr_char dest(ep->getLocation());
-    const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
-
-    const PropertySet* relyingParty = app.getRelyingParty(entity.first);
-
-    string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "wa=wsignin1.0&wreply=" + urlenc->encode(acsLocation) +
-        "&wct=" + urlenc->encode(timebuf) + "&wtrealm=" + urlenc->encode(relyingParty->getString("entityID").second);
-    if (!authnContextClassRef) {
-        pair<bool,const char*> rpClass = relyingParty->getString("authnContextClassRef");
-        if (rpClass.first)
-            authnContextClassRef = rpClass.second;
-    }
-    if (authnContextClassRef)
-        req += "&wauth=" + urlenc->encode(authnContextClassRef);
-    if (!relayState.empty())
-        req += "&wctx=" + urlenc->encode(relayState.c_str());
-
-    if (httpRequest) {
-        // If the request object is available, we're responsible for the POST data.
-        preservePostData(app, *httpRequest, httpResponse, relayState.c_str());
-    }
-
-    return make_pair(true, httpResponse.sendRedirect(req.c_str()));
-#else
-    return make_pair(false, 0L);
-#endif
-}
-
-#ifndef SHIBSP_LITE
-
-XMLObject* ADFSDecoder::decode(
-    string& relayState, const GenericRequest& genericRequest, const GenericResponse*, SecurityPolicy& policy
-    ) const
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("decode");
-#endif
-    Category& log = Category::getInstance(SHIBSP_LOGCAT ".MessageDecoder.ADFS");
-
-    log.debug("validating input");
-    const HTTPRequest* httpRequest=dynamic_cast<const HTTPRequest*>(&genericRequest);
-    if (!httpRequest)
-        throw BindingException("Unable to cast request object to HTTPRequest type.");
-    if (strcmp(httpRequest->getMethod(),"POST"))
-        throw BindingException("Invalid HTTP method ($1).", params(1, httpRequest->getMethod()));
-    const char* param = httpRequest->getParameter("wa");
-    if (!param || strcmp(param, "wsignin1.0"))
-        throw BindingException("Missing or invalid wa parameter (should be wsignin1.0).");
-    param = httpRequest->getParameter("wctx");
-    if (param)
-        relayState = param;
-
-    param = httpRequest->getParameter("wresult");
-    if (!param)
-        throw BindingException("Request missing wresult parameter.");
-
-    log.debug("decoded ADFS response:\n%s", param);
-
-    // Parse and bind the document into an XMLObject.
-    istringstream is(param);
-    DOMDocument* doc = (policy.getValidating() ? XMLToolingConfig::getConfig().getValidatingParser()
-        : XMLToolingConfig::getConfig().getParser()).parse(is);
-    XercesJanitor<DOMDocument> janitor(doc);
-    auto_ptr<XMLObject> xmlObject(XMLObjectBuilder::buildOneFromElement(doc->getDocumentElement(), true));
-    janitor.release();
-
-    if (!XMLString::equals(xmlObject->getElementQName().getLocalPart(), RequestSecurityTokenResponse)) {
-    	log.error("unrecognized root element on message: %s", xmlObject->getElementQName().toString().c_str());
-        throw BindingException("Decoded message was not of the appropriate type.");
-    }
-
-    SchemaValidators.validate(xmlObject.get());
-
-    // Skip policy step here, there's no security in the wrapper.
-    // policy.evaluate(*xmlObject.get(), &genericRequest);
-
-    return xmlObject.release();
-}
-
-void ADFSConsumer::implementProtocol(
-    const Application& application,
-    const HTTPRequest& httpRequest,
-    HTTPResponse& httpResponse,
-    SecurityPolicy& policy,
-    const PropertySet*,
-    const XMLObject& xmlObject
-    ) const
-{
-    // Implementation of ADFS profile.
-    m_log.debug("processing message against ADFS Passive Requester profile");
-
-    // With ADFS, all the security comes from the assertion, which is two levels down in the message.
-
-    const ElementProxy* response = dynamic_cast<const ElementProxy*>(&xmlObject);
-    if (!response || !response->hasChildren())
-        throw FatalProfileException("Incoming message was not of the proper type or contains no security token.");
-
-    const Assertion* token = nullptr;
-    for (vector<XMLObject*>::const_iterator xo = response->getUnknownXMLObjects().begin(); xo != response->getUnknownXMLObjects().end(); ++xo) {
-    	// Look for the RequestedSecurityToken element.
-    	if (XMLString::equals((*xo)->getElementQName().getLocalPart(), RequestedSecurityToken)) {
-    	    response = dynamic_cast<const ElementProxy*>(*xo);
-    	    if (!response || !response->hasChildren())
-    	        throw FatalProfileException("Token wrapper element did not contain a security token.");
-    	    token = dynamic_cast<const Assertion*>(response->getUnknownXMLObjects().front());
-    	    if (!token || !token->getSignature())
-    	        throw FatalProfileException("Incoming message did not contain a signed SAML assertion.");
-    	    break;
-    	}
-    }
-
-    // Extract message and issuer details from assertion.
-    extractMessageDetails(*token, m_protocol.get(), policy);
-
-    // Populate recipient as audience.
-    const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : nullptr;
-    policy.getAudiences().push_back(application.getRelyingParty(entity)->getXMLString("entityID").second);
-
-    // Run the policy over the assertion. Handles replay, freshness, and
-    // signature verification, assuming the relevant rules are configured,
-    // along with condition enforcement.
-    policy.evaluate(*token, &httpRequest);
-
-    // If no security is in place now, we kick it.
-    if (!policy.isAuthenticated())
-        throw SecurityPolicyException("Unable to establish security of incoming assertion.");
-
-    const saml1::NameIdentifier* saml1name=nullptr;
-    const saml1::AuthenticationStatement* saml1statement=nullptr;
-    const saml2::NameID* saml2name=nullptr;
-    const saml2::AuthnStatement* saml2statement=nullptr;
-    const XMLCh* authMethod=nullptr;
-    const XMLCh* authInstant=nullptr;
-    time_t now = time(nullptr), sessionExp = 0;
-    const PropertySet* sessionProps = application.getPropertySet("Sessions");
-
-    const saml1::Assertion* saml1token = dynamic_cast<const saml1::Assertion*>(token);
-    if (saml1token) {
-        // Now do profile validation to ensure we can use it for SSO.
-        if (!saml1token->getConditions() || !saml1token->getConditions()->getNotBefore() || !saml1token->getConditions()->getNotOnOrAfter())
-            throw FatalProfileException("Assertion did not contain time conditions.");
-        else if (saml1token->getAuthenticationStatements().empty())
-            throw FatalProfileException("Assertion did not contain an authentication statement.");
-
-        // authnskew allows rejection of SSO if AuthnInstant is too old.
-        pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
-
-        saml1statement = saml1token->getAuthenticationStatements().front();
-        if (saml1statement->getAuthenticationInstant()) {
-            if (saml1statement->getAuthenticationInstantEpoch() - XMLToolingConfig::getConfig().clock_skew_secs > now) {
-                throw FatalProfileException("The login time at your identity provider was future-dated.");
-            }
-            else if (authnskew.first && authnskew.second && saml1statement->getAuthenticationInstantEpoch() <= now &&
-                    (now - saml1statement->getAuthenticationInstantEpoch() > authnskew.second)) {
-                throw FatalProfileException("The gap between now and the time you logged into your identity provider exceeds the allowed limit.");
-            }
-        }
-        else if (authnskew.first && authnskew.second) {
-            throw FatalProfileException("Your identity provider did not supply a time of login, violating local policy.");
-        }
-
-        // Address checking.
-        saml1::SubjectLocality* locality = saml1statement->getSubjectLocality();
-        if (locality && locality->getIPAddress()) {
-            auto_ptr_char ip(locality->getIPAddress());
-            checkAddress(application, httpRequest, ip.get());
-        }
-
-        saml1name = saml1statement->getSubject()->getNameIdentifier();
-        authMethod = saml1statement->getAuthenticationMethod();
-        if (saml1statement->getAuthenticationInstant())
-            authInstant = saml1statement->getAuthenticationInstant()->getRawData();
-
-        // Session expiration.
-        pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
-        if (!lifetime.first || lifetime.second == 0)
-            lifetime.second = 28800;
-        sessionExp = now + lifetime.second;
-    }
-    else {
-        const saml2::Assertion* saml2token = dynamic_cast<const saml2::Assertion*>(token);
-        if (!saml2token)
-            throw FatalProfileException("Incoming message did not contain a recognized type of SAML assertion.");
-
-        // Now do profile validation to ensure we can use it for SSO.
-        if (!saml2token->getConditions() || !saml2token->getConditions()->getNotBefore() || !saml2token->getConditions()->getNotOnOrAfter())
-            throw FatalProfileException("Assertion did not contain time conditions.");
-        else if (saml2token->getAuthnStatements().empty())
-            throw FatalProfileException("Assertion did not contain an authentication statement.");
-
-        // authnskew allows rejection of SSO if AuthnInstant is too old.
-        pair<bool,unsigned int> authnskew = sessionProps ? sessionProps->getUnsignedInt("maxTimeSinceAuthn") : pair<bool,unsigned int>(false,0);
-
-        saml2statement = saml2token->getAuthnStatements().front();
-        if (authnskew.first && authnskew.second &&
-                saml2statement->getAuthnInstant() && (now - saml2statement->getAuthnInstantEpoch() > authnskew.second))
-            throw FatalProfileException("The gap between now and the time you logged into your identity provider exceeds the limit.");
-
-        // Address checking.
-        saml2::SubjectLocality* locality = saml2statement->getSubjectLocality();
-        if (locality && locality->getAddress()) {
-            auto_ptr_char ip(locality->getAddress());
-            checkAddress(application, httpRequest, ip.get());
-        }
-
-        saml2name = saml2token->getSubject() ? saml2token->getSubject()->getNameID() : nullptr;
-        if (saml2statement->getAuthnContext() && saml2statement->getAuthnContext()->getAuthnContextClassRef())
-            authMethod = saml2statement->getAuthnContext()->getAuthnContextClassRef()->getReference();
-        if (saml2statement->getAuthnInstant())
-            authInstant = saml2statement->getAuthnInstant()->getRawData();
-
-        // Session expiration for SAML 2.0 is jointly IdP- and SP-driven.
-        sessionExp = saml2statement->getSessionNotOnOrAfter() ? saml2statement->getSessionNotOnOrAfterEpoch() : 0;
-        pair<bool,unsigned int> lifetime = sessionProps ? sessionProps->getUnsignedInt("lifetime") : pair<bool,unsigned int>(true,28800);
-        if (!lifetime.first || lifetime.second == 0)
-            lifetime.second = 28800;
-        if (sessionExp == 0)
-            sessionExp = now + lifetime.second;     // IdP says nothing, calulate based on SP.
-        else
-            sessionExp = min(sessionExp, now + lifetime.second);    // Use the lowest.
-    }
-
-    m_log.debug("ADFS profile processing completed successfully");
-
-    // We've successfully "accepted" the SSO token.
-    // To complete processing, we need to extract and resolve attributes and then create the session.
-
-    // Normalize a SAML 1.x NameIdentifier...
-    scoped_ptr<saml2::NameID> nameid(saml1name ? saml2::NameIDBuilder::buildNameID() : nullptr);
-    if (saml1name) {
-        nameid->setName(saml1name->getName());
-        nameid->setFormat(saml1name->getFormat());
-        nameid->setNameQualifier(saml1name->getNameQualifier());
-    }
-
-    // The context will handle deleting attributes and new tokens.
-    vector<const Assertion*> tokens(1,token);
-    scoped_ptr<ResolutionContext> ctx(
-        resolveAttributes(
-            application,
-            &httpRequest,
-            policy.getIssuerMetadata(),
-            m_protocol.get(),
-            nullptr,
-            saml1name,
-            saml1statement,
-            (saml1name ? nameid.get() : saml2name),
-            saml2statement,
-            authMethod,
-            nullptr,
-            &tokens
-            )
-        );
-
-    if (ctx.get()) {
-        // Copy over any new tokens, but leave them in the context for cleanup.
-        tokens.insert(tokens.end(), ctx->getResolvedAssertions().begin(), ctx->getResolvedAssertions().end());
-    }
-
-    string session_id;
-    application.getServiceProvider().getSessionCache()->insert(
-        session_id,
-        application,
-        httpRequest,
-        httpResponse,
-        sessionExp,
-        entity,
-        m_protocol.get(),
-        (saml1name ? nameid.get() : saml2name),
-        authInstant,
-        nullptr,
-        authMethod,
-        nullptr,
-        &tokens,
-        ctx ? &ctx->getResolvedAttributes() : nullptr
-        );
-
-    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;
-        login_event->m_binding = WSFED_NS;
-        login_event->m_saml1AuthnStatement = saml1statement;
-        login_event->m_nameID = (saml1name ? nameid.get() : saml2name);
-        login_event->m_saml2AuthnStatement = saml2statement;
-        if (ctx)
-            login_event->m_attributes = &ctx->getResolvedAttributes();
-        application.getServiceProvider().getTransactionLog()->write(*login_event);
-    }
-}
-
-#endif
-
-pair<bool,long> ADFSLogoutInitiator::run(SPRequest& request, bool) const
-{
-    // Normally we'd do notifications and session clearage here, but ADFS logout
-    // is missing the needed request/response features, so we have to rely on
-    // the IdP half to notify us back about the logout and do the work there.
-    // Basically we have no way to tell in the Logout receiving handler whether
-    // we initiated the logout or not.
-
-    Session* session = nullptr;
-    try {
-        session = request.getSession(false, true, false);  // don't cache it and ignore all checks
-        if (!session)
-            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);
-        }
-    }
-    catch (std::exception& ex) {
-        m_log.error("error accessing current session: %s", ex.what());
-        return make_pair(false,0L);
-    }
-
-    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-        // When out of process, we run natively.
-        return doRequest(request.getApplication(), request, request, session);
-    }
-    else {
-        // When not out of process, we remote the request.
-        session->unlock();
-        vector<string> headers(1,"Cookie");
-        headers.push_back("User-Agent");
-        DDF out,in = wrap(request, &headers);
-        DDFJanitor jin(in), jout(out);
-        out = send(request, in);
-        return unwrap(request, out);
-    }
-}
-
-void ADFSLogoutInitiator::receive(DDF& in, ostream& out)
-{
-#ifndef SHIBSP_LITE
-    // Defer to base class for notifications
-    if (in["notify"].integer() == 1)
-        return LogoutHandler::receive(in, out);
-
-    // Find application.
-    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)");
-        throw ConfigurationException("Unable to locate application for logout, deleted?");
-    }
-
-    // Unpack the request.
-    scoped_ptr<HTTPRequest> req(getRequest(*app, in));
-
-    // Set up a response shim.
-    DDF ret(nullptr);
-    DDFJanitor jout(ret);
-    scoped_ptr<HTTPResponse> resp(getResponse(*app, ret));
-
-    Session* session = nullptr;
-    try {
-         session = app->getServiceProvider().getSessionCache()->find(*app, *req, nullptr, nullptr);
-    }
-    catch (std::exception& ex) {
-        m_log.error("error accessing current session: %s", ex.what());
-    }
-
-    // With no session, we just skip the request and let it fall through to an empty struct return.
-    if (session) {
-        if (session->getEntityID()) {
-            // 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, *resp, session);
-        }
-        else {
-            m_log.error("no issuing entityID found in session");
-            time_t revocationExp = session->getExpiration();
-            session->unlock();
-            app->getServiceProvider().getSessionCache()->remove(*app, *req, resp.get(), revocationExp);
-        }
-    }
-    out << ret;
-#else
-    throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
-#endif
-}
-
-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
-        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
-        time_t revocationExp = session->getExpiration();
-        sessionLocker.assign();
-        session = nullptr;
-        application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse, revocationExp);
-        return sendLogoutPage(application, httpRequest, httpResponse, "partial");
-    }
-
-#ifndef SHIBSP_LITE
-    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();
-        Locker metadataLocker(m);
-        MetadataProviderCriteria mc(application, session->getEntityID(), &IDPSSODescriptor::ELEMENT_QNAME, m_binding.get());
-        pair<const EntityDescriptor*,const RoleDescriptor*> entity=m->getEntityDescriptor(mc);
-        if (!entity.first) {
-            throw MetadataException(
-                "Unable to locate metadata for identity provider ($entityID)", namedparams(1, "entityID", session->getEntityID())
-                );
-        }
-        else if (!entity.second) {
-            throw MetadataException(
-                "Unable to locate ADFS IdP role for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID())
-                );
-        }
-
-        const EndpointType* ep = EndpointManager<SingleLogoutService>(
-            dynamic_cast<const IDPSSODescriptor*>(entity.second)->getSingleLogoutServices()
-            ).getByBinding(m_binding.get());
-        if (!ep) {
-            throw MetadataException(
-                "Unable to locate ADFS single logout service for identity provider ($entityID).",
-                namedparams(1, "entityID", session->getEntityID())
-                );
-        }
-
-        const char* returnloc = httpRequest.getParameter("return");
-        if (returnloc)
-            application.limitRedirect(httpRequest, returnloc);
-
-        // Log the request.
-        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);
-        }
-
-        auto_ptr_char dest(ep->getLocation());
-        string req=string(dest.get()) + (strchr(dest.get(),'?') ? '&' : '?') + "wa=wsignout1.0";
-        if (returnloc) {
-            req += "&wreply=";
-            if (*returnloc == '/') {
-                string s(returnloc);
-                httpRequest.absolutize(s);
-                req += XMLToolingConfig::getConfig().getURLEncoder()->encode(s.c_str());
-            }
-            else {
-                req += XMLToolingConfig::getConfig().getURLEncoder()->encode(returnloc);
-            }
-        }
-        ret.second = httpResponse.sendRedirect(req.c_str());
-        ret.first = true;
-
-        if (session) {
-            time_t revocationExp = session->getExpiration();
-            sessionLocker.assign();
-            session = nullptr;
-            application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse, revocationExp);
-        }
-    }
-    catch (const MetadataException& mex) {
-        // Less noise for IdPs that don't support logout
-        m_log.info("unable to issue ADFS logout request: %s", mex.what());
-    }
-    catch (const std::exception& ex) {
-        m_log.error("error issuing ADFS logout request: %s", ex.what());
-    }
-
-    return ret;
-#else
-    throw ConfigurationException("Cannot perform logout using lite version of shibsp library.");
-#endif
-}
-
-pair<bool,long> ADFSLogout::run(SPRequest& request, bool isHandler) const
-{
-    // Defer to base class for front-channel loop first.
-    // This won't initiate the loop, only continue/end it.
-    pair<bool,long> ret = LogoutHandler::run(request, isHandler);
-    if (ret.first)
-        return ret;
-
-    // wa parameter indicates the "action" to perform
-    bool returning = false;
-    const char* param = request.getParameter("wa");
-    if (param) {
-        if (!strcmp(param, "wsignin1.0"))
-            return m_login.run(request, isHandler);
-        else if (strcmp(param, "wsignout1.0") && strcmp(param, "wsignoutcleanup1.0"))
-            throw FatalProfileException("Unsupported WS-Federation action parameter ($1).", params(1, param));
-    }
-    else if (strcmp(request.getMethod(),"GET") || !request.getParameter("notifying"))
-        throw FatalProfileException("Unsupported request to ADFS protocol endpoint.");
-    else
-        returning = true;
-
-    param = request.getParameter("wreply");
-    const Application& app = request.getApplication();
-
-    if (!returning) {
-        // Pass control to the first front channel notification point, if any.
-        map<string,string> parammap;
-        if (param)
-            parammap["wreply"] = param;
-        pair<bool,long> result = notifyFrontChannel(app, request, request, &parammap);
-        if (result.first)
-            return result;
-    }
-
-    // Best effort on back channel and to remove the user agent's session.
-    string session_id = app.getServiceProvider().getSessionCache()->active(app, request);
-    if (!session_id.empty()) {
-        vector<string> sessions(1,session_id);
-        notifyBackChannel(app, request.getRequestURL(), sessions, false);
-        try {
-            app.getServiceProvider().getSessionCache()->remove(app, request, &request);
-        }
-        catch (const std::exception& ex) {
-            m_log.error("error removing session (%s): %s", session_id.c_str(), ex.what());
-        }
-    }
-
-    if (param) {
-        if (*param == '/') {
-            string p(param);
-            request.absolutize(p);
-            return make_pair(true, request.sendRedirect(p.c_str()));
-        }
-        else {
-            app.limitRedirect(request, param);
-            return make_pair(true, request.sendRedirect(param));
-        }
-    }
-    return sendLogoutPage(app, request, request, "global");
-}
diff --git a/adfs/adfs.rc b/adfs/adfs.rc
deleted file mode 100644
index 9dfb6027..00000000
--- a/adfs/adfs.rc
+++ /dev/null
@@ -1,109 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"
-#ifdef SHIBSP_LITE
-            VALUE "InternalName", "adfs-lite\0"
-#else
-            VALUE "InternalName", "adfs\0"
-#endif
-#ifdef SHIBSP_LITE
-            VALUE "OriginalFilename", "adfs-lite.so\0"
-#else
-            VALUE "OriginalFilename", "adfs.so\0"
-#endif
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // !_MAC
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/adfs/resource.h b/adfs/resource.h
deleted file mode 100644
index 213fc9a2..00000000
--- a/adfs/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by adfs.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/configure.ac b/configure.ac
index 1cfd7511..112b94d5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,24 +1,11 @@
 AC_PREREQ([2.50])
-AC_INIT([shibboleth],[3.5.0],[https://shibboleth.atlassian.net/jira],[shibboleth-sp])
+AC_INIT([shibboleth],[4.0.0],[https://shibboleth.atlassian.net/jira],[shibboleth-sp])
 AC_CONFIG_SRCDIR(shibsp)
 AC_CONFIG_AUX_DIR(build-aux)
 AC_CONFIG_MACRO_DIR(m4)
 AM_INIT_AUTOMAKE
 PKG_INSTALLDIR
 
-# Docygen features
-DX_HTML_FEATURE(ON)
-DX_DOT_FEATURE(ON)
-DX_CHM_FEATURE(OFF)
-DX_CHI_FEATURE(OFF)
-DX_MAN_FEATURE(OFF)
-DX_RTF_FEATURE(OFF)
-DX_XML_FEATURE(OFF)
-DX_PDF_FEATURE(OFF)
-DX_PS_FEATURE(OFF)
-DX_INIT_DOXYGEN(shibboleth, doxygen.cfg, doc/api)
-DX_INCLUDE=
-
 AC_ARG_ENABLE(debug,
     AS_HELP_STRING([--enable-debug],[Produce debug variant (Default = no)]),
     enable_debug=$enableval, enable_debug=no)
@@ -29,15 +16,11 @@ if test "$enable_debug" = "yes" ; then
 fi
 
 AC_CONFIG_HEADERS([config.h shibsp/config_pub.h])
-AC_CONFIG_FILES([shibsp.pc shibsp-lite.pc shibboleth.spec])
+AC_CONFIG_FILES([shibsp.pc shibsp-lite.pc])
 
 AC_PROG_CC([gcc gcc3 cc])
 AC_PROG_CXX([g++ g++3 c++ CC])
-
-if test "$GCC" = "yes" ; then
-    AM_CFLAGS="$AM_CFLAGS -Wall -W"
-    AM_CXXFLAGS="$AM_CXXFLAGS -Wall -W"
-fi
+AX_CXX_COMPILE_STDCXX([11])
 
 AC_SUBST([AM_CFLAGS])
 AC_SUBST([AM_CXXFLAGS])
@@ -145,26 +128,9 @@ AX_PKG_CHECK_MODULES([opensaml],,[opensaml >= 3.1],,,
 PKG_CHECK_VAR([OPENSAMLXMLDIR],[opensaml],[pkgxmldir])
 
 # output the underlying makefiles
-WANT_SUBDIRS="doc schemas configs shibsp plugins shibd util"
+WANT_SUBDIRS="doc schemas configs shibsp util"
 AC_CONFIG_FILES([Makefile doc/Makefile schemas/Makefile \
-	configs/Makefile shibsp/Makefile plugins/Makefile \
-	shibd/Makefile util/Makefile selinux/Makefile])
-
-## ADFS?
-AC_CONFIG_FILES([adfs/Makefile])
-AC_ARG_ENABLE([adfs],
-    AS_HELP_STRING([--disable-adfs],[do not build the ADFS module]),
-    [adfs_enabled=$enableval], [adfs_enabled=yes])
-if test "x$adfs_enabled" = "x" ; then
-    adfs_enabled=yes
-fi
-AC_MSG_CHECKING(whether to build the ADFS module)
-if test "$adfs_enabled" = "no" ; then
-    AC_MSG_RESULT(no)
-else
-    AC_MSG_RESULT(yes)
-    WANT_SUBDIRS="$WANT_SUBDIRS adfs"
-fi
+	configs/Makefile shibsp/Makefile util/Makefile])
 
 ## systemd
 dnl Systemd will be disabled by default and requires you to run configure with
@@ -177,50 +143,6 @@ AC_ARG_ENABLE(systemd,
 	 # sd_notify() is always present, no need to check for it:
          AC_DEFINE([HAVE_SD_NOTIFY],[1],[Define to 1 if you have the sd_notify function.])])])
 
-#
-# Build NSAPI module?
-#
-AC_MSG_CHECKING(for NSAPI module option)
-AC_ARG_WITH(nsapi,
-    AS_HELP_STRING([--with-nsapi=DIR],[Build NSAPI module for Netscape/iPlanet/SunONE]),
-    [WANT_NSAPI=$withval],[WANT_NSAPI=no])
-AC_MSG_RESULT($WANT_NSAPI)
-
-if test "$WANT_NSAPI" != "no"; then
-  if test ! -d $WANT_NSAPI/bin ; then
-    AC_MSG_ERROR([Please specify the path to the root of your Netscape/iPlanet/SunONE server using --with-nsapi=DIR])
-  fi
-  AC_MSG_CHECKING(for NSAPI include files)
-  if test -d $WANT_NSAPI/include ; then
-    NSAPI_INCLUDE=$WANT_NSAPI/include
-    AC_MSG_RESULT(Netscape-Enterprise 3.x style)
-    AC_CHECK_HEADERS([$NSAPI_INCLUDE/nsapi.h],,,[#define XP_UNIX])
-    NSAPI_INCLUDE="$NSAPI_INC_DIR -I$NSAPI_INCLUDE"
-  fi
-  if test -d $WANT_NSAPI/plugins/include ; then
-    test -n "$NSAPI_INCLUDE" && NSAPI_INC_DIR="-I$NSAPI_INCLUDE"
-    NSAPI_INCLUDE="$WANT_NSAPI/plugins/include"
-    AC_MSG_RESULT(iPlanet 4.x / SunONE 6.x style)
-    AC_CHECK_HEADERS([$NSAPI_INCLUDE/nsapi.h],,,[#define XP_UNIX])
-    NSAPI_INCLUDE="$NSAPI_INC_DIR -I$NSAPI_INCLUDE"
-  fi
-  if test "$NSAPI_INCLUDE" = ""; then
-    AC_MSG_ERROR([Please check you have nsapi.h in either $WANT_NSAPI/include or $WANT_NSAPI/plugins/include])
-  fi
-fi
-
-AC_SUBST(NSAPI_INCLUDE)
-
-# always output the Makefile, even if you don't use it
-AC_CONFIG_FILES([nsapi_shib/Makefile])
-AM_CONDITIONAL(BUILD_NSAPI,test ! "$WANT_NSAPI" = "no")
-
-# add the NSAPI module to the list of wanted subdirs..
-if test ! "$WANT_NSAPI" = "no" ; then
-    WANT_SUBDIRS="$WANT_SUBDIRS nsapi_shib"
-fi
-
-
 #
 # Build FastCGI support?
 #
@@ -262,51 +184,6 @@ if test ! "$WANT_FASTCGI" = "no" ; then
     WANT_SUBDIRS="$WANT_SUBDIRS fastcgi"
 fi
 
-#
-# Build Memcached support?
-#
-AC_MSG_CHECKING(for Memcached support)
-AC_ARG_WITH(memcached,
-    AS_HELP_STRING([--with-memcached=DIR],[Build Memcached support]),
-    [WANT_MEMCACHED=$withval],[WANT_MEMCACHED=no])
-AC_MSG_RESULT($WANT_MEMCACHED)
-
-if test "$WANT_MEMCACHED" != "no"; then
-
-    if test "$WANT_MEMCACHED" != "yes"; then
-        if test x_$WANT_MEMCACHED != x_/usr; then
-            MEMCACHED_INCLUDE="-I$WANT_MEMCACHED/include"
-            MEMCACHED_LDFLAGS="-L$WANT_MEMCACHED/lib"
-        fi
-    fi
-
-    # save and append master flags
-    save_CPPFLAGS="$CPPFLAGS"
-    CPPFLAGS="$MEMCACHED_INCLUDE $CPPFLAGS"    
-
-    AC_CHECK_HEADER([libmemcached/memcached.h],,
-        AC_MSG_ERROR([unable to find Memcached header files]))
-    AC_CHECK_DECL([memcached_last_error_message],
-        [AC_DEFINE([HAVE_MEMCACHED_LAST_ERROR_MESSAGE],[1],[Define to 1 if libmemcached supports error handling function.])],,
-        [#include <libmemcached/memcached.h>])
-    MEMCACHED_LIBS="-lmemcached"
-
-    # restore standard flags
-    CPPFLAGS="$save_CPPFLAGS"
-fi
-
-AC_SUBST(MEMCACHED_INCLUDE)
-AC_SUBST(MEMCACHED_LDFLAGS)
-AC_SUBST(MEMCACHED_LIBS)
-
-# always output the Makefile, even if you don't use it
-AC_CONFIG_FILES([memcache-store/Makefile])
-AM_CONDITIONAL(BUILD_MEMCACHED,test ! "$WANT_MEMCACHED" = "no")
-
-if test ! "$WANT_MEMCACHED" = "no" ; then
-    WANT_SUBDIRS="$WANT_SUBDIRS memcache-store"
-fi
-
 
 #
 # If no --enable-apache-xx specified 
@@ -809,101 +686,6 @@ if test "$WANT_APACHE_13" = "yes" || test "$WANT_APACHE_20" = "yes" || test "$WA
 fi
 
 
-#
-# Implement the checks of the ODBC Storage Service
-#
-# 1) Assume the user wants ODBC; if it's not found then just continue without
-# 2) If the user specifically requested odbc, look for it and ERROR if not found
-# 3) If the user specifically requested no odbc, don't build it.
-#
-
-AC_CONFIG_FILES([odbc-store/Makefile])
-
-# determine whether we should enable the odbc ccache
-AC_ARG_ENABLE([odbc],
-	AS_HELP_STRING([--disable-odbc],[disable the ODBC Storage Service]),
-	[odbc_enabled=$enableval], [odbc_enabled=default])
-if test "x$odbc_enabled" = "x" ; then
-    odbc_enabled=yes
-fi
-
-# Are we trying to build ODBC?
-AC_MSG_CHECKING(whether to build the ODBC storage service)
-if test "$odbc_enabled" = "yes" ; then
-    build_odbc=yes
-    AC_MSG_RESULT(yes)
-elif test "$odbc_enabled" = "default" ; then
-    build_odbc=yes
-    AC_MSG_RESULT([yes, if it can be found])
-else
-    build_odbc=no
-    AC_MSG_RESULT(no)
-fi
-
-# If we're trying to build ODBC, try to find the odbc_config program.
-if test "$build_odbc" = "yes" ; then
-    odbc_dir=""
-    AC_ARG_WITH(odbc,
-	   AS_HELP_STRING([--with-odbc=PATH],[directory where odbc is installed]),
-	    [if test "$with_odbc" = no ; then
-            AC_MSG_ERROR([Try running --disable-odbc instead.])
-         elif test "$with_odbc" != yes ; then
-            odbc_dir="$with_odbc/bin"
-            if test "$with_odbc" != /usr ; then
-                ODBC_CFLAGS="-I$with_odbc/include"
-                ODBC_LIBS="-L$with_odbc/lib"
-            fi
-         fi])
-
-   AC_PATH_PROG(ODBC_CONFIG, odbc_config, no, $odbc_dir $PATH )
-   if test "$ODBC_CONFIG" = no ; then
-      AC_MSG_WARN([Cannot find odbc_config, will try to guess settings.])
-      ODBC_LIBS="$ODBC_LIBS -lodbc"
-   else
-      ODBC_CFLAGS=`$ODBC_CONFIG --cflags`
-      ODBC_LIBS=`$ODBC_CONFIG --libs`
-   fi
-
-   save_CPPFLAGS="$CPPFLAGS"
-   CPPFLAGS="$CPPFLAGS $ODBC_CFLAGS"
-
-   AC_CHECK_HEADER([sql.h], [have_sql_h=yes], [have_sql_h=no])
-   if test "$have_sql_h" = no -a "$odbc_enabled" = "yes" ; then
-     AC_MSG_ERROR(unable to find ODBC header files)
-   fi
-
-   if test "$have_sql_h" = yes ; then
-      save_LIBS="$LIBS"
-      LIBS="$LIBS $ODBC_LIBS"
-      AC_MSG_CHECKING(if we can link againt ODBC)
-      AC_LINK_IFELSE(
-        [AC_LANG_PROGRAM([[#include <sql.h>
- #include <sqlext.h>
- #include <stdio.h>]],
-            [[SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0)]])],
-        [have_odbc_libs=yes],[have_odbc_libs=no])
-      LIBS="$save_LIBS"
-      if test "$have_odbc_libs" = no ; then
-         if test "$odbc_enabled" = "yes" ; then
-            AC_MSG_ERROR([unable to link with ODBC Library])
-         else
-            AC_MSG_RESULT([no, skipping ODBC])
-         fi
-      fi
-   fi
-
-   CPPFLAGS="$save_CPPFLAGS"
-fi
-
-# if have_odbc_libs=yes then go ahead with building ODBC
-if test "$have_odbc_libs" = yes ; then
-   # this AC_MSG_RESULT is from above!
-   AC_MSG_RESULT(yes)
-   WANT_SUBDIRS="$WANT_SUBDIRS odbc-store"
-   AC_SUBST(ODBC_CFLAGS)
-   AC_SUBST(ODBC_LIBS)
-fi
-
 AC_ARG_WITH([gssapi],
   [AS_HELP_STRING([--with-gssapi],[include GSSAPI support])],,[with_gssapi=check])
 AS_IF([test "x$with_gssapi" != xno],
diff --git a/doc/api/.gitkeep b/doc/api/.gitkeep
deleted file mode 100644
index e69de29b..00000000
diff --git a/doxygen.am b/doxygen.am
deleted file mode 100644
index a03a6282..00000000
--- a/doxygen.am
+++ /dev/null
@@ -1,186 +0,0 @@
-# Copyright (C) 2004 Oren Ben-Kiki
-# This file is distributed under the same terms as the Automake macro files.
-
-# Generate automatic documentation using Doxygen. Goals and variables values
-# are controlled by the various DX_COND_??? conditionals set by autoconf.
-#
-# The provided goals are:
-# doxygen-doc: Generate all doxygen documentation.
-# doxygen-run: Run doxygen, which will generate some of the documentation
-#              (HTML, CHM, CHI, MAN, RTF, XML) but will not do the post
-#              processing required for the rest of it (PS, PDF, and some MAN).
-# doxygen-man: Rename some doxygen generated man pages.
-# doxygen-ps: Generate doxygen PostScript documentation.
-# doxygen-pdf: Generate doxygen PDF documentation.
-#
-# Note that by default these are not integrated into the automake goals. If
-# doxygen is used to generate man pages, you can achieve this integration by
-# setting man3_MANS to the list of man pages generated and then adding the
-# dependency:
-#
-#   $(man3_MANS): doxygen-doc
-#
-# This will cause make to run doxygen and generate all the documentation.
-#
-# The following variable is intended for use in Makefile.am:
-#
-# DX_CLEANFILES = everything to clean.
-#
-# This is usually added to MOSTLYCLEANFILES.
-
-## --------------------------------- ##
-## Format-independent Doxygen rules. ##
-## --------------------------------- ##
-
-if DX_COND_doc
-
-## ------------------------------- ##
-## Rules specific for HTML output. ##
-## ------------------------------- ##
-
-if DX_COND_html
-
-DX_CLEAN_HTML = @DX_DOCDIR@/html
-
-endif DX_COND_html
-
-## ------------------------------ ##
-## Rules specific for CHM output. ##
-## ------------------------------ ##
-
-if DX_COND_chm
-
-DX_CLEAN_CHM = @DX_DOCDIR@/chm
-
-if DX_COND_chi
-
-DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE_NAME at .chi
-
-endif DX_COND_chi
-
-endif DX_COND_chm
-
-## ------------------------------ ##
-## Rules specific for MAN output. ##
-## ------------------------------ ##
-
-if DX_COND_man
-
-DX_CLEAN_MAN = @DX_DOCDIR@/man
-
-endif DX_COND_man
-
-## ------------------------------ ##
-## Rules specific for RTF output. ##
-## ------------------------------ ##
-
-if DX_COND_rtf
-
-DX_CLEAN_RTF = @DX_DOCDIR@/rtf
-
-endif DX_COND_rtf
-
-## ------------------------------ ##
-## Rules specific for XML output. ##
-## ------------------------------ ##
-
-if DX_COND_xml
-
-DX_CLEAN_XML = @DX_DOCDIR@/xml
-
-endif DX_COND_xml
-
-## ----------------------------- ##
-## Rules specific for PS output. ##
-## ----------------------------- ##
-
-if DX_COND_ps
-
-DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE_NAME at .ps
-
-DX_PS_GOAL = doxygen-ps
-
-doxygen-ps: @DX_DOCDIR@/@PACKAGE_NAME at .ps
-
- at DX_DOCDIR@/@PACKAGE_NAME at .ps: @DX_DOCDIR@/@PACKAGE_NAME at .tag
-	cd @DX_DOCDIR@/latex; \
-	rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-	$(DX_LATEX) refman.tex; \
-	$(MAKEINDEX_PATH) refman.idx; \
-	$(DX_LATEX) refman.tex; \
-	countdown=5; \
-	while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-	                  refman.log > /dev/null 2>&1 \
-	   && test $$countdown -gt 0; do \
-	    $(DX_LATEX) refman.tex; \
-	    countdown=`expr $$countdown - 1`; \
-	done; \
-	$(DX_DVIPS) -o ../@PACKAGE_NAME at .ps refman.dvi
-
-endif DX_COND_ps
-
-## ------------------------------ ##
-## Rules specific for PDF output. ##
-## ------------------------------ ##
-
-if DX_COND_pdf
-
-DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE_NAME at .pdf
-
-DX_PDF_GOAL = doxygen-pdf
-
-doxygen-pdf: @DX_DOCDIR@/@PACKAGE_NAME at .pdf
-
- at DX_DOCDIR@/@PACKAGE_NAME at .pdf: @DX_DOCDIR@/@PACKAGE_NAME at .tag
-	cd @DX_DOCDIR@/latex; \
-	rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-	$(DX_PDFLATEX) refman.tex; \
-	$(DX_MAKEINDEX) refman.idx; \
-	$(DX_PDFLATEX) refman.tex; \
-	countdown=5; \
-	while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-	                  refman.log > /dev/null 2>&1 \
-	   && test $$countdown -gt 0; do \
-	    $(DX_PDFLATEX) refman.tex; \
-	    countdown=`expr $$countdown - 1`; \
-	done; \
-	mv refman.pdf ../@PACKAGE_NAME at .pdf
-
-endif DX_COND_pdf
-
-## ------------------------------------------------- ##
-## Rules specific for LaTeX (shared for PS and PDF). ##
-## ------------------------------------------------- ##
-
-if DX_COND_latex
-
-DX_CLEAN_LATEX = @DX_DOCDIR@/latex
-
-endif DX_COND_latex
-
-.PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-.INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
-doxygen-run: @DX_DOCDIR@/@PACKAGE_NAME at .tag
-
-doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-
- at DX_DOCDIR@/@PACKAGE_NAME at .tag: $(DX_CONFIG) $(pkginclude_HEADERS)
-	rm -rf @DX_DOCDIR@
-	$(DX_ENV) DX_INCLUDE=$(DX_INCLUDE) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
-
-DX_CLEANFILES = \
-    @DX_DOCDIR@/@PACKAGE_NAME at .tag \
-    -r \
-    $(DX_CLEAN_HTML) \
-    $(DX_CLEAN_CHM) \
-    $(DX_CLEAN_CHI) \
-    $(DX_CLEAN_MAN) \
-    $(DX_CLEAN_RTF) \
-    $(DX_CLEAN_XML) \
-    $(DX_CLEAN_PS) \
-    $(DX_CLEAN_PDF) \
-    $(DX_CLEAN_LATEX)
-
-endif DX_COND_doc
diff --git a/doxygen.cfg b/doxygen.cfg
deleted file mode 100644
index 1c136a61..00000000
--- a/doxygen.cfg
+++ /dev/null
@@ -1,255 +0,0 @@
-# Doxyfile 1.4.6
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-PROJECT_NAME           = $(PROJECT)-$(VERSION)
-PROJECT_NUMBER         = 
-OUTPUT_DIRECTORY       = $(DOCDIR)
-CREATE_SUBDIRS         = NO
-OUTPUT_LANGUAGE        = English
-USE_WINDOWS_ENCODING   = YES
-BRIEF_MEMBER_DESC      = YES
-REPEAT_BRIEF           = YES
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-ALWAYS_DETAILED_SEC    = NO
-INLINE_INHERITED_MEMB  = NO
-FULL_PATH_NAMES        = YES
-STRIP_FROM_PATH        = $(SRCDIR)
-STRIP_FROM_INC_PATH    = $(SRCDIR)
-SHORT_NAMES            = YES
-JAVADOC_AUTOBRIEF      = YES
-MULTILINE_CPP_IS_BRIEF = NO
-DETAILS_AT_TOP         = NO
-INHERIT_DOCS           = YES
-SEPARATE_MEMBER_PAGES  = NO
-TAB_SIZE               = 4
-ALIASES                = 
-OPTIMIZE_OUTPUT_FOR_C  = NO
-OPTIMIZE_OUTPUT_JAVA   = NO
-BUILTIN_STL_SUPPORT    = YES
-DISTRIBUTE_GROUP_DOC   = NO
-SUBGROUPING            = YES
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-EXTRACT_ALL            = NO
-EXTRACT_PRIVATE        = NO
-EXTRACT_STATIC         = YES
-EXTRACT_LOCAL_CLASSES  = YES
-EXTRACT_LOCAL_METHODS  = NO
-HIDE_UNDOC_MEMBERS     = NO
-HIDE_UNDOC_CLASSES     = NO
-HIDE_FRIEND_COMPOUNDS  = NO
-HIDE_IN_BODY_DOCS      = NO
-INTERNAL_DOCS          = NO
-CASE_SENSE_NAMES       = NO
-HIDE_SCOPE_NAMES       = NO
-SHOW_INCLUDE_FILES     = YES
-INLINE_INFO            = YES
-SORT_MEMBER_DOCS       = YES
-SORT_BRIEF_DOCS        = NO
-SORT_BY_SCOPE_NAME     = NO
-GENERATE_TODOLIST      = YES
-GENERATE_TESTLIST      = YES
-GENERATE_BUGLIST       = YES
-GENERATE_DEPRECATEDLIST= YES
-ENABLED_SECTIONS       = 
-MAX_INITIALIZER_LINES  = 30
-SHOW_USED_FILES        = YES
-SHOW_DIRECTORIES       = YES
-FILE_VERSION_FILTER    = 
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-QUIET                  = NO
-WARNINGS               = YES
-WARN_IF_UNDOCUMENTED   = YES
-WARN_IF_DOC_ERROR      = YES
-WARN_NO_PARAMDOC       = NO
-WARN_FORMAT            = "$file:$line: $text"
-WARN_LOGFILE           = 
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-INPUT                  = $(SRCDIR)/shibsp
-FILE_PATTERNS          = *.d \
-                         *.java \
-                         *.ii \
-                         *.ixx \
-                         *.ipp \
-                         *.i++ \
-                         *.inl \
-                         *.h \
-                         *.hh \
-                         *.hxx \
-                         *.hpp \
-                         *.h++ \
-                         *.idl \
-                         *.odl \
-                         *.cs \
-                         *.php \
-                         *.php3 \
-                         *.inc \
-                         *.m \
-                         *.mm \
-                         *.dox \
-                         *.py
-RECURSIVE              = YES
-EXCLUDE                = 
-EXCLUDE_SYMLINKS       = NO
-EXCLUDE_PATTERNS       = 
-EXAMPLE_PATH           = $(SRCDIR)/shibsp
-EXAMPLE_PATTERNS       =
-EXAMPLE_RECURSIVE      = NO
-IMAGE_PATH             = 
-INPUT_FILTER           = 
-FILTER_PATTERNS        = 
-FILTER_SOURCE_FILES    = NO
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-SOURCE_BROWSER         = NO
-INLINE_SOURCES         = NO
-STRIP_CODE_COMMENTS    = YES
-REFERENCED_BY_RELATION = NO
-REFERENCES_RELATION    = NO
-USE_HTAGS              = NO
-VERBATIM_HEADERS       = NO
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-ALPHABETICAL_INDEX     = NO
-COLS_IN_ALPHA_INDEX    = 5
-IGNORE_PREFIX          = 
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-GENERATE_HTML          = $(GENERATE_HTML)
-HTML_OUTPUT            = html
-HTML_FILE_EXTENSION    = .html
-HTML_HEADER            = 
-HTML_FOOTER            = 
-HTML_STYLESHEET        = 
-HTML_ALIGN_MEMBERS     = YES
-GENERATE_HTMLHELP      = $(GENERATE_CHM)
-CHM_FILE               = ../$(PROJECT).chm
-HHC_LOCATION           = $(HHC_PATH)
-GENERATE_CHI           = $(GENERATE_CHI)
-BINARY_TOC             = NO
-TOC_EXPAND             = NO
-DISABLE_INDEX          = NO
-ENUM_VALUES_PER_LINE   = 4
-GENERATE_TREEVIEW      = YES
-TREEVIEW_WIDTH         = 250
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-GENERATE_LATEX         = $(GENERATE_LATEX)
-LATEX_OUTPUT           = latex
-LATEX_CMD_NAME         = latex
-MAKEINDEX_CMD_NAME     = makeindex
-COMPACT_LATEX          = NO
-PAPER_TYPE             = $(PAPER_SIZE)
-EXTRA_PACKAGES         = 
-LATEX_HEADER           = 
-PDF_HYPERLINKS         = NO
-USE_PDFLATEX           = NO
-LATEX_BATCHMODE        = YES
-LATEX_HIDE_INDICES     = NO
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-GENERATE_RTF           = $(GENERATE_RTF)
-RTF_OUTPUT             = rtf
-COMPACT_RTF            = NO
-RTF_HYPERLINKS         = NO
-RTF_STYLESHEET_FILE    = 
-RTF_EXTENSIONS_FILE    = 
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-GENERATE_MAN           = $(GENERATE_MAN)
-MAN_OUTPUT             = man
-MAN_EXTENSION          = .1
-MAN_LINKS              = NO
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-GENERATE_XML           = $(GENERATE_XML)
-XML_OUTPUT             = xml
-XML_SCHEMA             = 
-XML_DTD                = 
-XML_PROGRAMLISTING     = YES
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-GENERATE_AUTOGEN_DEF   = NO
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-GENERATE_PERLMOD       = NO
-PERLMOD_LATEX          = NO
-PERLMOD_PRETTY         = YES
-PERLMOD_MAKEVAR_PREFIX = 
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor   
-#---------------------------------------------------------------------------
-ENABLE_PREPROCESSING   = YES
-MACRO_EXPANSION        = YES
-EXPAND_ONLY_PREDEF     = NO
-SEARCH_INCLUDES        = YES
-INCLUDE_PATH           = $(SRCDIR) $(DX_INCLUDE)
-INCLUDE_FILE_PATTERNS  = 
-PREDEFINED             = _MSC_VER \
-                         DOXYGEN_SKIP
-EXPAND_AS_DEFINED      = 
-SKIP_FUNCTION_MACROS   = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references   
-#---------------------------------------------------------------------------
-TAGFILES               = 
-GENERATE_TAGFILE       = $(DOCDIR)/$(PROJECT).tag
-ALLEXTERNALS           = NO
-EXTERNAL_GROUPS        = YES
-PERL_PATH              = $(PERL_PATH)
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool   
-#---------------------------------------------------------------------------
-CLASS_DIAGRAMS         = YES
-HIDE_UNDOC_RELATIONS   = YES
-HAVE_DOT               = $(HAVE_DOT)
-CLASS_GRAPH            = YES
-COLLABORATION_GRAPH    = YES
-GROUP_GRAPHS           = YES
-UML_LOOK               = NO
-TEMPLATE_RELATIONS     = NO
-INCLUDE_GRAPH          = YES
-INCLUDED_BY_GRAPH      = YES
-CALL_GRAPH             = NO
-GRAPHICAL_HIERARCHY    = YES
-DIRECTORY_GRAPH        = YES
-DOT_IMAGE_FORMAT       = png
-DOT_PATH               = $(DOT_PATH)
-DOTFILE_DIRS           = 
-MAX_DOT_GRAPH_WIDTH    = 1024
-MAX_DOT_GRAPH_HEIGHT   = 1024
-MAX_DOT_GRAPH_DEPTH    = 1000
-DOT_TRANSPARENT        = NO
-DOT_MULTI_TARGETS      = NO
-GENERATE_LEGEND        = YES
-DOT_CLEANUP            = YES
-#---------------------------------------------------------------------------
-# Configuration::additions related to the search engine   
-#---------------------------------------------------------------------------
-SEARCHENGINE           = NO
diff --git a/isapi_shib/isapi_shib.cpp b/isapi_shib/isapi_shib.cpp
deleted file mode 100644
index adea5924..00000000
--- a/isapi_shib/isapi_shib.cpp
+++ /dev/null
@@ -1,1105 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/**
- * isapi_shib.cpp
- *
- * Shibboleth ISAPI filter.
- */
-
-#define SHIBSP_LITE
-#include "config_win32.h"
-
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#define _CRT_SECURE_NO_DEPRECATE 1
-#define _CRT_RAND_S
-
-#include <shibsp/exceptions.h>
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-
-#include <set>
-#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>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xmltooling/logging.h>
-
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-using xmltooling::logging::Category;
-using xmltooling::logging::Priority;
-
-// globals
-namespace {
-    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);
-    static const XMLCh validate[] =         UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
-    static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);
-    static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);
-    static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);
-    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);
-    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);
-    static const XMLCh useHeaders[] =       UNICODE_LITERAL_10(u, s, e, H, e, a, d, e, r, s);
-    static const XMLCh useVariables[] =     UNICODE_LITERAL_12(u, s, e, V, a, r, i, a, b, l, e, s);
-    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);
-    static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);
-
-    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))
-        {
-            e = XMLHelper::getFirstChildElement(e, Alias);
-            while (e) {
-                if (e->hasChildNodes()) {
-                    auto_ptr_char alias(XMLHelper::getTextContent(e));
-                    m_aliases.insert(alias.get());
-                }
-                e = XMLHelper::getNextSiblingElement(e, Alias);
-            }
-        }
-        string m_scheme,m_port,m_sslport,m_name;
-        set<string> m_aliases;
-    };
-
-    HINSTANCE g_hinstDLL;
-    SPConfig* g_Config = nullptr;
-    map<string,site_t> g_Sites;
-    bool g_bNormalizeRequest = true;
-    string g_unsetHeaderValue,g_spoofKey;
-    bool g_checkSpoofing = true;
-    bool g_catchAll = false;
-    bool g_bSafeHeaderNames = false;
-    vector<string> g_NoCerts;
-}
-
-void _my_invalid_parameter_handler(
-   const wchar_t * expression,
-   const wchar_t * function,
-   const wchar_t * file,
-   unsigned int line,
-   uintptr_t pReserved
-   )
-{
-    return;
-}
-
-extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)
-{
-    if (fdwReason == DLL_PROCESS_ATTACH)
-        g_hinstDLL = hinstDLL;
-    return TRUE;
-}
-
-extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)
-{
-    if (!pVer)
-        return FALSE;
-
-    if (!g_Config) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").fatal("extension mode startup not possible, is the DLL loaded as a filter?");
-        return FALSE;
-    }
-
-    pVer->dwExtensionVersion = HSE_VERSION;
-    strncpy(pVer->lpszExtensionDesc, "Shibboleth ISAPI Extension", HSE_MAX_EXT_DLL_NAME_LEN-1);
-    return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateExtension(DWORD)
-{
-    return TRUE;    // cleanup should happen when filter unloads
-}
-
-extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
-{
-    Category& log = Category::getInstance(SHIBSP_LOGCAT ".ISAPI");
-
-    if (!pVer)
-        return FALSE;
-    else if (g_Config) {
-        log.warn("reentrant ISAPI filter initialization, ignoring...");
-        return TRUE;
-    }
-
-    g_Config = &SPConfig::getConfig();
-    g_Config->deprecation().warn("ISAPI extension is replaced by IIS 7+ module");
-    g_Config->setFeatures(
-        SPConfig::Listener |
-        SPConfig::Caching |
-        SPConfig::RequestMapping |
-        SPConfig::InProcess |
-        SPConfig::Logging |
-        SPConfig::Handlers
-        );
-    if (!g_Config->init()) {
-        g_Config = nullptr;
-        log.fatal("ISAPI filter startup failed during library initialization, check native log for help");
-        return FALSE;
-    }
-
-    try {
-        if (!g_Config->instantiate(nullptr, true))
-            throw runtime_error("unknown error");
-    }
-    catch (const std::exception& ex) {
-        log.fatal("ISAPI filter startup failed: %s", ex.what());
-        g_Config->term();
-        g_Config=nullptr;
-        return FALSE;
-    }
-
-    // Access implementation-specifics and site mappings.
-    ServiceProvider* sp = g_Config->getServiceProvider();
-    Locker locker(sp);
-    const PropertySet* props = sp->getPropertySet("InProcess");
-    if (props) {
-        pair<bool,bool> flag = props->getBool("checkSpoofing");
-        g_checkSpoofing = !flag.first || flag.second;
-        flag = props->getBool("catchAll");
-        g_catchAll = flag.first && flag.second;
-
-        pair<bool,const char*> unsetValue = props->getString("unsetHeaderValue");
-        if (unsetValue.first)
-            g_unsetHeaderValue = unsetValue.second;
-        if (g_checkSpoofing) {
-            unsetValue = props->getString("spoofKey");
-            if (unsetValue.first)
-                g_spoofKey = unsetValue.second;
-            else {
-                _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
-                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);
-                    g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
-                        lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
-                }
-                else {
-                    _set_invalid_parameter_handler(old);
-                    log.fatal("ISAPI filter failed to generate a random anti-spoofing key");
-                    locker.assign();    // pops lock on SP config
-                    g_Config->term();
-                    g_Config = nullptr;
-                    return FALSE;
-                }
-            }
-        }
-
-        props = props->getPropertySet("ISAPI");
-        if (props) {
-            flag = props->getBool("normalizeRequest");
-            g_bNormalizeRequest = !flag.first || flag.second;
-            flag = props->getBool("safeHeaderNames");
-            g_bSafeHeaderNames = flag.first && flag.second;
-            if (props->getString("useHeaders").first)
-                log.warn("useHeaders attribute not supported by ISAPI filter, ignored");
-            if (props->getString("useVariables").first)
-                log.warn("useVariables attribute not supported by ISAPI filter, ignored");
-
-            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(), Site);
-            while (child) {
-                string id(XMLHelper::getAttrString(child, "", id));
-                if (!id.empty()) {
-                    g_Sites.insert(make_pair(id, site_t(child)));
-                    if (!XMLHelper::getAttrString(child, "", useHeaders).empty())
-                        log.warn("useHeaders attribute not valid for this filter");
-                    if (!XMLHelper::getAttrString(child, "", useVariables).empty())
-                        log.warn("useVariables attribute not valid for this filter");
-                }
-                child = XMLHelper::getNextSiblingElement(child, Site);
-            }
-
-            if (nullptr != props->getPropertySet("Roles"))
-                log.warn("<Roles> element not valid for this filter");
-        }
-    }
-
-    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 |
-                   SF_NOTIFY_PREPROC_HEADERS |
-                   SF_NOTIFY_LOG);
-    log.info("ISAPI filter initialized");
-    return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
-    if (g_Config)
-        g_Config->term();
-    g_Config = nullptr;
-    Category::getInstance(SHIBSP_LOGCAT ".ISAPI").info("ISAPI filter shutting down");
-    return TRUE;
-}
-
-/* Next up, some suck-free versions of various APIs.
-
-   You DON'T require people to guess the buffer size and THEN tell them the right size.
-   Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that
-   constant strings aren't typed as such, making it just that much harder. These versions
-   are now updated to use a special growable buffer object, modeled after the standard
-   string class. The standard string won't work because they left out the option to
-   pre-allocate a non-constant buffer.
-*/
-
-class dynabuf
-{
-public:
-    dynabuf() { bufptr=nullptr; buflen=0; }
-    dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }
-    ~dynabuf() { delete[] bufptr; }
-    size_t length() const { return bufptr ? strlen(bufptr) : 0; }
-    size_t size() const { return buflen; }
-    bool empty() const { return length()==0; }
-    void reserve(size_t s, bool keep=false);
-    void erase() { if (bufptr) memset(bufptr,0,buflen); }
-    operator char*() { return bufptr; }
-    bool operator ==(const char* s) const;
-    bool operator !=(const char* s) const { return !(*this==s); }
-private:
-    char* bufptr;
-    size_t buflen;
-};
-
-void dynabuf::reserve(size_t s, bool keep)
-{
-    if (s<=buflen)
-        return;
-    char* p=new char[s];
-    if (keep)
-        while (buflen--)
-            p[buflen]=bufptr[buflen];
-    buflen=s;
-    delete[] bufptr;
-    bufptr=p;
-}
-
-bool dynabuf::operator==(const char* s) const
-{
-    if (buflen==0 || s==nullptr)
-        return (buflen==0 && s==nullptr);
-    else
-        return strcmp(bufptr,s)==0;
-}
-
-/****************************************************************************/
-// ISAPI Filter
-
-class ShibTargetIsapiF : public AbstractSPRequest
-{
-  PHTTP_FILTER_CONTEXT m_pfc;
-  PHTTP_FILTER_PREPROC_HEADERS m_pn;
-  multimap<string,string> m_headers;
-  int m_port;
-  string m_scheme,m_hostname;
-  mutable string m_remote_addr,m_content_type,m_method;
-  dynabuf m_allhttp;
-  bool m_firsttime;
-
-public:
-  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)
-      : AbstractSPRequest(SHIBSP_LOGCAT ".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {
-
-    static char _url[] = "url";
-    static char _SERVER_PORT[] = "SERVER_PORT";
-    static char _SERVER_NAME[] = "SERVER_NAME";
-    static char _ShibSpoofCheck[] = "ShibSpoofCheck:";
-
-    // URL path always come from IIS.
-    dynabuf var(256);
-    GetHeader(_url,var,256,false);
-    setRequestURI(var);
-
-    // Port may come from IIS or from site def.
-    if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {
-        GetServerVariable(_SERVER_PORT,var,10);
-        if (var.empty()) {
-            m_port = pfc->fIsSecurePort ? 443 : 80;
-        }
-        else {
-            m_port = atoi(var);
-        }
-    }
-    else if (pfc->fIsSecurePort) {
-        m_port = atoi(site.m_sslport.c_str());
-    }
-    else {
-        m_port = atoi(site.m_port.c_str());
-    }
-
-    // Scheme may come from site def or be derived from IIS.
-    m_scheme=site.m_scheme;
-    if (m_scheme.empty() || !g_bNormalizeRequest)
-        m_scheme=pfc->fIsSecurePort ? "https" : "http";
-
-    GetServerVariable(_SERVER_NAME,var,32);
-
-    // Make sure SERVER_NAME is "authorized" for use on this site. If not, or empty, set to canonical name.
-    if (var.empty()) {
-        m_hostname = site.m_name;
-    }
-    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 (!g_spoofKey.empty()) {
-        GetHeader(_ShibSpoofCheck, var, 32, false);
-        if (!var.empty() && g_spoofKey == (char*)var)
-            m_firsttime = false;
-    }
-
-    if (!m_firsttime)
-        log(SPDebug, "ISAPI filter running more than once");
-  }
-  ~ShibTargetIsapiF() { }
-
-  const char* getScheme() const {
-    return m_scheme.c_str();
-  }
-  const char* getHostname() const {
-    return m_hostname.c_str();
-  }
-  int getPort() const {
-    return m_port;
-  }
-  const char* getQueryString() const {
-      const char* uri = getRequestURI();
-      uri = (uri ? strchr(uri, '?') : nullptr);
-      return uri ? (uri + 1) : nullptr;
-  }
-  const char* getMethod() const {
-    static char _HTTP_METHOD[] = "HTTP_METHOD";
-    if (m_method.empty()) {
-        dynabuf var(5);
-        GetServerVariable(_HTTP_METHOD,var,5,false);
-        if (!var.empty())
-            m_method = var;
-    }
-    return m_method.c_str();
-  }
-  string getContentType() const {
-    static char _HTTP_CONTENT_TYPE[] = "HTTP_CONTENT_TYPE";
-    if (m_content_type.empty()) {
-        dynabuf var(32);
-        GetServerVariable(_HTTP_CONTENT_TYPE,var,32,false);
-        if (!var.empty())
-            m_content_type = var;
-    }
-    return m_content_type;
-  }
-  string getRemoteAddr() const {
-    static char _REMOTE_ADDR[] = "REMOTE_ADDR";
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(_REMOTE_ADDR,var,16,false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  string makeSafeHeader(const char* rawname) const {
-      string hdr;
-      for (; *rawname; ++rawname) {
-          if (isalnum(*rawname))
-              hdr += *rawname;
-      }
-      return (hdr + ':');
-  }
-  void clearHeader(const char* rawname, const char* cginame) {
-    static char _ALL_HTTP[] = "ALL_HTTP";
-    static char _REMOTE_USER[] = "remote-user:";
-    static char _REMOTE_USER2[] = "remote_user:";
-
-    if (g_checkSpoofing && m_firsttime) {
-        if (m_allhttp.empty())
-	        GetServerVariable(_ALL_HTTP, m_allhttp, 4096, false);
-        if (!m_allhttp.empty()) {
-            string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');
-            if (strstr(m_allhttp, hdr.c_str()))
-                throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));
-        }
-    }
-    if (g_bSafeHeaderNames) {
-        string hdr = makeSafeHeader(rawname);
-        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
-    }
-    else if (!strcmp(rawname,"REMOTE_USER")) {
-        m_pn->SetHeader(m_pfc, _REMOTE_USER, const_cast<char*>(g_unsetHeaderValue.c_str()));
-        m_pn->SetHeader(m_pfc, _REMOTE_USER2, const_cast<char*>(g_unsetHeaderValue.c_str()));
-	}
-	else {
-        string hdr = string(rawname) + ':';
-        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));
-	}
-  }
-  void setHeader(const char* name, const char* value) {
-    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
-    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
-  }
-  string getSecureHeader(const char* name) const {
-    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');
-    dynabuf buf(256);
-    GetHeader(const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf.empty() ? "" : static_cast<char*>(buf));
-  }
-  string getHeader(const char* name) const {
-    string hdr(name);
-    hdr += ':';
-    dynabuf buf(256);
-    GetHeader(const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf.empty() ? "" : static_cast<char*>(buf));
-  }
-  void setRemoteUser(const char* user) {
-    setHeader("remote-user", user);
-    if (!user || !*user)
-        m_pfc->pFilterContext = nullptr;
-    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), 0))
-        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
-  }
-  string getRemoteUser() const {
-    return getSecureHeader("remote-user");
-  }
-  void setResponseHeader(const char* name, const char* value, bool replace=false) {
-    HTTPResponse::setResponseHeader(name, value, replace);
-    if (name && *name) {
-        // Set for later.
-        if (replace || !value)
-            m_headers.erase(name);
-        if (value && *value)
-            m_headers.insert(make_pair(name,value));
-    }
-  }
-  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)
-        hdr += i->first + ": " + i->second + "\r\n";
-    hdr += "\r\n";
-    const char* codestr="200 OK";
-    switch (status) {
-        case XMLTOOLING_HTTP_STATUS_NOTMODIFIED:    codestr="304 Not Modified"; break;
-        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;
-        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;
-        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;
-        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;
-    }
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (ULONG_PTR)hdr.c_str(), 0);
-    char buf[1024];
-    while (in) {
-        in.read(buf,1024);
-        DWORD resplen = in.gcount();
-        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);
-    }
-    return SF_STATUS_REQ_FINISHED;
-  }
-  long sendRedirect(const char* url) {
-    static char _status[] = "302 Please Wait";
-    HTTPResponse::sendRedirect(url);
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "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)
-        hdr += i->first + ": " + i->second + "\r\n";
-    hdr += "\r\n";
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, _status, (ULONG_PTR)hdr.c_str(), 0);
-    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
-    DWORD resplen=40;
-    m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);
-    return SF_STATUS_REQ_FINISHED;
-  }
-  long returnDecline() {
-      return SF_STATUS_REQ_NEXT_NOTIFICATION;
-  }
-  long returnOK() {
-    return SF_STATUS_REQ_NEXT_NOTIFICATION;
-  }
-
-  const vector<string>& getClientCertificates() const {
-      return g_NoCerts;
-  }
-
-  // The filter never processes the POST, so stub these methods.
-  long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }
-  const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }
-
-  void GetServerVariable(LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true) const {
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!m_pfc->GetServerVariable(m_pfc,lpszVariable,s,&size)) {
-        // Grumble. Check the error.
-        DWORD e = GetLastError();
-        if (e == ERROR_INSUFFICIENT_BUFFER)
-            s.reserve(size);
-        else
-            break;
-    }
-    if (bRequired && s.empty())
-        log(SPRequest::SPError, string("missing required server variable: ") + lpszVariable);
-  }
-
-  void GetHeader(LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true) const {
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!m_pn->GetHeader(m_pfc,lpszName,s,&size)) {
-        // Grumble. Check the error.
-        DWORD e = GetLastError();
-        if (e == ERROR_INSUFFICIENT_BUFFER)
-            s.reserve(size);
-        else
-            break;
-    }
-    if (bRequired && s.empty())
-        log(SPRequest::SPError, string("missing required header: ") + lpszName);
-  }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
-    static char _status[] = "200 OK";
-    static char ctype[] = "Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,_status,(ULONG_PTR)ctype,0);
-    static char xmsg[] = "<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
-                            "<H1>Shibboleth Filter Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    pfc->WriteClient(pfc,xmsg,&resplen,0);
-    resplen=strlen(msg);
-    pfc->WriteClient(pfc,const_cast<char*>(msg),&resplen,0);
-    static char xmsg2[] = "</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    pfc->WriteClient(pfc,xmsg2,&resplen,0);
-    return SF_STATUS_REQ_FINISHED;
-}
-
-void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {
-        // Grumble. Check the error.
-        DWORD e=GetLastError();
-        if (e==ERROR_INSUFFICIENT_BUFFER)
-            s.reserve(size);
-        else
-            break;
-    }
-    if (bRequired && s.empty()) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("missing server variable: %s", lpszVariable);
-    }
-}
-
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
-    static char _INSTANCE_ID[] = "INSTANCE_ID";
-    static char _ShibSpoofCheck[] = "ShibSpoofCheck:";
-
-    // Is this a log notification?
-    if (notificationType == SF_NOTIFY_LOG) {
-        if (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 {
-        // Determine web site number. This can't really fail, I don't think.
-        dynabuf buf(128);
-        GetServerVariable(pfc,_INSTANCE_ID,buf,10);
-        if (buf.empty())
-            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())
-            return SF_STATUS_REQ_NEXT_NOTIFICATION;
-
-        string threadid("[");
-        threadid += lexical_cast<string>(getpid()) + "] isapi_shib";
-        xmltooling::NDC ndc(threadid.c_str());
-
-        ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
-        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
-        if (!g_spoofKey.empty())
-            pn->SetHeader(pfc, _ShibSpoofCheck, const_cast<char*>(g_spoofKey.c_str()));
-        if (res.first) return res.second;
-
-        res = stf.getServiceProvider().doExport(stf);
-        if (res.first) return res.second;
-
-        res = stf.getServiceProvider().doAuthorization(stf);
-        if (res.first) return res.second;
-
-        return SF_STATUS_REQ_NEXT_NOTIFICATION;
-    }
-    catch(const bad_alloc&) {
-        return WriteClientError(pfc, "Out of Memory");
-    }
-    catch(long e) {
-        if (e==ERROR_NO_DATA)
-            return WriteClientError(pfc, "A required variable or header was empty.");
-        else
-            return WriteClientError(pfc, "Shibboleth Filter detected unexpected IIS error.");
-    }
-    catch (const std::exception& e) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("ISAPI filter caught an exception: %s", e.what());
-        return WriteClientError(pfc, "Shibboleth Filter caught an exception, check Event Log for details.");
-    }
-    catch(...) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").crit("ISAPI extension caught an unknown exception");
-        if (g_catchAll)
-            return WriteClientError(pfc, "Shibboleth Filter threw an unknown exception.");
-        throw;
-    }
-    return WriteClientError(pfc, "Shibboleth Filter reached unreachable code, save my walrus!");
-}
-
-
-/****************************************************************************/
-// ISAPI Extension
-
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)
-{
-    static char _status[] = "200 OK";
-    static char ctype[] = "Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,_status,0,(LPDWORD)ctype);
-    static char xmsg[] = "<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    lpECB->WriteClient(lpECB->ConnID,xmsg,&resplen,HSE_IO_SYNC);
-    resplen=strlen(msg);
-    lpECB->WriteClient(lpECB->ConnID,const_cast<char*>(msg),&resplen,HSE_IO_SYNC);
-    static char xmsg2[] = "</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    lpECB->WriteClient(lpECB->ConnID,xmsg2,&resplen,HSE_IO_SYNC);
-    return HSE_STATUS_SUCCESS;
-}
-
-
-class ShibTargetIsapiE : public AbstractSPRequest
-{
-  LPEXTENSION_CONTROL_BLOCK m_lpECB;
-  multimap<string,string> m_headers;
-  mutable vector<string> m_certs;
-  mutable string m_body;
-  mutable bool m_gotBody;
-  int m_port;
-  string m_scheme,m_hostname,m_uri;
-  mutable string m_remote_addr,m_remote_user;
-
-public:
-  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)
-      : AbstractSPRequest(SHIBSP_LOGCAT ".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {
-    static char _HTTPS[] = "HTTPS";
-    static char _URL[] = "URL";
-    static char _SERVER_PORT[] = "SERVER_PORT";
-    static char _SERVER_NAME[] = "SERVER_NAME";
-
-    dynabuf ssl(5);
-    GetServerVariable(_HTTPS,ssl,5);
-    bool SSL=(ssl=="on" || ssl=="ON");
-
-    // Scheme may come from site def or be derived from IIS.
-    m_scheme = site.m_scheme;
-    if (m_scheme.empty() || !g_bNormalizeRequest)
-        m_scheme = SSL ? "https" : "http";
-
-    // URL path always come from IIS.
-    dynabuf url(256);
-    GetServerVariable(_URL,url,255);
-
-    // Port may come from IIS or from site def.
-    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty())) {
-        dynabuf port(11);
-        GetServerVariable(_SERVER_PORT,port,10);
-        if (port.empty()) {
-            m_port = SSL ? 443 : 80;
-        }
-        else {
-            m_port = atoi(port);
-        }
-    }
-    else if (SSL) {
-        m_port = atoi(site.m_sslport.c_str());
-    }
-    else {
-        m_port = atoi(site.m_port.c_str());
-    }
-
-    dynabuf var(32);
-    GetServerVariable(_SERVER_NAME, var, 32);
-    if (var.empty()) {
-        m_hostname = site.m_name;
-    }
-    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;
-    }
-
-    /*
-     * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if
-     * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",
-     * which is the default. No perfect way to tell, but we can take a good guess by checking
-     * whether the URL is a substring of the PATH_INFO:
-     *
-     * e.g. for /Shibboleth.sso/SAML/POST
-     *
-     *  Bad mode (default):
-     *      URL:        /Shibboleth.sso
-     *      PathInfo:   /Shibboleth.sso/SAML/POST
-     *
-     *  Good mode:
-     *      URL:        /Shibboleth.sso
-     *      PathInfo:   /SAML/POST
-     */
-
-    string uri;
-
-    // Clearly we're only in bad mode if path info exists at all.
-    if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {
-        if (strstr(lpECB->lpszPathInfo,url))
-            // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.
-            uri = lpECB->lpszPathInfo;
-        else {
-            if (!url.empty())
-                uri = url;
-            uri += lpECB->lpszPathInfo;
-        }
-    }
-    else if (!url.empty()) {
-        uri = url;
-    }
-
-    // For consistency with Apache, let's add the query string.
-    if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {
-        uri += '?';
-        uri += lpECB->lpszQueryString;
-    }
-
-    setRequestURI(uri.c_str());
-  }
-  ~ShibTargetIsapiE() {}
-
-  const char* getScheme() const {
-    return m_scheme.c_str();
-  }
-  const char* getHostname() const {
-    return m_hostname.c_str();
-  }
-  int getPort() const {
-    return m_port;
-  }
-  const char* getMethod() const {
-    return m_lpECB->lpszMethod;
-  }
-  string getContentType() const {
-    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";
-  }
-  long getContentLength() const {
-      return m_lpECB->cbTotalBytes;
-  }
-  string getRemoteUser() const {
-    static char _REMOTE_USER[] = "REMOTE_USER";
-    if (m_remote_user.empty()) {
-        dynabuf var(16);
-        GetServerVariable(_REMOTE_USER, var, 32, false);
-        if (!var.empty())
-            m_remote_user = var;
-    }
-    return m_remote_user;
-  }
-  string getRemoteAddr() const {
-      static char _REMOTE_ADDR[] = "REMOTE_ADDR";
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(_REMOTE_ADDR, var, 16, false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  string getHeader(const char* name) const {
-    string hdr("HTTP_");
-    for (; *name; ++name) {
-        if (*name == '-')
-            hdr += '_';
-        else
-            hdr += toupper(*name);
-    }
-    dynabuf buf(128);
-    GetServerVariable(const_cast<char*>(hdr.c_str()), buf, 128, false);
-    return buf.empty() ? "" : static_cast<char*>(buf);
-  }
-  void setResponseHeader(const char* name, const char* value, bool replace = false) {
-      HTTPResponse::setResponseHeader(name, value, replace);
-      if (name && *name) {
-          // Set for later.
-          if (replace || !value)
-              m_headers.erase(name);
-          if (value && *value)
-              m_headers.insert(make_pair(name, value));
-      }
-  }
-  const char* getQueryString() const {
-    return m_lpECB->lpszQueryString;
-  }
-  const char* getRequestBody() const {
-    if (m_gotBody)
-        return m_body.c_str();
-    if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?
-        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");
-    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {
-      m_gotBody=true;
-      DWORD datalen=m_lpECB->cbTotalBytes;
-      if (m_lpECB->cbAvailable > 0) {
-        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
-        datalen-=m_lpECB->cbAvailable;
-      }
-      char buf[8192];
-      while (datalen) {
-        DWORD buflen=8192;
-        BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);
-        if (!ret) {
-            char message[65];
-            _snprintf(message, 64, "Error reading request body from browser (%x).", GetLastError());
-            throw IOException(message);
-        }
-        else if (!buflen)
-            throw IOException("Socket closed while reading request body from browser.");
-        m_body.append(buf, buflen);
-        datalen-=buflen;
-      }
-    }
-    else if (m_lpECB->cbAvailable) {
-        m_gotBody=true;
-        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);
-    }
-    return m_body.c_str();
-  }
-  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)
-        hdr += i->first + ": " + i->second + "\r\n";
-    hdr += "\r\n";
-
-    static char okstr[] = "200 OK";
-    static char notmodstr[] = "304 Not Modified";
-    static char authzstr[] = "401 Authorization Required";
-    static char forbiddenstr[] = "403 Forbidden";
-    static char notfoundstr[] = "404 Not Found";
-    static char errorstr[] = "500 Server Error";
-    
-    char* str = nullptr;
-
-    switch (status) {
-        case XMLTOOLING_HTTP_STATUS_NOTMODIFIED:    str = notmodstr; break;
-        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   str = authzstr; break;
-        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      str = forbiddenstr; break;
-        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       str = notfoundstr; break;
-        case XMLTOOLING_HTTP_STATUS_ERROR:          str = errorstr; break;
-
-        default: str = okstr;
-    }
-    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, str, 0, (LPDWORD)hdr.c_str());
-    char buf[1024];
-    while (in) {
-        in.read(buf,1024);
-        DWORD resplen = in.gcount();
-        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);
-    }
-    return HSE_STATUS_SUCCESS;
-  }
-  long sendRedirect(const char* url) {
-    static char _status[] = "302 Moved";
-
-    HTTPResponse::sendRedirect(url);
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "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)
-        hdr += i->first + ": " + i->second + "\r\n";
-    hdr += "\r\n";
-    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, _status, 0, (LPDWORD)hdr.c_str());
-    static char redmsg[] = "<HTML><BODY>Redirecting...</BODY></HTML>";
-    DWORD resplen=40;
-    m_lpECB->WriteClient(m_lpECB->ConnID, redmsg, &resplen, HSE_IO_SYNC);
-    return HSE_STATUS_SUCCESS;
-  }
-  // 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(
-        m_lpECB,
-        "ISAPI extension can only be invoked to process Shibboleth protocol requests."
-		"Make sure the mapped file extension doesn't match actual content."
-        );
-  }
-  long returnOK() {
-      return HSE_STATUS_SUCCESS;
-  }
-
-  const vector<string>& getClientCertificates() const {
-      if (m_certs.empty()) {
-        char CertificateBuf[8192];
-        CERT_CONTEXT_EX ccex;
-        ccex.cbAllocated = sizeof(CertificateBuf);
-        ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;
-        DWORD dwSize = sizeof(ccex);
-
-        if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, nullptr)) {
-            if (ccex.CertContext.cbCertEncoded) {
-                XMLSize_t outlen;
-                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
-                m_certs.push_back(reinterpret_cast<char*>(serialized));
-                XMLString::release((char**)&serialized);
-            }
-        }
-      }
-      return m_certs;
-  }
-
-  // Not used in the extension.
-  void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }
-  void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }
-  void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }
-
-  void GetServerVariable(LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true) const {
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!m_lpECB->GetServerVariable(m_lpECB->ConnID,lpszVariable,s,&size)) {
-        // Grumble. Check the error.
-        DWORD e=GetLastError();
-        if (e==ERROR_INSUFFICIENT_BUFFER)
-            s.reserve(size);
-        else
-            break;
-    }
-    if (bRequired && s.empty()) {
-        log(SPRequest::SPError, string("missing required server variable: ") + lpszVariable);
-    }
-  }
-};
-
-void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {
-        // Grumble. Check the error.
-        DWORD e=GetLastError();
-        if (e==ERROR_INSUFFICIENT_BUFFER)
-            s.reserve(size);
-        else
-            break;
-    }
-    if (bRequired && s.empty()) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("missing required server variable: %s", lpszVariable);
-    }
-}
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
-    static char _INSTANCE_ID[] = "INSTANCE_ID";
-
-    try {
-        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);
-        GetServerVariable(lpECB,_INSTANCE_ID,buf,10);
-        if (buf.empty())
-            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())
-            return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check ISAPI mappings in SP configuration).");
-
-        ShibTargetIsapiE ste(lpECB, map_i->second);
-        pair<bool,long> res = ste.getServiceProvider().doHandler(ste);
-        if (res.first) return res.second;
-
-        return WriteClientError(lpECB, "Shibboleth Extension failed to process request");
-
-    }
-    catch(const bad_alloc&) {
-        return WriteClientError(lpECB, "Out of Memory");
-    }
-    catch(long e) {
-        if (e==ERROR_NO_DATA)
-            return WriteClientError(lpECB, "A required variable or header was empty.");
-        else
-            return WriteClientError(lpECB, "Server detected unexpected IIS error.");
-    }
-    catch (const std::exception& e) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").error("ISAPI extension caught an exception: %s", e.what());
-        return WriteClientError(lpECB, "Shibboleth Extension caught an exception, check native log for details.");
-    }
-    catch(...) {
-        Category::getInstance(SHIBSP_LOGCAT ".ISAPI").crit("ISAPI filter caught an unknown exception");
-        if (g_catchAll)
-            return WriteClientError(lpECB, "Shibboleth Extension threw an unknown exception.");
-        throw;
-    }
-
-    // If we get here we've got an error.
-    return HSE_STATUS_ERROR;
-}
diff --git a/isapi_shib/isapi_shib.rc b/isapi_shib/isapi_shib.rc
deleted file mode 100644
index 7f1751a4..00000000
--- a/isapi_shib/isapi_shib.rc
+++ /dev/null
@@ -1,96 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (United States) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth ISAPI Filter / Extension"
-            VALUE "InternalName", "isapi_shib"
-            VALUE "OriginalFilename", "isapi_shib.dll"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (United States) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/isapi_shib/resource.h b/isapi_shib/resource.h
deleted file mode 100644
index 74732329..00000000
--- a/isapi_shib/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by isapi_shib.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 00000000..528592d0
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,1071 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11', '14', '17', '20', or
+#   '23' for the respective C++ standard version.
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for no added switch, and then for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz at redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw at panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr at ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov at google.com>
+#   Copyright (c) 2015 Paul Norman <penorman at mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz at klammler.eu>
+#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz at gmail.com>
+#   Copyright (c) 2019 Enji Cooper <yaneurabeya at gmail.com>
+#   Copyright (c) 2020 Jason Merrill <jason at redhat.com>
+#   Copyright (c) 2021, 2024 Jörn Heusipp <osmanx at problemloesungsmaschine.de>
+#   Copyright (c) 2015, 2022, 2023, 2024 Olly Betts
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 25
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+        [$1], [20], [ax_cxx_compile_alternatives="20"],
+        [$1], [23], [ax_cxx_compile_alternatives="23"],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+
+  m4_if([$2], [], [dnl
+    AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+		   ax_cv_cxx_compile_cxx$1,
+      [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+        [ax_cv_cxx_compile_cxx$1=yes],
+        [ax_cv_cxx_compile_cxx$1=no])])
+    if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+      ac_success=yes
+    fi])
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    dnl MSVC needs -std:c++NN for C++17 and later (default is C++14)
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do
+        if test x"$switch" = xMSVC; then
+          dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide
+          dnl with -std=c++17.  We suffix the cache variable name with _MSVC to
+          dnl avoid this.
+          switch=-std:c++${alternative}
+          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC])
+        else
+          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+        fi
+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                       $cachevar,
+          [ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+            [eval $cachevar=yes],
+            [eval $cachevar=no])
+           CXX="$ac_save_CXX"])
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11]
+)
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14]
+)
+
+dnl  Test body for checking C++17 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17]
+)
+
+dnl  Test body for checking C++20 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
+  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_20]
+)
+
+dnl  Test body for checking C++23 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_23],
+  [_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_20
+   _AX_CXX_COMPILE_STDCXX_testbody_new_in_23]
+)
+
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+// MSVC always sets __cplusplus to 199711L in older versions; newer versions
+// only set it correctly if /Zc:__cplusplus is specified as well as a
+// /std:c++NN switch:
+//
+// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
+//
+// The value __cplusplus ought to have is available in _MSVC_LANG since
+// Visual Studio 2015 Update 3:
+//
+// https://learn.microsoft.com/en-us/cpp/preprocessor/predefined-macros
+//
+// This was also the first MSVC version to support C++14 so we can't use the
+// value of either __cplusplus or _MSVC_LANG to quickly rule out MSVC having
+// C++11 or C++14 support, but we can check _MSVC_LANG for C++17 and later.
+#elif __cplusplus < 201103L && !defined _MSC_VER
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual ~Base() {}
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual ~Derived() override {}
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L && !defined _MSC_VER
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_separators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
+
+
+dnl  Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+  namespace test_constexpr_lambdas
+  {
+
+    constexpr int foo = [](){return 42;}();
+
+  }
+
+  namespace test::nested_namespace::definitions
+  {
+
+  }
+
+  namespace test_fold_expression
+  {
+
+    template<typename... Args>
+    int multiply(Args... args)
+    {
+      return (args * ... * 1);
+    }
+
+    template<typename... Args>
+    bool all(Args... args)
+    {
+      return (args && ...);
+    }
+
+  }
+
+  namespace test_extended_static_assert
+  {
+
+    static_assert (true);
+
+  }
+
+  namespace test_auto_brace_init_list
+  {
+
+    auto foo = {5};
+    auto bar {5};
+
+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+    static_assert(std::is_same<int, decltype(bar)>::value);
+  }
+
+  namespace test_typename_in_template_template_parameter
+  {
+
+    template<template<typename> typename X> struct D;
+
+  }
+
+  namespace test_fallthrough_nodiscard_maybe_unused_attributes
+  {
+
+    int f1()
+    {
+      return 42;
+    }
+
+    [[nodiscard]] int f2()
+    {
+      [[maybe_unused]] auto unused = f1();
+
+      switch (f1())
+      {
+      case 17:
+        f1();
+        [[fallthrough]];
+      case 42:
+        f1();
+      }
+      return f1();
+    }
+
+  }
+
+  namespace test_extended_aggregate_initialization
+  {
+
+    struct base1
+    {
+      int b1, b2 = 42;
+    };
+
+    struct base2
+    {
+      base2() {
+        b3 = 42;
+      }
+      int b3;
+    };
+
+    struct derived : base1, base2
+    {
+        int d;
+    };
+
+    derived d1 {{1, 2}, {}, 4};  // full initialization
+    derived d2 {{}, {}, 4};      // value-initialized bases
+
+  }
+
+  namespace test_general_range_based_for_loop
+  {
+
+    struct iter
+    {
+      int i;
+
+      int& operator* ()
+      {
+        return i;
+      }
+
+      const int& operator* () const
+      {
+        return i;
+      }
+
+      iter& operator++()
+      {
+        ++i;
+        return *this;
+      }
+    };
+
+    struct sentinel
+    {
+      int i;
+    };
+
+    bool operator== (const iter& i, const sentinel& s)
+    {
+      return i.i == s.i;
+    }
+
+    bool operator!= (const iter& i, const sentinel& s)
+    {
+      return !(i == s);
+    }
+
+    struct range
+    {
+      iter begin() const
+      {
+        return {0};
+      }
+
+      sentinel end() const
+      {
+        return {5};
+      }
+    };
+
+    void f()
+    {
+      range r {};
+
+      for (auto i : r)
+      {
+        [[maybe_unused]] auto v = i;
+      }
+    }
+
+  }
+
+  namespace test_lambda_capture_asterisk_this_by_value
+  {
+
+    struct t
+    {
+      int i;
+      int foo()
+      {
+        return [*this]()
+        {
+          return i;
+        }();
+      }
+    };
+
+  }
+
+  namespace test_enum_class_construction
+  {
+
+    enum class byte : unsigned char
+    {};
+
+    byte foo {42};
+
+  }
+
+  namespace test_constexpr_if
+  {
+
+    template <bool cond>
+    int f ()
+    {
+      if constexpr(cond)
+      {
+        return 13;
+      }
+      else
+      {
+        return 42;
+      }
+    }
+
+  }
+
+  namespace test_selection_statement_with_initializer
+  {
+
+    int f()
+    {
+      return 13;
+    }
+
+    int f2()
+    {
+      if (auto i = f(); i > 0)
+      {
+        return 3;
+      }
+
+      switch (auto i = f(); i + 4)
+      {
+      case 17:
+        return 2;
+
+      default:
+        return 1;
+      }
+    }
+
+  }
+
+  namespace test_template_argument_deduction_for_class_templates
+  {
+
+    template <typename T1, typename T2>
+    struct pair
+    {
+      pair (T1 p1, T2 p2)
+        : m1 {p1},
+          m2 {p2}
+      {}
+
+      T1 m1;
+      T2 m2;
+    };
+
+    void f()
+    {
+      [[maybe_unused]] auto p = pair{13, 42u};
+    }
+
+  }
+
+  namespace test_non_type_auto_template_parameters
+  {
+
+    template <auto n>
+    struct B
+    {};
+
+    B<5> b1;
+    B<'a'> b2;
+
+  }
+
+  namespace test_structured_bindings
+  {
+
+    int arr[2] = { 1, 2 };
+    std::pair<int, int> pr = { 1, 2 };
+
+    auto f1() -> int(&)[2]
+    {
+      return arr;
+    }
+
+    auto f2() -> std::pair<int, int>&
+    {
+      return pr;
+    }
+
+    struct S
+    {
+      int x1 : 2;
+      volatile double y1;
+    };
+
+    S f3()
+    {
+      return {};
+    }
+
+    auto [ x1, y1 ] = f1();
+    auto& [ xr1, yr1 ] = f1();
+    auto [ x2, y2 ] = f2();
+    auto& [ xr2, yr2 ] = f2();
+    const auto [ x3, y3 ] = f3();
+
+  }
+
+  namespace test_exception_spec_type_system
+  {
+
+    struct Good {};
+    struct Bad {};
+
+    void g1() noexcept;
+    void g2();
+
+    template<typename T>
+    Bad
+    f(T*, T*);
+
+    template<typename T1, typename T2>
+    Good
+    f(T1*, T2*);
+
+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+  }
+
+  namespace test_inline_variables
+  {
+
+    template<class T> void f(T)
+    {}
+
+    template<class T> inline T g(T)
+    {
+      return T{};
+    }
+
+    template<> inline void f<>(int)
+    {}
+
+    template<> int g<>(int)
+    {
+      return 5;
+    }
+
+  }
+
+}  // namespace cxx17
+
+#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 201703L
+
+]])
+
+
+dnl  Tests for new features in C++20
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L
+
+#error "This is not a C++20 compiler"
+
+#else
+
+#include <version>
+
+namespace cxx20
+{
+
+// As C++20 supports feature test macros in the standard, there is no
+// immediate need to actually test for feature availability on the
+// Autoconf side.
+
+}  // namespace cxx20
+
+#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202002L
+
+]])
+
+
+dnl  Tests for new features in C++23
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_23], [[
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L
+
+#error "This is not a C++23 compiler"
+
+#else
+
+#include <version>
+
+namespace cxx23
+{
+
+// As C++23 supports feature test macros in the standard, there is no
+// immediate need to actually test for feature availability on the
+// Autoconf side.
+
+}  // namespace cxx23
+
+#endif  // (defined _MSVC_LANG ? _MSVC_LANG : __cplusplus) < 202302L
+
+]])
+
diff --git a/m4/doxygen.m4 b/m4/doxygen.m4
deleted file mode 100644
index a44060cb..00000000
--- a/m4/doxygen.m4
+++ /dev/null
@@ -1,537 +0,0 @@
-# ===========================================================================
-#      http://www.gnu.org/software/autoconf-archive/ax_prog_doxygen.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   DX_INIT_DOXYGEN(PROJECT-NAME, DOXYFILE-PATH, [OUTPUT-DIR])
-#   DX_DOXYGEN_FEATURE(ON|OFF)
-#   DX_DOT_FEATURE(ON|OFF)
-#   DX_HTML_FEATURE(ON|OFF)
-#   DX_CHM_FEATURE(ON|OFF)
-#   DX_CHI_FEATURE(ON|OFF)
-#   DX_MAN_FEATURE(ON|OFF)
-#   DX_RTF_FEATURE(ON|OFF)
-#   DX_XML_FEATURE(ON|OFF)
-#   DX_PDF_FEATURE(ON|OFF)
-#   DX_PS_FEATURE(ON|OFF)
-#
-# DESCRIPTION
-#
-#   The DX_*_FEATURE macros control the default setting for the given
-#   Doxygen feature. Supported features are 'DOXYGEN' itself, 'DOT' for
-#   generating graphics, 'HTML' for plain HTML, 'CHM' for compressed HTML
-#   help (for MS users), 'CHI' for generating a seperate .chi file by the
-#   .chm file, and 'MAN', 'RTF', 'XML', 'PDF' and 'PS' for the appropriate
-#   output formats. The environment variable DOXYGEN_PAPER_SIZE may be
-#   specified to override the default 'a4wide' paper size.
-#
-#   By default, HTML, PDF and PS documentation is generated as this seems to
-#   be the most popular and portable combination. MAN pages created by
-#   Doxygen are usually problematic, though by picking an appropriate subset
-#   and doing some massaging they might be better than nothing. CHM and RTF
-#   are specific for MS (note that you can't generate both HTML and CHM at
-#   the same time). The XML is rather useless unless you apply specialized
-#   post-processing to it.
-#
-#   The macros mainly control the default state of the feature. The use can
-#   override the default by specifying --enable or --disable. The macros
-#   ensure that contradictory flags are not given (e.g.,
-#   --enable-doxygen-html and --enable-doxygen-chm,
-#   --enable-doxygen-anything with --disable-doxygen, etc.) Finally, each
-#   feature will be automatically disabled (with a warning) if the required
-#   programs are missing.
-#
-#   Once all the feature defaults have been specified, call DX_INIT_DOXYGEN
-#   with the following parameters: a one-word name for the project for use
-#   as a filename base etc., an optional configuration file name (the
-#   default is 'Doxyfile', the same as Doxygen's default), and an optional
-#   output directory name (the default is 'doxygen-doc').
-#
-#   Automake Support
-#
-#   The following is a template aminclude.am file for use with Automake.
-#   Make targets and variables values are controlled by the various
-#   DX_COND_* conditionals set by autoconf.
-#
-#   The provided targets are:
-#
-#     doxygen-doc: Generate all doxygen documentation.
-#
-#     doxygen-run: Run doxygen, which will generate some of the
-#                  documentation (HTML, CHM, CHI, MAN, RTF, XML)
-#                  but will not do the post processing required
-#                  for the rest of it (PS, PDF, and some MAN).
-#
-#     doxygen-man: Rename some doxygen generated man pages.
-#
-#     doxygen-ps:  Generate doxygen PostScript documentation.
-#
-#     doxygen-pdf: Generate doxygen PDF documentation.
-#
-#   Note that by default these are not integrated into the automake targets.
-#   If doxygen is used to generate man pages, you can achieve this
-#   integration by setting man3_MANS to the list of man pages generated and
-#   then adding the dependency:
-#
-#     $(man3_MANS): doxygen-doc
-#
-#   This will cause make to run doxygen and generate all the documentation.
-#
-#   The following variable is intended for use in Makefile.am:
-#
-#     DX_CLEANFILES = everything to clean.
-#
-#   Then add this variable to MOSTLYCLEANFILES.
-#
-#     ----- begin aminclude.am -------------------------------------
-#
-#     ## --------------------------------- ##
-#     ## Format-independent Doxygen rules. ##
-#     ## --------------------------------- ##
-#
-#     if DX_COND_doc
-#
-#     ## ------------------------------- ##
-#     ## Rules specific for HTML output. ##
-#     ## ------------------------------- ##
-#
-#     if DX_COND_html
-#
-#     DX_CLEAN_HTML = @DX_DOCDIR@/html
-#
-#     endif DX_COND_html
-#
-#     ## ------------------------------ ##
-#     ## Rules specific for CHM output. ##
-#     ## ------------------------------ ##
-#
-#     if DX_COND_chm
-#
-#     DX_CLEAN_CHM = @DX_DOCDIR@/chm
-#
-#     if DX_COND_chi
-#
-#     DX_CLEAN_CHI = @DX_DOCDIR@/@PACKAGE at .chi
-#
-#     endif DX_COND_chi
-#
-#     endif DX_COND_chm
-#
-#     ## ------------------------------ ##
-#     ## Rules specific for MAN output. ##
-#     ## ------------------------------ ##
-#
-#     if DX_COND_man
-#
-#     DX_CLEAN_MAN = @DX_DOCDIR@/man
-#
-#     endif DX_COND_man
-#
-#     ## ------------------------------ ##
-#     ## Rules specific for RTF output. ##
-#     ## ------------------------------ ##
-#
-#     if DX_COND_rtf
-#
-#     DX_CLEAN_RTF = @DX_DOCDIR@/rtf
-#
-#     endif DX_COND_rtf
-#
-#     ## ------------------------------ ##
-#     ## Rules specific for XML output. ##
-#     ## ------------------------------ ##
-#
-#     if DX_COND_xml
-#
-#     DX_CLEAN_XML = @DX_DOCDIR@/xml
-#
-#     endif DX_COND_xml
-#
-#     ## ----------------------------- ##
-#     ## Rules specific for PS output. ##
-#     ## ----------------------------- ##
-#
-#     if DX_COND_ps
-#
-#     DX_CLEAN_PS = @DX_DOCDIR@/@PACKAGE at .ps
-#
-#     DX_PS_GOAL = doxygen-ps
-#
-#     doxygen-ps: @DX_DOCDIR@/@PACKAGE at .ps
-#
-#     @DX_DOCDIR@/@PACKAGE at .ps: @DX_DOCDIR@/@PACKAGE at .tag
-#         cd @DX_DOCDIR@/latex; \
-#         rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-#         $(DX_LATEX) refman.tex; \
-#         $(MAKEINDEX_PATH) refman.idx; \
-#         $(DX_LATEX) refman.tex; \
-#         countdown=5; \
-#         while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-#                           refman.log > /dev/null 2>&1 \
-#            && test $$countdown -gt 0; do \
-#             $(DX_LATEX) refman.tex; \
-#             countdown=`expr $$countdown - 1`; \
-#         done; \
-#         $(DX_DVIPS) -o ../@PACKAGE at .ps refman.dvi
-#
-#     endif DX_COND_ps
-#
-#     ## ------------------------------ ##
-#     ## Rules specific for PDF output. ##
-#     ## ------------------------------ ##
-#
-#     if DX_COND_pdf
-#
-#     DX_CLEAN_PDF = @DX_DOCDIR@/@PACKAGE at .pdf
-#
-#     DX_PDF_GOAL = doxygen-pdf
-#
-#     doxygen-pdf: @DX_DOCDIR@/@PACKAGE at .pdf
-#
-#     @DX_DOCDIR@/@PACKAGE at .pdf: @DX_DOCDIR@/@PACKAGE at .tag
-#         cd @DX_DOCDIR@/latex; \
-#         rm -f *.aux *.toc *.idx *.ind *.ilg *.log *.out; \
-#         $(DX_PDFLATEX) refman.tex; \
-#         $(DX_MAKEINDEX) refman.idx; \
-#         $(DX_PDFLATEX) refman.tex; \
-#         countdown=5; \
-#         while $(DX_EGREP) 'Rerun (LaTeX|to get cross-references right)' \
-#                           refman.log > /dev/null 2>&1 \
-#            && test $$countdown -gt 0; do \
-#             $(DX_PDFLATEX) refman.tex; \
-#             countdown=`expr $$countdown - 1`; \
-#         done; \
-#         mv refman.pdf ../@PACKAGE at .pdf
-#
-#     endif DX_COND_pdf
-#
-#     ## ------------------------------------------------- ##
-#     ## Rules specific for LaTeX (shared for PS and PDF). ##
-#     ## ------------------------------------------------- ##
-#
-#     if DX_COND_latex
-#
-#     DX_CLEAN_LATEX = @DX_DOCDIR@/latex
-#
-#     endif DX_COND_latex
-#
-#     .PHONY: doxygen-run doxygen-doc $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-#     .INTERMEDIATE: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-#     doxygen-run: @DX_DOCDIR@/@PACKAGE at .tag
-#
-#     doxygen-doc: doxygen-run $(DX_PS_GOAL) $(DX_PDF_GOAL)
-#
-#     @DX_DOCDIR@/@PACKAGE at .tag: $(DX_CONFIG) $(pkginclude_HEADERS)
-#         rm -rf @DX_DOCDIR@
-#         $(DX_ENV) $(DX_DOXYGEN) $(srcdir)/$(DX_CONFIG)
-#
-#     DX_CLEANFILES = \
-#         @DX_DOCDIR@/@PACKAGE at .tag \
-#         -r \
-#         $(DX_CLEAN_HTML) \
-#         $(DX_CLEAN_CHM) \
-#         $(DX_CLEAN_CHI) \
-#         $(DX_CLEAN_MAN) \
-#         $(DX_CLEAN_RTF) \
-#         $(DX_CLEAN_XML) \
-#         $(DX_CLEAN_PS) \
-#         $(DX_CLEAN_PDF) \
-#         $(DX_CLEAN_LATEX)
-#
-#     endif DX_COND_doc
-#
-#     ----- end aminclude.am ---------------------------------------
-#
-# LICENSE
-#
-#   Copyright (c) 2009 Oren Ben-Kiki <oren at ben-kiki.org>
-#
-#   Copying and distribution of this file, with or without modification, are
-#   permitted in any medium without royalty provided the copyright notice
-#   and this notice are preserved. This file is offered as-is, without any
-#   warranty.
-
-#serial 11
-
-## ----------##
-## Defaults. ##
-## ----------##
-
-DX_ENV=""
-AC_DEFUN([DX_FEATURE_doc],  ON)
-AC_DEFUN([DX_FEATURE_dot],  OFF)
-AC_DEFUN([DX_FEATURE_man],  OFF)
-AC_DEFUN([DX_FEATURE_html], ON)
-AC_DEFUN([DX_FEATURE_chm],  OFF)
-AC_DEFUN([DX_FEATURE_chi],  OFF)
-AC_DEFUN([DX_FEATURE_rtf],  OFF)
-AC_DEFUN([DX_FEATURE_xml],  OFF)
-AC_DEFUN([DX_FEATURE_pdf],  ON)
-AC_DEFUN([DX_FEATURE_ps],   ON)
-
-# Compatibility with older autoconf versions.
-m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))])
-
-## --------------- ##
-## Private macros. ##
-## --------------- ##
-
-# DX_ENV_APPEND(VARIABLE, VALUE)
-# ------------------------------
-# Append VARIABLE="VALUE" to DX_ENV for invoking doxygen.
-AC_DEFUN([DX_ENV_APPEND], [AC_SUBST([DX_ENV], ["$DX_ENV $1='$2'"])])
-
-# DX_DIRNAME_EXPR
-# ---------------
-# Expand into a shell expression prints the directory part of a path.
-AC_DEFUN([DX_DIRNAME_EXPR],
-         [[expr ".$1" : '\(\.\)[^/]*$' \| "x$1" : 'x\(.*\)/[^/]*$']])
-
-# DX_IF_FEATURE(FEATURE, IF-ON, IF-OFF)
-# -------------------------------------
-# Expands according to the M4 (static) status of the feature.
-AC_DEFUN([DX_IF_FEATURE], [ifelse(DX_FEATURE_$1, ON, [$2], [$3])])
-
-# DX_REQUIRE_PROG(VARIABLE, PROGRAM)
-# ----------------------------------
-# Require the specified program to be found for the DX_CURRENT_FEATURE to work.
-AC_DEFUN([DX_REQUIRE_PROG], [
-AC_PATH_TOOL([$1], [$2])
-if test "$DX_FLAG_[]DX_CURRENT_FEATURE$$1" = 1; then
-    AC_MSG_WARN([$2 not found - will not DX_CURRENT_DESCRIPTION])
-    AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
-fi
-])
-
-# DX_TEST_FEATURE(FEATURE)
-# ------------------------
-# Expand to a shell expression testing whether the feature is active.
-AC_DEFUN([DX_TEST_FEATURE], [test "$DX_FLAG_$1" = 1])
-
-# DX_CHECK_DEPEND(REQUIRED_FEATURE, REQUIRED_STATE)
-# -------------------------------------------------
-# Verify that a required features has the right state before trying to turn on
-# the DX_CURRENT_FEATURE.
-AC_DEFUN([DX_CHECK_DEPEND], [
-test "$DX_FLAG_$1" = "$2" \
-|| AC_MSG_ERROR([doxygen-DX_CURRENT_FEATURE ifelse([$2], 1,
-                            requires, contradicts) doxygen-DX_CURRENT_FEATURE])
-])
-
-# DX_CLEAR_DEPEND(FEATURE, REQUIRED_FEATURE, REQUIRED_STATE)
-# ----------------------------------------------------------
-# Turn off the DX_CURRENT_FEATURE if the required feature is off.
-AC_DEFUN([DX_CLEAR_DEPEND], [
-test "$DX_FLAG_$1" = "$2" || AC_SUBST(DX_FLAG_[]DX_CURRENT_FEATURE, 0)
-])
-
-# DX_FEATURE_ARG(FEATURE, DESCRIPTION,
-#                CHECK_DEPEND, CLEAR_DEPEND,
-#                REQUIRE, DO-IF-ON, DO-IF-OFF)
-# --------------------------------------------
-# Parse the command-line option controlling a feature. CHECK_DEPEND is called
-# if the user explicitly turns the feature on (and invokes DX_CHECK_DEPEND),
-# otherwise CLEAR_DEPEND is called to turn off the default state if a required
-# feature is disabled (using DX_CLEAR_DEPEND). REQUIRE performs additional
-# requirement tests (DX_REQUIRE_PROG). Finally, an automake flag is set and
-# DO-IF-ON or DO-IF-OFF are called according to the final state of the feature.
-AC_DEFUN([DX_ARG_ABLE], [
-    AC_DEFUN([DX_CURRENT_FEATURE], [$1])
-    AC_DEFUN([DX_CURRENT_DESCRIPTION], [$2])
-    AC_ARG_ENABLE(doxygen-$1,
-                  [AS_HELP_STRING(DX_IF_FEATURE([$1], [--disable-doxygen-$1],
-                                                      [--enable-doxygen-$1]),
-                                  DX_IF_FEATURE([$1], [don't $2], [$2]))],
-                  [
-case "$enableval" in
-#(
-y|Y|yes|Yes|YES)
-    AC_SUBST([DX_FLAG_$1], 1)
-    $3
-;; #(
-n|N|no|No|NO)
-    AC_SUBST([DX_FLAG_$1], 0)
-;; #(
-*)
-    AC_MSG_ERROR([invalid value '$enableval' given to doxygen-$1])
-;;
-esac
-], [
-AC_SUBST([DX_FLAG_$1], [DX_IF_FEATURE([$1], 1, 0)])
-$4
-])
-if DX_TEST_FEATURE([$1]); then
-    $5
-    :
-fi
-if DX_TEST_FEATURE([$1]); then
-    AM_CONDITIONAL(DX_COND_$1, :)
-    $6
-    :
-else
-    AM_CONDITIONAL(DX_COND_$1, false)
-    $7
-    :
-fi
-])
-
-## -------------- ##
-## Public macros. ##
-## -------------- ##
-
-# DX_XXX_FEATURE(DEFAULT_STATE)
-# -----------------------------
-AC_DEFUN([DX_DOXYGEN_FEATURE], [AC_DEFUN([DX_FEATURE_doc],  [$1])])
-AC_DEFUN([DX_DOT_FEATURE],     [AC_DEFUN([DX_FEATURE_dot], [$1])])
-AC_DEFUN([DX_MAN_FEATURE],     [AC_DEFUN([DX_FEATURE_man],  [$1])])
-AC_DEFUN([DX_HTML_FEATURE],    [AC_DEFUN([DX_FEATURE_html], [$1])])
-AC_DEFUN([DX_CHM_FEATURE],     [AC_DEFUN([DX_FEATURE_chm],  [$1])])
-AC_DEFUN([DX_CHI_FEATURE],     [AC_DEFUN([DX_FEATURE_chi],  [$1])])
-AC_DEFUN([DX_RTF_FEATURE],     [AC_DEFUN([DX_FEATURE_rtf],  [$1])])
-AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
-AC_DEFUN([DX_XML_FEATURE],     [AC_DEFUN([DX_FEATURE_xml],  [$1])])
-AC_DEFUN([DX_PDF_FEATURE],     [AC_DEFUN([DX_FEATURE_pdf],  [$1])])
-AC_DEFUN([DX_PS_FEATURE],      [AC_DEFUN([DX_FEATURE_ps],   [$1])])
-
-# DX_INIT_DOXYGEN(PROJECT, [CONFIG-FILE], [OUTPUT-DOC-DIR])
-# ---------------------------------------------------------
-# PROJECT also serves as the base name for the documentation files.
-# The default CONFIG-FILE is "Doxyfile" and OUTPUT-DOC-DIR is "doxygen-doc".
-AC_DEFUN([DX_INIT_DOXYGEN], [
-
-# Files:
-AC_SUBST([DX_PROJECT], [$1])
-AC_SUBST([DX_CONFIG], [ifelse([$2], [], Doxyfile, [$2])])
-AC_SUBST([DX_DOCDIR], [ifelse([$3], [], doxygen-doc, [$3])])
-
-# Environment variables used inside doxygen.cfg:
-DX_ENV_APPEND(SRCDIR, $srcdir)
-DX_ENV_APPEND(PROJECT, $DX_PROJECT)
-DX_ENV_APPEND(DOCDIR, $DX_DOCDIR)
-DX_ENV_APPEND(VERSION, $PACKAGE_VERSION)
-
-# Doxygen itself:
-DX_ARG_ABLE(doc, [generate any doxygen documentation],
-            [],
-            [],
-            [DX_REQUIRE_PROG([DX_DOXYGEN], doxygen)
-             DX_REQUIRE_PROG([DX_PERL], perl)],
-            [DX_ENV_APPEND(PERL_PATH, $DX_PERL)])
-
-# Dot for graphics:
-DX_ARG_ABLE(dot, [generate graphics for doxygen documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [DX_REQUIRE_PROG([DX_DOT], dot)],
-            [DX_ENV_APPEND(HAVE_DOT, YES)
-             DX_ENV_APPEND(DOT_PATH, [`DX_DIRNAME_EXPR($DX_DOT)`])],
-            [DX_ENV_APPEND(HAVE_DOT, NO)])
-
-# Man pages generation:
-DX_ARG_ABLE(man, [generate doxygen manual pages],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [],
-            [DX_ENV_APPEND(GENERATE_MAN, YES)],
-            [DX_ENV_APPEND(GENERATE_MAN, NO)])
-
-# RTF file generation:
-DX_ARG_ABLE(rtf, [generate doxygen RTF documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [],
-            [DX_ENV_APPEND(GENERATE_RTF, YES)],
-            [DX_ENV_APPEND(GENERATE_RTF, NO)])
-
-# XML file generation:
-DX_ARG_ABLE(xml, [generate doxygen XML documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [],
-            [DX_ENV_APPEND(GENERATE_XML, YES)],
-            [DX_ENV_APPEND(GENERATE_XML, NO)])
-
-# (Compressed) HTML help generation:
-DX_ARG_ABLE(chm, [generate doxygen compressed HTML help documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [DX_REQUIRE_PROG([DX_HHC], hhc)],
-            [DX_ENV_APPEND(HHC_PATH, $DX_HHC)
-             DX_ENV_APPEND(GENERATE_HTML, YES)
-             DX_ENV_APPEND(GENERATE_HTMLHELP, YES)],
-            [DX_ENV_APPEND(GENERATE_HTMLHELP, NO)])
-
-# Seperate CHI file generation.
-DX_ARG_ABLE(chi, [generate doxygen seperate compressed HTML help index file],
-            [DX_CHECK_DEPEND(chm, 1)],
-            [DX_CLEAR_DEPEND(chm, 1)],
-            [],
-            [DX_ENV_APPEND(GENERATE_CHI, YES)],
-            [DX_ENV_APPEND(GENERATE_CHI, NO)])
-
-# Plain HTML pages generation:
-DX_ARG_ABLE(html, [generate doxygen plain HTML documentation],
-            [DX_CHECK_DEPEND(doc, 1) DX_CHECK_DEPEND(chm, 0)],
-            [DX_CLEAR_DEPEND(doc, 1) DX_CLEAR_DEPEND(chm, 0)],
-            [],
-            [DX_ENV_APPEND(GENERATE_HTML, YES)],
-            [DX_TEST_FEATURE(chm) || DX_ENV_APPEND(GENERATE_HTML, NO)])
-
-# PostScript file generation:
-DX_ARG_ABLE(ps, [generate doxygen PostScript documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [DX_REQUIRE_PROG([DX_LATEX], latex)
-             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
-             DX_REQUIRE_PROG([DX_DVIPS], dvips)
-             DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# PDF file generation:
-DX_ARG_ABLE(pdf, [generate doxygen PDF documentation],
-            [DX_CHECK_DEPEND(doc, 1)],
-            [DX_CLEAR_DEPEND(doc, 1)],
-            [DX_REQUIRE_PROG([DX_PDFLATEX], pdflatex)
-             DX_REQUIRE_PROG([DX_MAKEINDEX], makeindex)
-             DX_REQUIRE_PROG([DX_EGREP], egrep)])
-
-# LaTeX generation for PS and/or PDF:
-if DX_TEST_FEATURE(ps) || DX_TEST_FEATURE(pdf); then
-    AM_CONDITIONAL(DX_COND_latex, :)
-    DX_ENV_APPEND(GENERATE_LATEX, YES)
-else
-    AM_CONDITIONAL(DX_COND_latex, false)
-    DX_ENV_APPEND(GENERATE_LATEX, NO)
-fi
-
-# Paper size for PS and/or PDF:
-AC_ARG_VAR(DOXYGEN_PAPER_SIZE,
-           [a4wide (default), a4, letter, legal or executive])
-case "$DOXYGEN_PAPER_SIZE" in
-#(
-"")
-    AC_SUBST(DOXYGEN_PAPER_SIZE, "")
-;; #(
-a4wide|a4|letter|legal|executive)
-    DX_ENV_APPEND(PAPER_SIZE, $DOXYGEN_PAPER_SIZE)
-;; #(
-*)
-    AC_MSG_ERROR([unknown DOXYGEN_PAPER_SIZE='$DOXYGEN_PAPER_SIZE'])
-;;
-esac
-
-#For debugging:
-#echo DX_FLAG_doc=$DX_FLAG_doc
-#echo DX_FLAG_dot=$DX_FLAG_dot
-#echo DX_FLAG_man=$DX_FLAG_man
-#echo DX_FLAG_html=$DX_FLAG_html
-#echo DX_FLAG_chm=$DX_FLAG_chm
-#echo DX_FLAG_chi=$DX_FLAG_chi
-#echo DX_FLAG_rtf=$DX_FLAG_rtf
-#echo DX_FLAG_xml=$DX_FLAG_xml
-#echo DX_FLAG_pdf=$DX_FLAG_pdf
-#echo DX_FLAG_ps=$DX_FLAG_ps
-#echo DX_ENV=$DX_ENV
-])
\ No newline at end of file
diff --git a/memcache-store/Makefile.am b/memcache-store/Makefile.am
deleted file mode 100644
index a2cf4dc5..00000000
--- a/memcache-store/Makefile.am
+++ /dev/null
@@ -1,29 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = memcache-store.la
-
-memcache_store_la_LDFLAGS = $(MEMCACHED_LDFLAGS) -module -avoid-version
-memcache_store_la_CXXFLAGS = \
-	$(AM_CXXFLAGS) \
-	$(MEMCACHED_INCLUDE) \
-	$(BOOST_CPPFLAGS) \
-	$(PTHREAD_CFLAGS) \
-	$(log4cpp_CFLAGS) \
-	$(log4shib_CFLAGS) \
-	$(opensaml_CFLAGS) \
-	$(xerces_CFLAGS) \
-	$(xmltooling_CFLAGS)
-memcache_store_la_LIBADD = \
-	$(MEMCACHED_LIBS) \
-	$(PTHREAD_LIBS) \
-	$(log4cpp_LIBS) \
-	$(log4shib_LIBS) \
-	$(opensaml_LIBS) \
-	$(xerces_LIBS) \
-	$(xmltooling_LIBS)
-
-memcache_store_la_SOURCES = \
-	memcache-store.cpp
-
-EXTRA_DIST = memcache-store.rc resource.h
diff --git a/memcache-store/memcache-store.cpp b/memcache-store/memcache-store.cpp
deleted file mode 100644
index 98b4f4c0..00000000
--- a/memcache-store/memcache-store.cpp
+++ /dev/null
@@ -1,630 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/**
- * memcache-store.cpp
- *
- * Storage Service using memcache (pre memcache tags).
- */
-
-#if defined (_MSC_VER) || defined(__BORLANDC__)
-# include "config_win32.h"
-#else
-# include "config.h"
-#endif
-
-#ifdef WIN32
-# define _CRT_NONSTDC_NO_DEPRECATE 1
-# define _CRT_SECURE_NO_DEPRECATE 1
-# define MCEXT_EXPORTS __declspec(dllexport)
-#else
-# define MCEXT_EXPORTS
-#endif
-
-#include <xmltooling/base.h>
-
-#include <list>
-#include <iostream> 
-#include <libmemcached/memcached.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <xmltooling/logging.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/StorageService.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLHelper.h>
-
-using namespace xmltooling::logging;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-namespace {
-    static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);
-    static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);
-    static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);
-    static const XMLCh sendTimeout[] = UNICODE_LITERAL_11(s,e,n,d,T,i,m,e,o,u,t);
-    static const XMLCh recvTimeout[] = UNICODE_LITERAL_11(r,e,c,v,T,i,m,e,o,u,t);
-    static const XMLCh pollTimeout[] = UNICODE_LITERAL_11(p,o,l,l,T,i,m,e,o,u,t);
-    static const XMLCh failLimit[] = UNICODE_LITERAL_9(f,a,i,l,L,i,m,i,t);
-    static const XMLCh retryTimeout[] = UNICODE_LITERAL_12(r,e,t,r,y,T,i,m,e,o,u,t);
-    static const XMLCh nonBlocking[] = UNICODE_LITERAL_11(n,o,n,B,l,o,c,k,i,n,g);
-  
-    class mc_record {
-    public:
-        string value;
-        time_t expiration;
-        mc_record() {};
-        mc_record(string _v, time_t _e) : value(_v), expiration(_e) {}
-    };
-
-    class MemcacheBase {
-    public:
-        MemcacheBase(const DOMElement* e);
-        ~MemcacheBase();
-        
-        bool addMemcache(const char* key, string &value, time_t timeout, uint32_t flags, bool use_prefix = true);
-        bool setMemcache(const char* key, string &value, time_t timeout, uint32_t flags, bool use_prefix = true);
-        bool replaceMemcache(const char* key, string &value, time_t timeout, uint32_t flags, bool use_prefix = true);
-        bool getMemcache(const char* key, string &dest, uint32_t *flags, bool use_prefix = true);
-        bool deleteMemcache(const char* key, time_t timeout, bool use_prefix = true);
-
-        void serialize(mc_record &source, string &dest);
-        void serialize(list<string> &source, string &dest);
-        void deserialize(string &source, mc_record &dest);
-        void deserialize(string &source, list<string> &dest);
-
-        bool addLock(string what, bool use_prefix = true);
-        void deleteLock(string what, bool use_prefix = true);
-
-    protected:
-        Category& m_log;
-        memcached_st* memc;
-        string m_prefix;
-        scoped_ptr<Mutex> m_lock;
-
-    private:
-        bool handleError(const char*, memcached_return) const;
-    };
-  
-    class MemcacheStorageService : public StorageService, public MemcacheBase {
-
-    public:
-        MemcacheStorageService(const DOMElement* e);
-        ~MemcacheStorageService() {}
-    
-        const Capabilities& getCapabilities() const {
-            return m_caps;
-        }
-
-        bool createString(const char* context, const char* key, const char* value, time_t expiration);
-        int readString(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0);
-        int updateString(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0);
-        bool deleteString(const char* context, const char* key);
-    
-        bool createText(const char* context, const char* key, const char* value, time_t expiration) {
-            return createString(context, key, value, expiration);
-        }
-        int readText(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0) {
-            return readString(context, key, pvalue, pexpiration, version);
-        }
-        int updateText(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0) {
-            return updateString(context, key, value, expiration, version);
-        }
-        bool deleteText(const char* context, const char* key) {
-            return deleteString(context, key);
-        }
-    
-        void reap(const char*) {}
-
-        void updateContext(const char* context, time_t expiration);
-        void deleteContext(const char* context);
-
-    private:
-        Capabilities m_caps;
-        bool m_buildMap;
-    };
-
-    StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e, bool) {
-        return new MemcacheStorageService(e);
-    }
-};
-
-MemcacheBase::MemcacheBase(const DOMElement* e)
-    : m_log(Category::getInstance("XMLTooling.StorageService.MEMCACHE")), memc(nullptr),
-        m_prefix(XMLHelper::getAttrString(e, nullptr, prefix)), m_lock(Mutex::create())
-{
-    memc = memcached_create(nullptr);
-    if (!memc)
-        throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
-    m_log.debug("Memcache created");
-
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, MEMCACHED_HASH_CRC);
-    m_log.debug("CRC hash set");
-
-    int prop = XMLHelper::getAttrInt(e, 999999, sendTimeout);
-    m_log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, prop);
-
-    prop = XMLHelper::getAttrInt(e, 999999, recvTimeout);
-    m_log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, prop);
-
-    prop = XMLHelper::getAttrInt(e, 1000, pollTimeout);
-    m_log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, prop);
-
-    prop = XMLHelper::getAttrInt(e, 5, failLimit);
-    m_log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, prop);
-
-    prop = XMLHelper::getAttrInt(e, 30, retryTimeout);
-    m_log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, prop);
-
-    prop = XMLHelper::getAttrInt(e, 1, nonBlocking);
-    m_log.debug("MEMCACHED_BEHAVIOR_NO_BLOCK will be set to %d", prop);
-    memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NO_BLOCK, prop);
-
-    // Grab hosts from the configuration.
-    e = e ? XMLHelper::getFirstChildElement(e, Hosts) : nullptr;
-    if (!e || !e->hasChildNodes()) {
-        memcached_free(memc);
-        throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");
-    }
-    auto_ptr_char h(XMLHelper::getTextContent(e));
-    m_log.debug("INIT: GOT Hosts: %s", h.get());
-    memcached_server_st* servers;
-    servers = memcached_servers_parse(const_cast<char*>(h.get()));
-    m_log.debug("Got %u hosts.",  memcached_server_list_count(servers));
-    if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {
-        memcached_server_list_free(servers);
-        memcached_free(memc);
-        throw IOException("MemcacheBase: memcached_server_push() failed");
-    }
-    memcached_server_list_free(servers);
-
-    m_log.debug("Memcache object initialized");
-}
-
-MemcacheBase::~MemcacheBase()
-{
-    memcached_free(memc);
-    m_log.debug("Base object destroyed");
-}
-
-
-bool MemcacheBase::handleError(const char* fn, memcached_return rv) const
-{
-#ifdef HAVE_MEMCACHED_LAST_ERROR_MESSAGE
-    string error = string("Memcache::") + fn + ": " + memcached_last_error_message(memc);
-#else
-    string error;
-    if (rv == MEMCACHED_ERRNO) {
-        // System error
-        error = string("Memcache::") + fn + "SYSTEM ERROR: " + strerror(memc->cached_errno);
-    }
-    else {
-        error = string("Memcache::") + fn + " Problems: " + memcached_strerror(memc, rv);
-    }
-#endif
-    m_log.error(error);
-    throw IOException(error);
-}
-
-bool MemcacheBase::addLock(string what, bool use_prefix)
-{
-    string lock_name = what + ":LOCK";
-    string set_val = "1";
-    unsigned tries = 5;
-    while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {
-        if (tries-- == 0) {
-            m_log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
-            return false;
-        }
-        m_log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());
-    
-        // sleep 100ms
-#ifdef WIN32
-        Sleep(100);
-#else
-        struct timeval tv = { 0, 100000 };
-        select(0, 0, 0, 0, &tv);
-#endif
-    }
-    return true;
-}
-
-void MemcacheBase::deleteLock(string what, bool use_prefix)
-{
-    string lock_name = what + ":LOCK";
-    deleteMemcache(lock_name.c_str(), 0, use_prefix);
-    return;
-
-}  
-
-void MemcacheBase::deserialize(string& source, mc_record& dest)
-{
-    istringstream is(source, stringstream::in | stringstream::out);
-    is >> dest.expiration;
-    is.ignore(1); // ignore delimiter
-    dest.value = is.str().c_str() + is.tellg();
-}
-
-void MemcacheBase::deserialize(string& source, list<string>& dest)
-{
-    istringstream is(source, stringstream::in | stringstream::out);
-    while (!is.eof()) {
-        string s;
-        is >> s;
-        dest.push_back(s);
-    }
-}
-
-void MemcacheBase::serialize(mc_record& source, string& dest)
-{
-    ostringstream os(stringstream::in | stringstream::out);
-    os << source.expiration;
-    os << "-"; // delimiter
-    os << source.value;
-    dest = os.str();
-}
-
-void MemcacheBase::serialize(list<string>& source, string& dest)
-{
-    ostringstream os(stringstream::in | stringstream::out);
-    for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {
-        if (iter != source.begin()) {
-            os << endl;
-        }
-        os << *iter;
-    }
-    dest = os.str();
-}
-
-bool MemcacheBase::deleteMemcache(const char* key, time_t timeout, bool use_prefix)
-{
-    string final_key;
-    if (use_prefix)
-        final_key = m_prefix + key;
-    else
-        final_key = key;
-
-    Lock lock(m_lock);
-    memcached_return rv = memcached_delete(memc, const_cast<char*>(final_key.c_str()), final_key.length(), timeout);
-
-    switch (rv) {
-        case MEMCACHED_SUCCESS:
-            return true;
-        case MEMCACHED_NOTFOUND:
-            // Key wasn't there... No biggie.
-            return false;
-        default:
-            return handleError("deleteMemcache", rv);
-    }
-}
-
-bool MemcacheBase::getMemcache(const char* key, string& dest, uint32_t* flags, bool use_prefix)
-{
-    string final_key;
-    if (use_prefix)
-        final_key = m_prefix + key;
-    else
-        final_key = key;
-
-    Lock lock(m_lock);
-    size_t len;
-    memcached_return rv;
-    char* result = memcached_get(memc, const_cast<char*>(final_key.c_str()), final_key.length(), &len, flags, &rv);
-
-    switch (rv) {
-        case MEMCACHED_SUCCESS:
-            dest = result;
-            free(result);
-            return true;
-        case MEMCACHED_NOTFOUND:
-            m_log.debug("Key %s not found in memcache...", key);
-            return false;
-        default:
-            return handleError("getMemcache", rv);
-    }
-}
-
-bool MemcacheBase::addMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
-    string final_key;
-    if (use_prefix)
-        final_key = m_prefix + key;
-    else
-        final_key = key;
-
-    Lock lock(m_lock);
-    memcached_return rv = memcached_add(
-        memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
-        );
-
-    switch (rv) {
-        case MEMCACHED_SUCCESS:
-            return true;
-        case MEMCACHED_NOTSTORED:
-            return false;
-        default:
-            return handleError("addMemcache", rv);
-    }
-}
-
-bool MemcacheBase::setMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
-    string final_key;
-    if (use_prefix)
-        final_key = m_prefix + key;
-    else
-        final_key = key;
-
-    Lock lock(m_lock);
-    memcached_return rv = memcached_set(
-        memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
-        );
-
-    if (rv == MEMCACHED_SUCCESS)
-        return true;
-    return handleError("setMemcache", rv);
-}
-
-bool MemcacheBase::replaceMemcache(const char* key, string& value, time_t timeout, uint32_t flags, bool use_prefix)
-{
-  
-    string final_key;
-    if (use_prefix)
-        final_key = m_prefix + key;
-    else
-        final_key = key;
-
-    Lock lock(m_lock);
-    memcached_return rv = memcached_replace(
-        memc, const_cast<char*>(final_key.c_str()), final_key.length(), const_cast<char*>(value.c_str()), value.length(), timeout, flags
-        );
-
-    switch (rv) {
-        case MEMCACHED_SUCCESS:
-            return true;
-        case MEMCACHED_NOTSTORED:
-            // not there
-            return false;
-        default:
-            return handleError("replaceMemcache", rv);
-    }
-}
-
-
-MemcacheStorageService::MemcacheStorageService(const DOMElement* e)
-    : MemcacheBase(e), m_caps(80, 250 - m_prefix.length() - 1 - 80, 255),
-        m_buildMap(XMLHelper::getAttrBool(e, false, buildMap))
-{
-    if (m_buildMap)
-        m_log.debug("Cache built with buildMap ON");
-}
-
-bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration)
-{
-    m_log.debug("createString ctx: %s - key: %s", context, key);
-
-    string final_key = string(context) + ':' + string(key);
-
-    mc_record rec(value, expiration);
-    string final_value;
-    serialize(rec, final_value);
-
-    bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version
-
-    if (result && m_buildMap) {
-        m_log.debug("Got result, updating map");
-
-        string map_name = context;
-        // we need to update the context map
-        if (!addLock(map_name)) {
-            m_log.error("Unable to get lock for context %s!", context);
-            deleteMemcache(final_key.c_str(), 0);
-            return false;
-        }
-
-        string ser_arr;
-        uint32_t flags;
-        bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
-    
-        list<string> contents;
-        if (result) {
-            m_log.debug("Match found. Parsing...");
-            deserialize(ser_arr, contents);
-            if (m_log.isDebugEnabled()) {
-                m_log.debug("Iterating retrieved session map...");
-                for(list<string>::const_iterator iter = contents.begin(); iter != contents.end(); ++iter)
-                    m_log.debug("value = %s", iter->c_str());
-            }
-        }
-        else {
-            m_log.debug("New context: %s", map_name.c_str());
-        }
-
-        contents.push_back(key);
-        serialize(contents, ser_arr);
-        setMemcache(map_name.c_str(), ser_arr, expiration, 0);
-        deleteLock(map_name);
-    }
-    return result;
-}
-
-int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version)
-{
-    m_log.debug("readString ctx: %s - key: %s", context, key);
-
-    string final_key = string(context) + ":" + string(key);
-    uint32_t rec_version;
-    string value;
-
-    if (m_buildMap) {
-        m_log.debug("Checking context");
-        string map_name = context;
-        string ser_arr;
-        uint32_t flags;
-        bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);
-        if (!ctx_found)
-            return 0;
-    }
-
-    bool found = getMemcache(final_key.c_str(), value, &rec_version);
-    if (!found)
-        return 0;
-
-    mc_record rec;
-    if (pexpiration || pvalue)
-        deserialize(value, rec);
-    
-    if (pexpiration)
-        *pexpiration = rec.expiration;
-
-    if (version && rec_version <= (uint32_t)version)
-        return version;
-
-    if (pvalue)
-        *pvalue = rec.value;
-
-    return rec_version;
-}
-
-int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version)
-{
-    m_log.debug("updateString ctx: %s - key: %s", context, key);
-
-    time_t final_exp = expiration;
-    time_t* want_expiration = nullptr;
-    if (!final_exp)
-        want_expiration = &final_exp;
-
-    int read_res = readString(context, key, nullptr, want_expiration, version);
-
-    if (!read_res) {
-        // not found
-        return read_res;
-    }
-
-    if (version && version != read_res) {
-        // version incorrect
-        return -1;
-    }
-
-    // Proceding with update
-    string final_key = string(context) + ':' + string(key);
-    mc_record rec(value, final_exp);
-    string final_value;
-    serialize(rec, final_value);
-
-    replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);
-    return version;
-}
-
-bool MemcacheStorageService::deleteString(const char* context, const char* key)
-{
-    m_log.debug("deleteString ctx: %s - key: %s", context, key);
-  
-    string final_key = string(context) + ':' + string(key);
-
-    // Not updating context map, if there is one. There is no need.
-    return deleteMemcache(final_key.c_str(), 0);
-}
-
-void MemcacheStorageService::updateContext(const char* context, time_t expiration)
-{
-
-    m_log.debug("updateContext ctx: %s", context);
-
-    if (!m_buildMap) {
-        m_log.error("updateContext invoked on a Storage with no context map built!");
-        return;
-    }
-
-    string map_name = context;
-    string ser_arr;
-    uint32_t flags;
-    bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
-  
-    list<string> contents;
-    if (result) {
-        m_log.debug("Match found. Parsing...");
-        deserialize(ser_arr, contents);
-    
-        m_log.debug("Iterating retrieved session map...");
-        for(list<string>::const_iterator iter = contents.begin(); iter != contents.end(); ++iter) {
-            // Update expiration times
-            string value;
-            int read_res = readString(context, iter->c_str(), &value, nullptr, 0);
-            if (!read_res) {
-                // not found
-                continue;
-            }
-
-            updateString(context, iter->c_str(), value.c_str(), expiration, read_res);
-        }
-        replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);
-    }
-}
-
-void MemcacheStorageService::deleteContext(const char* context)
-{
-
-    m_log.debug("deleteContext ctx: %s", context);
-
-    if (!m_buildMap) {
-        m_log.error("deleteContext invoked on a Storage with no context map built!");
-        return;
-    }
-
-    string map_name = context;
-    string ser_arr;
-    uint32_t flags;
-    bool result = getMemcache(map_name.c_str(), ser_arr, &flags);
-  
-    list<string> contents;
-    if (result) {
-        m_log.debug("Match found. Parsing...");
-        deserialize(ser_arr, contents);
-    
-        m_log.debug("Iterating retrieved session map...");
-        for (list<string>::const_iterator iter = contents.begin(); iter != contents.end(); ++iter) {
-            string final_key = map_name + ':' + *iter;
-            deleteMemcache(final_key.c_str(), 0);
-        }
-    
-        deleteMemcache(map_name.c_str(), 0);
-    }
-}
-
-extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {
-    // Register this SS type
-    XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);
-    return 0;
-}
-
-extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {
-    XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");
-}
diff --git a/memcache-store/memcache-store.rc b/memcache-store/memcache-store.rc
deleted file mode 100644
index 506d7b14..00000000
--- a/memcache-store/memcache-store.rc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth Memcache Storage Service Plugin\0"
-            VALUE "InternalName", "memcache-store\0"
-            VALUE "OriginalFilename", "memcache-store.so\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
diff --git a/memcache-store/resource.h b/memcache-store/resource.h
deleted file mode 100644
index ccedb46a..00000000
--- a/memcache-store/resource.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by memcache-store.rc
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/nsapi_shib/Makefile.am b/nsapi_shib/Makefile.am
deleted file mode 100644
index 696f80ad..00000000
--- a/nsapi_shib/Makefile.am
+++ /dev/null
@@ -1,23 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-if BUILD_NSAPI
-nsapi_shibdir = $(libdir)/@PACKAGE_NAME@
-nsapi_shib_LTLIBRARIES = nsapi_shib.la
-nsapi_shib_la_SOURCES = nsapi_shib.cpp
-nsapi_shib_la_CXXFLAGS = $(NSAPI_INCLUDE) \
-  $(AM_CXXFLAGS) \
-  $(BOOST_CPPFLAGS) \
-  $(PTHREAD_CFLAGS) \
-  $(log4shib_CFLAGS) $(log4cpp_CFLAGS) \
-  $(xerces_CFLAGS) \
-  $(xmltooling_lite_CFLAGS)
-nsapi_shib_la_LDFLAGS = -module -avoid-version
-nsapi_shib_la_LIBADD = \
-  $(top_builddir)/shibsp/libshibsp-lite.la \
-  $(PTHREAD_LIBS) \
-  $(log4shib_LIBS) $(log4cpp_LIBS) \
-  $(xerces_LIBS) \
-  $(xmltooling_lite_LIBS)
-endif
-
-EXTRA_DIST = resource.h nsapi_shib.rc nsapi_shib.cpp
diff --git a/nsapi_shib/nsapi_shib.cpp b/nsapi_shib/nsapi_shib.cpp
deleted file mode 100644
index 570dfbf2..00000000
--- a/nsapi_shib/nsapi_shib.cpp
+++ /dev/null
@@ -1,696 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/**
- * nsapi_shib.cpp
- *
- * Shibboleth NSAPI filter.
- */
-
-#define SHIBSP_LITE
-
-#if defined (_MSC_VER) || defined(__BORLANDC__)
-# include "config_win32.h"
-#else
-# include "config.h"
-#endif
-
-#ifdef WIN32
-# define _CRT_NONSTDC_NO_DEPRECATE 1
-# define _CRT_SECURE_NO_DEPRECATE 1
-# define _CRT_RAND_S
-#endif
-
-#include <shibsp/exceptions.h>
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/RequestMapper.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-
-#include <set>
-#include <memory>
-#include <fstream>
-#include <stdexcept>
-#include <boost/lexical_cast.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/Threads.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#ifdef WIN32
-# define WIN32_LEAN_AND_MEAN
-# include <process.h>
-# define XP_WIN32
-#else
-# define XP_UNIX
-#endif
-
-#define MCC_HTTPD
-#define NET_SSL
-
-extern "C"
-{
-#include <nsapi.h>
-}
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace boost;
-using namespace std;
-
-// macros to output text to client
-#define NET_WRITE(str) \
-    if (IO_ERROR==net_write(sn->csd,str,strlen(str))) return REQ_EXIT
-
-namespace {
-    SPConfig* g_Config=nullptr;
-    string g_ServerName;
-    string g_unsetHeaderValue;
-    string g_spoofKey;
-    bool g_checkSpoofing = true;
-    bool g_catchAll = false;
-
-    static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);
-    static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);
-
-    void _my_invalid_parameter_handler(
-       const wchar_t * expression,
-       const wchar_t * function,
-       const wchar_t * file,
-       unsigned int line,
-       uintptr_t pReserved
-       ) {
-        return;
-    }
-}
-
-PluginManager<RequestMapper,string,const xercesc::DOMElement*>::Factory SunRequestMapFactory;
-
-extern "C" NSAPI_PUBLIC void nsapi_shib_exit(void*)
-{
-    if (g_Config)
-        g_Config->term();
-    g_Config = nullptr;
-}
-
-extern "C" NSAPI_PUBLIC int nsapi_shib_init(pblock* pb, ::Session* sn, Request* rq)
-{
-    static char _funcname[] = "nsapi_shib_init";
-
-    // Save off a default hostname for this virtual server.
-    char* name=pblock_findval("server-name",pb);
-    if (name)
-        g_ServerName=name;
-    else {
-        name=server_hostname;
-        if (name)
-            g_ServerName=name;
-        else {
-            name=util_hostname();
-            if (name) {
-                g_ServerName=name;
-                FREE(name);
-            }
-            else {
-                pblock_nvinsert("error","unable to determine web server hostname",pb);
-                return REQ_ABORTED;
-            }
-        }
-    }
-
-    static char _logmsg[] = "nsapi_shib loaded for host (%s)";
-    log_error(LOG_INFORM,_funcname,sn,rq,_logmsg,g_ServerName.c_str());
-
-    const char* schemadir=pblock_findval("shib-schemas",pb);
-    const char* prefix=pblock_findval("shib-prefix",pb);
-
-    g_Config=&SPConfig::getConfig();
-    g_Config->deprecation().warn("NSAPI filter");
-    g_Config->setFeatures(
-        SPConfig::Listener |
-        SPConfig::Caching |
-        SPConfig::RequestMapping |
-        SPConfig::InProcess |
-        SPConfig::Logging |
-        SPConfig::Handlers
-        );
-    if (!g_Config->init(schemadir,prefix)) {
-        g_Config=nullptr;
-        pblock_nvinsert("error","unable to initialize Shibboleth libraries",pb);
-        return REQ_ABORTED;
-    }
-
-    g_Config->RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER,&SunRequestMapFactory);
-
-    try {
-        if (!g_Config->instantiate(pblock_findval("shib-config",pb), true))
-            throw runtime_error("unknown error");
-    }
-    catch (std::exception& ex) {
-        pblock_nvinsert("error",ex.what(),pb);
-        g_Config->term();
-        g_Config=nullptr;
-        return REQ_ABORTED;
-    }
-
-    daemon_atrestart(nsapi_shib_exit,nullptr);
-
-    ServiceProvider* sp=g_Config->getServiceProvider();
-    Locker locker(sp);
-    const PropertySet* props=sp->getPropertySet("InProcess");
-    if (props) {
-        pair<bool,bool> flag=props->getBool("checkSpoofing");
-        g_checkSpoofing = !flag.first || flag.second;
-        flag=props->getBool("catchAll");
-        g_catchAll = flag.first && flag.second;
-
-        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
-        if (unsetValue.first)
-            g_unsetHeaderValue = unsetValue.second;
-        if (g_checkSpoofing) {
-            unsetValue=props->getString("spoofKey");
-            if (unsetValue.first)
-                g_spoofKey = unsetValue.second;
-#ifdef WIN32
-            else {
-                _invalid_parameter_handler old = _set_invalid_parameter_handler(_my_invalid_parameter_handler);
-                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);
-                    g_spoofKey = lexical_cast<string>(randkey) + lexical_cast<string>(randkey2) +
-                        lexical_cast<string>(randkey3) + lexical_cast<string>(randkey4);
-                }
-                else {
-                    _set_invalid_parameter_handler(old);
-                    pblock_nvinsert("error", "module failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually)", pb);
-                    locker.assign(); // pops lock on SP config
-                    g_Config->term();
-                    g_Config=nullptr;
-                    return REQ_ABORTED;
-                }
-            }
-#endif
-        }
-    }
-    return REQ_PROCEED;
-}
-
-/********************************************************************************/
-// NSAPI Shib Target Subclass
-
-class ShibTargetNSAPI : public AbstractSPRequest
-{
-  mutable string m_body;
-  mutable bool m_gotBody,m_firsttime;
-  bool m_security_active;
-  int m_server_portnum;
-  mutable vector<string> m_certs;
-  set<string> m_allhttp;
-
-public:
-  pblock* m_pb;
-  ::Session* m_sn;
-  Request* m_rq;
-
-  ShibTargetNSAPI(pblock* pb, ::Session* sn, Request* rq)
-      : AbstractSPRequest(SHIBSP_LOGCAT ".NSAPI"),
-        m_gotBody(false), m_firsttime(true), m_security_active(false), m_server_portnum(0), m_pb(pb), m_sn(sn), m_rq(rq) {
-
-    // To determine whether SSL is active or not, we're supposed to rely
-    // on the security_active macro. For iPlanet 4.x, this works.
-    // For Sun 7.x, it's useless and appears to be on or off based
-    // on whether ANY SSL support is enabled for a vhost. Sun 6.x is unknown.
-    // As a fix, there's a conf variable called $security that can be mapped
-    // into a function parameter: security_active="$security"
-    // We check for this parameter, and rely on the macro if it isn't set.
-    // This doubles as a scheme virtualizer for load balanced scenarios
-    // since you can set the parameter to 1 or 0 as needed.
-    const char* sa = pblock_findval("security_active", m_pb);
-    if (sa)
-        m_security_active = (*sa == '1');
-    else if (security_active)
-        m_security_active = true;
-    else
-        m_security_active = false;
-
-    // A similar issue exists for the port. server_portnum is no longer
-    // working on at least Sun 7.x, and returns the first listener's port
-    // rather than whatever port is actually used for the request. Nice job, Sun.
-    sa = pblock_findval("server_portnum", m_pb);
-    m_server_portnum = (sa && *sa) ? atoi(sa) : server_portnum;
-
-    const char* uri = pblock_findval("uri", rq->reqpb);
-    const char* qstr = pblock_findval("query", rq->reqpb);
-
-    if (qstr) {
-        string temp = string(uri) + '?' + qstr;
-        setRequestURI(temp.c_str());
-    }
-    else {
-        setRequestURI(uri);
-    }
-
-    // See if this is the first time we've run.
-    if (!g_spoofKey.empty()) {
-        qstr = pblock_findval("Shib-Spoof-Check", rq->headers);
-        if (qstr && g_spoofKey == qstr)
-            m_firsttime = false;
-    }
-    if (!m_firsttime || rq->orig_rq)
-        log(SPDebug, "nsapi_shib function running more than once");
-  }
-  ~ShibTargetNSAPI() { }
-
-  const char* getScheme() const {
-    return m_security_active ? "https" : "http";
-  }
-  const char* getHostname() const {
-#ifdef vs_is_default_vs
-    // This is 6.0 or later, so we can distinguish requests to name-based vhosts.
-    if (!vs_is_default_vs(request_get_vs(m_rq)))
-        // The beauty here is, a non-default vhost can *only* be accessed if the client
-        // specified the exact name in the Host header. So we can trust the Host header.
-        return pblock_findval("host", m_rq->headers);
-    else
-#endif
-    // In other cases, we're going to rely on the initialization process...
-    return g_ServerName.c_str();
-  }
-  int getPort() const {
-    return m_server_portnum;
-  }
-  const char* getMethod() const {
-    return pblock_findval("method", m_rq->reqpb);
-  }
-  string getContentType() const {
-    static char _contenttype[] = "content-type";
-    char* content_type = nullptr;
-    if (request_header(_contenttype, &content_type, m_sn, m_rq) != REQ_PROCEED)
-        return "";
-    return content_type ? content_type : "";
-  }
-  long getContentLength() const {
-    static char _contentlen[] = "content-length";
-    if (m_gotBody)
-        return m_body.length();
-    char* content_length=nullptr;
-    if (request_header(_contentlen, &content_length, m_sn, m_rq) != REQ_PROCEED)
-        return 0;
-    return content_length ? atoi(content_length) : 0;
-  }
-  string getRemoteAddr() const {
-    string ret = AbstractSPRequest::getRemoteAddr();
-    return ret.empty() ? pblock_findval("ip", m_sn->client) : ret;
-  }
-  void log(SPLogLevel level, const string& msg) const {
-    static char _module[] = "nsapi_shib";
-    AbstractSPRequest::log(level,msg);
-    if (level>=SPError)
-        log_error(LOG_FAILURE, _module, m_sn, m_rq, const_cast<char*>(msg.c_str()));
-  }
-  const char* getQueryString() const {
-    return pblock_findval("query", m_rq->reqpb);
-  }
-  const char* getRequestBody() const {
-    static char _contentlen[] = "content-length";
-    if (m_gotBody)
-        return m_body.c_str();
-    char* content_length=nullptr;
-    if (request_header(_contentlen, &content_length, m_sn, m_rq) != REQ_PROCEED || !content_length) {
-        m_gotBody = true;
-        return nullptr;
-    }
-    else if (atoi(content_length) > 1024*1024) // 1MB?
-      throw opensaml::SecurityPolicyException("Blocked request body exceeding 1M size limit.");
-    else {
-      char ch=IO_EOF+1;
-      int cl=atoi(content_length);
-      m_gotBody=true;
-      while (cl && ch != IO_EOF) {
-        ch=netbuf_getc(m_sn->inbuf);
-        // Check for error.
-        if(ch==IO_ERROR)
-          break;
-        m_body += ch;
-        cl--;
-      }
-      if (cl)
-        throw IOException("Error reading request body from browser.");
-      return m_body.c_str();
-    }
-  }
-  void clearHeader(const char* rawname, const char* cginame) {
-    if (g_checkSpoofing && m_firsttime && !m_rq->orig_rq) {
-        if (m_allhttp.empty()) {
-            // Populate the set of client-supplied headers for spoof checking.
-            const pb_entry* entry;
-            for (int i=0; i<m_rq->headers->hsize; ++i) {
-                entry = m_rq->headers->ht[i];
-                while (entry) {
-                    string cgiversion("HTTP_");
-                    const char* pch = entry->param->name;
-                    while (*pch) {
-                        cgiversion += (isalnum(*pch) ? toupper(*pch) : '_');
-                        pch++;
-                    }
-                    m_allhttp.insert(cgiversion);
-                    entry = entry->next;
-                }
-            }
-        }
-        if (m_allhttp.count(cginame) > 0)
-            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
-    }
-    if (strcmp(rawname, "REMOTE_USER") == 0) {
-        param_free(pblock_remove("remote-user", m_rq->headers));
-        pblock_nvinsert("remote-user", g_unsetHeaderValue.c_str(), m_rq->headers);
-    }
-    else {
-        param_free(pblock_remove(rawname, m_rq->headers));
-        pblock_nvinsert(rawname, g_unsetHeaderValue.c_str(), m_rq->headers);
-    }
-  }
-  void setHeader(const char* name, const char* value) {
-    param_free(pblock_remove(name, m_rq->headers));
-    pblock_nvinsert(name, value, m_rq->headers);
-  }
-  string getHeader(const char* name) const {
-    // NSAPI headers tend to be lower case. We'll special case "cookie" since it's used a lot.
-    char* hdr = nullptr;
-    int cookie = strcmp(name, "Cookie");
-    if (cookie == 0)
-        name = "cookie";
-    if (request_header(const_cast<char*>(name), &hdr, m_sn, m_rq) != REQ_PROCEED) {
-      // We didn't get a hit, so we'll try a lower-casing operation, unless we already did...
-      if (cookie == 0)
-          return "";
-      string n;
-      while (*name)
-          n += tolower(*(name++));
-      if (request_header(const_cast<char*>(n.c_str()), &hdr, m_sn, m_rq) != REQ_PROCEED)
-          return "";
-    }
-    return string(hdr ? hdr : "");
-  }
-  void setRemoteUser(const char* user) {
-    pblock_nvinsert("auth-user", user, m_rq->vars);
-    param_free(pblock_remove("remote-user", m_rq->headers));
-    pblock_nvinsert("remote-user", user, m_rq->headers);
-  }
-  string getRemoteUser() const {
-    const char* ru = pblock_findval("auth-user", m_rq->vars);
-    return ru ? ru : "";
-  }
-  void setAuthType(const char* authtype) {
-    param_free(pblock_remove("auth-type", m_rq->vars));
-    if (authtype)
-        pblock_nvinsert("auth-type", authtype, m_rq->vars);
-  }
-  string getAuthType() const {
-    const char* at = pblock_findval("auth-type", m_rq->vars);
-    return at ? at : "";
-  }
-  void setContentType(const char* type) {
-      // iPlanet seems to have a case folding problem.
-      param_free(pblock_remove("content-type", m_rq->srvhdrs));
-      setResponseHeader("Content-Type", type);
-  }
-  void setResponseHeader(const char* name, const char* value, bool replace=false) {
-    HTTPResponse::setResponseHeader(name, value, replace);
-    if (name && *name) {
-        if (replace || !value)
-            param_free(pblock_remove(name, m_rq->srvhdrs));
-        if (value && *value)
-            pblock_nvinsert(name, value, m_rq->srvhdrs);
-    }
-  }
-
-  long sendResponse(istream& in, long status) {
-    string msg;
-    char buf[1024];
-    while (in) {
-        in.read(buf,1024);
-        msg.append(buf,in.gcount());
-    }
-    pblock_nvinsert("connection","close",m_rq->srvhdrs);
-    pblock_nninsert("content-length", msg.length(), m_rq->srvhdrs);
-    protocol_status(m_sn, m_rq, status, nullptr);
-    protocol_start_response(m_sn, m_rq);
-    net_write(m_sn->csd,const_cast<char*>(msg.c_str()),msg.length());
-    return REQ_EXIT;
-  }
-  long sendRedirect(const char* url) {
-    HTTPResponse::sendRedirect(url);
-    param_free(pblock_remove("content-type", m_rq->srvhdrs));
-    pblock_nninsert("content-length", 0, m_rq->srvhdrs);
-    pblock_nvinsert("expires", "Wed, 01 Jan 1997 12:00:00 GMT", m_rq->srvhdrs);
-    pblock_nvinsert("cache-control", "private,no-store,no-cache,max-age=0", m_rq->srvhdrs);
-    pblock_nvinsert("location", url, m_rq->srvhdrs);
-    pblock_nvinsert("connection","close",m_rq->srvhdrs);
-    protocol_status(m_sn, m_rq, PROTOCOL_REDIRECT, nullptr);
-    protocol_start_response(m_sn, m_rq);
-    return REQ_ABORTED;
-  }
-  long returnDecline() { return REQ_NOACTION; }
-  long returnOK() { return REQ_PROCEED; }
-  const vector<string>& getClientCertificates() const {
-      if (m_certs.empty()) {
-          const char* cert = pblock_findval("auth-cert", m_rq->vars);
-          if (cert)
-              m_certs.push_back(cert);
-      }
-      return m_certs;
-  }
-};
-
-/********************************************************************************/
-
-int WriteClientError(::Session* sn, Request* rq, char* func, char* msg)
-{
-    log_error(LOG_FAILURE,func,sn,rq,msg);
-    protocol_status(sn,rq,PROTOCOL_SERVER_ERROR,msg);
-    return REQ_ABORTED;
-}
-
-extern "C" NSAPI_PUBLIC int nsapi_shib(pblock* pb, ::Session* sn, Request* rq)
-{
-  static char _func[] = "nsapi_shib";
-
-  string threadid("[");
-  threadid += lexical_cast<string>(getpid()) + "] nsapi_shib";
-  xmltooling::NDC ndc(threadid.c_str());
-
-  try {
-    ShibTargetNSAPI stn(pb, sn, rq);
-
-    // Check user authentication
-    pair<bool,long> res = stn.getServiceProvider().doAuthentication(stn);
-    // If directed, install a spoof key to recognize when we've already cleared headers.
-    if (!g_spoofKey.empty()) {
-      param_free(pblock_remove("Shib-Spoof-Check", rq->headers));
-      pblock_nvinsert("Shib-Spoof-Check", g_spoofKey.c_str(), rq->headers);
-    }
-    if (res.first) return (int)res.second;
-
-    // user authN was okay -- export the assertions now
-    param_free(pblock_remove("auth-user",rq->vars));
-
-    res = stn.getServiceProvider().doExport(stn);
-    if (res.first) return (int)res.second;
-
-    // Check the Authorization
-    res = stn.getServiceProvider().doAuthorization(stn);
-    if (res.first) return (int)res.second;
-
-    // this user is ok.
-    return REQ_PROCEED;
-  }
-  catch (const std::exception& e) {
-    log_error(LOG_FAILURE,_func,sn,rq,const_cast<char*>(e.what()));
-    static char _errmsg[] = "Shibboleth module threw an exception, see web server log for error.";
-    return WriteClientError(sn, rq, _func, _errmsg);
-  }
-  catch (...) {
-    static char _errmsg2[] = "Shibboleth module threw an unknown exception.";
-    log_error(LOG_FAILURE,_func,sn,rq,_errmsg2);
-    if (g_catchAll)
-        return WriteClientError(sn, rq, _func, _errmsg2);
-    throw;
-  }
-}
-
-
-extern "C" NSAPI_PUBLIC int shib_handler(pblock* pb, ::Session* sn, Request* rq)
-{
-  static char _func[] = "shib_handler";
-
-  string threadid("[");
-  threadid += lexical_cast<string>(getpid()) + "] shib_handler";
-  xmltooling::NDC ndc(threadid.c_str());
-
-  try {
-    ShibTargetNSAPI stn(pb, sn, rq);
-
-    pair<bool,long> res = stn.getServiceProvider().doHandler(stn);
-    if (res.first) return (int)res.second;
-
-    static char _errmsg[] = "Shibboleth handler did not do anything.";
-    return WriteClientError(sn, rq, _func, _errmsg);
-  }
-  catch (const std::exception& e) {
-    static char _errmsg2[] = "Shibboleth handler threw an exception, see web server log for error.";
-    log_error(LOG_FAILURE,_func,sn,rq,const_cast<char*>(e.what()));
-    return WriteClientError(sn, rq, _func, _errmsg2);
-  }
-  catch (...) {
-    static char _errmsg3[] = "Shibboleth handler threw an unknown exception.";
-    log_error(LOG_FAILURE,_func,sn,rq,_errmsg3);
-    if (g_catchAll)
-        return WriteClientError(sn, rq, _func, _errmsg3);
-    throw;
-  }
-}
-
-
-class SunRequestMapper : public virtual RequestMapper, public virtual PropertySet
-{
-public:
-    SunRequestMapper(const xercesc::DOMElement* e, bool deprecationSupport=true);
-    ~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;
-
-    const PropertySet* getParent() const { return nullptr; }
-    void setParent(const PropertySet*) {}
-    pair<bool,bool> getBool(const char* name, const char* ns=nullptr) const;
-    pair<bool,const char*> getString(const char* name, const char* ns=nullptr) const;
-    pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=nullptr) const;
-    pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=nullptr) const;
-    pair<bool,int> getInt(const char* name, const char* ns=nullptr) const;
-    const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIBSPCONFIG_NS) const;
-    const xercesc::DOMElement* getElement() const;
-
-private:
-    scoped_ptr<RequestMapper> m_mapper;
-    scoped_ptr<ThreadKey> m_stKey, m_propsKey;
-};
-
-RequestMapper* SunRequestMapFactory(const xercesc::DOMElement* const & e, bool deprecationSupport)
-{
-    return new SunRequestMapper(e);
-}
-
-SunRequestMapper::SunRequestMapper(const xercesc::DOMElement* e, bool deprecationSupport)
-    : m_mapper(SPConfig::getConfig().RequestMapperManager.newPlugin(XML_REQUEST_MAPPER,e, deprecationSupport)),
-        m_stKey(ThreadKey::create(nullptr)),
-        m_propsKey(ThreadKey::create(nullptr))
-{
-}
-
-RequestMapper::Settings SunRequestMapper::getSettings(const HTTPRequest& request) const
-{
-    Settings s=m_mapper->getSettings(request);
-    m_stKey->setData((void*)dynamic_cast<const ShibTargetNSAPI*>(&request));
-    m_propsKey->setData((void*)s.first);
-    return pair<const PropertySet*,AccessControl*>(this,s.second);
-}
-
-pair<bool,bool> SunRequestMapper::getBool(const char* name, const char* ns) const
-{
-    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    if (stn && !ns && name) {
-        // Override boolean properties.
-        const char* param=pblock_findval(name,stn->m_pb);
-		if (param)
-			return make_pair(true, !strcmp(param, "1") || !strcasecmp(param, "true"));
-    }
-    return s ? s->getBool(name,ns) : make_pair(false,false);
-}
-
-pair<bool,const char*> SunRequestMapper::getString(const char* name, const char* ns) const
-{
-    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    if (stn && !ns && name) {
-        // Override string properties.
-        if (!strcmp(name,"authType"))
-            return pair<bool,const char*>(true,"shibboleth");
-        else {
-            const char* param=pblock_findval(name,stn->m_pb);
-            if (param)
-                return make_pair(true,param);
-        }
-    }
-    return s ? s->getString(name,ns) : pair<bool,const char*>(false,nullptr);
-}
-
-pair<bool,const XMLCh*> SunRequestMapper::getXMLString(const char* name, const char* ns) const
-{
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    return s ? s->getXMLString(name,ns) : pair<bool,const XMLCh*>(false,nullptr);
-}
-
-pair<bool,unsigned int> SunRequestMapper::getUnsignedInt(const char* name, const char* ns) const
-{
-    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    if (stn && !ns && name) {
-        // Override int properties.
-        const char* param=pblock_findval(name,stn->m_pb);
-        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);
-}
-
-pair<bool,int> SunRequestMapper::getInt(const char* name, const char* ns) const
-{
-    const ShibTargetNSAPI* stn=reinterpret_cast<const ShibTargetNSAPI*>(m_stKey->getData());
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    if (stn && !ns && name) {
-        // Override int properties.
-        const char* param=pblock_findval(name,stn->m_pb);
-        if (param)
-            return pair<bool,int>(true,atoi(param));
-    }
-    return s ? s->getInt(name,ns) : pair<bool,int>(false,0);
-}
-
-const PropertySet* SunRequestMapper::getPropertySet(const char* name, const char* ns) const
-{
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    return s ? s->getPropertySet(name,ns) : nullptr;
-}
-
-const xercesc::DOMElement* SunRequestMapper::getElement() const
-{
-    const PropertySet* s=reinterpret_cast<const PropertySet*>(m_propsKey->getData());
-    return s ? s->getElement() : nullptr;
-}
diff --git a/nsapi_shib/nsapi_shib.rc b/nsapi_shib/nsapi_shib.rc
deleted file mode 100644
index e3aaee30..00000000
--- a/nsapi_shib/nsapi_shib.rc
+++ /dev/null
@@ -1,101 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth NSAPI Extension\0"
-            VALUE "InternalName", "nsapi_shib\0"
-            VALUE "OriginalFilename", "nsapi_shib.dll\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // !_MAC
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/nsapi_shib/resource.h b/nsapi_shib/resource.h
deleted file mode 100644
index bc921e9f..00000000
--- a/nsapi_shib/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by nsapi_shib.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/odbc-store/Makefile.am b/odbc-store/Makefile.am
deleted file mode 100644
index 49e87c52..00000000
--- a/odbc-store/Makefile.am
+++ /dev/null
@@ -1,30 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-plugindir = $(libdir)/@PACKAGE_NAME@
-plugin_LTLIBRARIES = odbc-store.la
-
-odbc_store_la_CXXFLAGS = \
-	$(AM_CXXFLAGS) \
-	$(ODBC_CFLAGS) \
-	$(BOOST_CPPFLAGS) \
-	$(PTHREAD_CFLAGS) \
-	$(log4cpp_CFLAGS) \
-	$(log4shib_CFLAGS) \
-	$(opensaml_CFLAGS) \
-	$(xerces_CFLAGS) \
-	$(xmltooling_CFLAGS)
-odbc_store_la_LIBADD = \
-	$(ODBC_LIBS) \
-	$(PTHREAD_LIBS) \
-	$(log4cpp_LIBS) \
-	$(log4shib_LIBS) \
-	$(opensaml_LIBS) \
-	$(xerces_LIBS) \
-	$(xmltooling_LIBS)
-
-odbc_store_la_SOURCES = \
-	odbc-store.cpp
-
-odbc_store_la_LDFLAGS = -module -avoid-version
-
-EXTRA_DIST = odbc-store.rc resource.h
diff --git a/odbc-store/odbc-store.cpp b/odbc-store/odbc-store.cpp
deleted file mode 100644
index 2316e95c..00000000
--- a/odbc-store/odbc-store.cpp
+++ /dev/null
@@ -1,897 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/**
- * odbc-store.cpp
- *
- * Storage Service using ODBC.
- */
-
-#if defined (_MSC_VER) || defined(__BORLANDC__)
-# include "config_win32.h"
-#else
-# include "config.h"
-#endif
-
-#ifdef WIN32
-# define _CRT_NONSTDC_NO_DEPRECATE 1
-# define _CRT_SECURE_NO_DEPRECATE 1
-#endif
-
-#ifdef WIN32
-# define ODBCSTORE_EXPORTS __declspec(dllexport)
-#else
-# define ODBCSTORE_EXPORTS
-#endif
-
-#include <xmltooling/logging.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.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/algorithm/string.hpp>
-
-using namespace xmltooling::logging;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace boost;
-using namespace std;
-
-#define PLUGIN_VER_MAJOR 1
-#define PLUGIN_VER_MINOR 1
-
-#define LONGDATA_BUFLEN 16384
-
-#define COLSIZE_CONTEXT 255
-#define COLSIZE_ID 255
-#define COLSIZE_STRING_VALUE 255
-
-#define STRING_TABLE "strings"
-#define TEXT_TABLE "texts"
-
-/* table definitions
-CREATE TABLE version (
-    major int NOT nullptr,
-    minor int NOT nullptr
-    )
-
-CREATE TABLE strings (
-    context varchar(255) not null,
-    id varchar(255) not null,
-    expires datetime not null,
-    version int not null,
-    value varchar(255) not null,
-    PRIMARY KEY (context, id)
-    )
-
-CREATE TABLE texts (
-    context varchar(255) not null,
-    id varchar(255) not null,
-    expires datetime not null,
-    version int not null,
-    value text not null,
-    PRIMARY KEY (context, id)
-    )
-*/
-
-namespace {
-    static const XMLCh cleanupInterval[] =  UNICODE_LITERAL_15(c,l,e,a,n,u,p,I,n,t,e,r,v,a,l);
-    static const XMLCh isolationLevel[] =   UNICODE_LITERAL_14(i,s,o,l,a,t,i,o,n,L,e,v,e,l);
-    static const XMLCh ConnectionString[] = UNICODE_LITERAL_16(C,o,n,n,e,c,t,i,o,n,S,t,r,i,n,g);
-    static const XMLCh RetryOnError[] =     UNICODE_LITERAL_12(R,e,t,r,y,O,n,E,r,r,o,r);
-    static const XMLCh contextSize[] =      UNICODE_LITERAL_11(c,o,n,t,e,x,t,S,i,z,e);
-    static const XMLCh keySize[] =          UNICODE_LITERAL_7(k,e,y,S,i,z,e);
-    static const XMLCh stringSize[] =       UNICODE_LITERAL_10(s,t,r,i,n,g,S,i,z,e);
-
-    // RAII for ODBC handles
-    struct ODBCConn {
-        ODBCConn(SQLHDBC conn) : handle(conn), autoCommit(true) {}
-        ~ODBCConn() {
-            if (handle != SQL_NULL_HDBC) {
-                SQLRETURN sr = SQL_SUCCESS;
-                if (!autoCommit)
-                    sr = SQLSetConnectAttr(handle, SQL_ATTR_AUTOCOMMIT, (SQLPOINTER)SQL_AUTOCOMMIT_ON, 0);
-                SQLDisconnect(handle);
-                SQLFreeHandle(SQL_HANDLE_DBC, handle);
-                if (!SQL_SUCCEEDED(sr))
-                    throw IOException("Failed to commit connection and return to auto-commit mode.");
-            }
-        }
-        operator SQLHDBC() {return handle;}
-        SQLHDBC handle;
-        bool autoCommit;
-    };
-
-    class ODBCStorageService : public StorageService
-    {
-    public:
-        ODBCStorageService(const DOMElement* e);
-        virtual ~ODBCStorageService();
-
-        const Capabilities& getCapabilities() const {
-            return m_caps;
-        }
-
-        bool createString(const char* context, const char* key, const char* value, time_t expiration) {
-            return createRow(STRING_TABLE, context, key, value, expiration);
-        }
-        int readString(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0) {
-            return readRow(STRING_TABLE, context, key, pvalue, pexpiration, version);
-        }
-        int updateString(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0) {
-            return updateRow(STRING_TABLE, context, key, value, expiration, version);
-        }
-        bool deleteString(const char* context, const char* key) {
-            return deleteRow(STRING_TABLE, context, key);
-        }
-
-        bool createText(const char* context, const char* key, const char* value, time_t expiration) {
-            return createRow(TEXT_TABLE, context, key, value, expiration);
-        }
-        int readText(const char* context, const char* key, string* pvalue=nullptr, time_t* pexpiration=nullptr, int version=0) {
-            return readRow(TEXT_TABLE, context, key, pvalue, pexpiration, version);
-        }
-        int updateText(const char* context, const char* key, const char* value=nullptr, time_t expiration=0, int version=0) {
-            return updateRow(TEXT_TABLE, context, key, value, expiration, version);
-        }
-        bool deleteText(const char* context, const char* key) {
-            return deleteRow(TEXT_TABLE, context, key);
-        }
-
-        void reap(const char* context) {
-            reap(STRING_TABLE, context);
-            reap(TEXT_TABLE, context);
-        }
-
-        void updateContext(const char* context, time_t expiration) {
-            updateContext(STRING_TABLE, context, expiration);
-            updateContext(TEXT_TABLE, context, expiration);
-        }
-
-        void deleteContext(const char* context) {
-            deleteContext(STRING_TABLE, context);
-            deleteContext(TEXT_TABLE, context);
-        }
-         
-
-    private:
-        bool createRow(const char *table, const char* context, const char* key, const char* value, time_t expiration);
-        int readRow(const char *table, const char* context, const char* key, string* pvalue, time_t* pexpiration, int version);
-        int updateRow(const char *table, const char* context, const char* key, const char* value, time_t expiration, int version);
-        bool deleteRow(const char *table, const char* context, const char* key);
-
-        void reap(const char* table, const char* context);
-        void updateContext(const char* table, const char* context, time_t expiration);
-        void deleteContext(const char* table, const char* context);
-
-        SQLHDBC getHDBC();
-        SQLHSTMT getHSTMT(SQLHDBC);
-        pair<SQLINTEGER,SQLINTEGER> getVersion(SQLHDBC);
-        pair<bool,bool> log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor=nullptr);
-
-        static void* cleanup_fn(void*); 
-        void cleanup();
-
-        Category& m_log;
-        Capabilities m_caps;
-        int m_cleanupInterval;
-        scoped_ptr<CondWait> shutdown_wait;
-        Thread* cleanup_thread;
-        bool shutdown;
-
-        SQLHENV m_henv;
-        string m_connstring;
-        long m_isolation;
-        bool m_wideVersion;
-        vector<SQLINTEGER> m_retries;
-    };
-
-    StorageService* ODBCStorageServiceFactory(const DOMElement* const & e, bool)
-    {
-        return new ODBCStorageService(e);
-    }
-
-    // convert SQL timestamp to time_t 
-    time_t timeFromTimestamp(SQL_TIMESTAMP_STRUCT expires)
-    {
-        time_t ret;
-        struct tm t;
-        t.tm_sec=expires.second;
-        t.tm_min=expires.minute;
-        t.tm_hour=expires.hour;
-        t.tm_mday=expires.day;
-        t.tm_mon=expires.month-1;
-        t.tm_year=expires.year-1900;
-        t.tm_isdst=0;
-#if defined(HAVE_TIMEGM)
-        ret = timegm(&t);
-#elif defined(WIN32)
-        ret = mktime(&t) - _timezone;
-#else
-        ret = mktime(&t) - timezone;
-#endif
-        return (ret);
-    }
-
-    // conver time_t to SQL string
-    void timestampFromTime(time_t t, char* ret)
-    {
-#ifdef HAVE_GMTIME_R
-        struct tm res;
-        struct tm* ptime=gmtime_r(&t,&res);
-#else
-        struct tm* ptime=gmtime(&t);
-#endif
-        strftime(ret,32,"{ts '%Y-%m-%d %H:%M:%S'}",ptime);
-    }
-
-    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, "'", "''");
-            }
-        }
-
-        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(XMLHelper::getAttrInt(e, 900, cleanupInterval)),
-    cleanup_thread(nullptr), shutdown(false), m_henv(SQL_NULL_HENV), m_isolation(SQL_TXN_SERIALIZABLE), m_wideVersion(false)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("ODBCStorageService");
-#endif
-    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_HENV) {
-        // Enable connection pooling.
-        SQLSetEnvAttr(SQL_NULL_HANDLE, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_HENV, 0);
-
-        // Allocate the environment.
-        if (!SQL_SUCCEEDED(SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_henv)))
-            throw XMLToolingException("ODBC failed to initialize.");
-
-        // Specify ODBC 3.x
-        SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
-
-        m_log.info("ODBC initialized");
-    }
-
-    // Grab connection string from the configuration.
-    e = e ? XMLHelper::getFirstChildElement(e, ConnectionString) : nullptr;
-    auto_ptr_char arg(XMLHelper::getTextContent(e));
-    if (!arg.get() || !*arg.get()) {
-        SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
-        throw XMLToolingException("ODBC StorageService requires ConnectionString element in configuration.");
-    }
-    m_connstring = arg.get();
-
-    // Connect and check version.
-    ODBCConn conn(getHDBC());
-    pair<SQLINTEGER,SQLINTEGER> v = getVersion(conn);
-
-    // Make sure we've got the right version.
-    if (v.first != PLUGIN_VER_MAJOR) {
-        SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
-        m_log.crit("unknown database version: %d.%d", v.first, v.second);
-        throw XMLToolingException("Unknown database version for ODBC StorageService.");
-    }
-    
-    if (v.first > 1 || v.second > 0) {
-        m_log.info("using 32-bit int type for version fields in tables");
-        m_wideVersion = true;
-    }
-
-    // Load any retry errors to check.
-    e = XMLHelper::getNextSiblingElement(e, RetryOnError);
-    while (e) {
-        if (e->hasChildNodes()) {
-            try {
-                int code = XMLString::parseInt(XMLHelper::getTextContent(e));
-                m_retries.push_back(code);
-                m_log.info("will retry operations when native ODBC error (%d) is returned", code);
-            }
-            catch (XMLException&) {
-                m_log.error("skipping non-numeric ODBC retry code");
-            }
-        }
-        e = XMLHelper::getNextSiblingElement(e, RetryOnError);
-    }
-
-    if (m_cleanupInterval > 0) {
-        // Initialize the cleanup thread
-        shutdown_wait.reset(CondWait::create());
-        cleanup_thread = Thread::create(&cleanup_fn, (void*)this);
-    }
-    else {
-        m_log.info("no cleanup interval configured, no cleanup thread will be started");
-    }
-}
-
-ODBCStorageService::~ODBCStorageService()
-{
-    shutdown = true;
-    if (shutdown_wait.get()) {
-        shutdown_wait->signal();
-    }
-    if (cleanup_thread) {
-        cleanup_thread->join(nullptr);
-    }
-    if (m_henv != SQL_NULL_HANDLE) {
-        SQLFreeHandle(SQL_HANDLE_ENV, m_henv);
-    }
-}
-
-pair<bool,bool> ODBCStorageService::log_error(SQLHANDLE handle, SQLSMALLINT htype, const char* checkfor)
-{
-    SQLSMALLINT	 i = 0;
-    SQLINTEGER	 native;
-    SQLCHAR	 state[7];
-    SQLCHAR	 text[256];
-    SQLSMALLINT	 len;
-    SQLRETURN	 ret;
-
-    pair<bool,bool> res = make_pair(false,false);
-    do {
-        ret = SQLGetDiagRec(htype, handle, ++i, state, &native, text, sizeof(text), &len);
-        if (SQL_SUCCEEDED(ret)) {
-            m_log.error("ODBC Error: %s:%ld:%ld:%s", state, i, native, text);
-            for (vector<SQLINTEGER>::const_iterator n = m_retries.begin(); !res.first && n != m_retries.end(); ++n)
-                res.first = (*n == native);
-            if (checkfor && !strcmp(checkfor, (const char*)state))
-                res.second = true;
-        }
-    } while(SQL_SUCCEEDED(ret));
-    return res;
-}
-
-SQLHDBC ODBCStorageService::getHDBC()
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("getHDBC");
-#endif
-
-    // Get a handle.
-    SQLHDBC handle = SQL_NULL_HDBC;
-    SQLRETURN sr = SQLAllocHandle(SQL_HANDLE_DBC, m_henv, &handle);
-    if (!SQL_SUCCEEDED(sr) || handle == SQL_NULL_HDBC) {
-        m_log.error("failed to allocate connection handle");
-        log_error(m_henv, SQL_HANDLE_ENV);
-        throw IOException("ODBC StorageService failed to allocate a connection handle.");
-    }
-
-    sr = SQLDriverConnect(handle,nullptr,(SQLCHAR*)m_connstring.c_str(),m_connstring.length(),nullptr,0,nullptr,SQL_DRIVER_NOPROMPT);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("failed to connect to database");
-        log_error(handle, SQL_HANDLE_DBC);
-        SQLFreeHandle(SQL_HANDLE_DBC, handle);
-        throw IOException("ODBC StorageService failed to connect to database.");
-    }
-
-    sr = SQLSetConnectAttr(handle, SQL_ATTR_TXN_ISOLATION, (SQLPOINTER)m_isolation, 0);
-    if (!SQL_SUCCEEDED(sr)) {
-        SQLDisconnect(handle);
-        SQLFreeHandle(SQL_HANDLE_DBC, handle);
-        throw IOException("ODBC StorageService failed to set transaction isolation level.");
-    }
-
-    return handle;
-}
-
-SQLHSTMT ODBCStorageService::getHSTMT(SQLHDBC conn)
-{
-    SQLHSTMT hstmt = SQL_NULL_HSTMT;
-    SQLRETURN sr = SQLAllocHandle(SQL_HANDLE_STMT, conn, &hstmt);
-    if (!SQL_SUCCEEDED(sr) || hstmt == SQL_NULL_HSTMT) {
-        m_log.error("failed to allocate statement handle");
-        log_error(conn, SQL_HANDLE_DBC);
-        throw IOException("ODBC StorageService failed to allocate a statement handle.");
-    }
-    return hstmt;
-}
-
-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);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("failed to read version from database");
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to read version from database.");
-    }
-
-    SQLINTEGER major;
-    SQLINTEGER minor;
-    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 make_pair(major,minor);
-
-    m_log.error("no rows returned in version query");
-    throw IOException("ODBC StorageService failed to read version from database.");
-}
-
-bool ODBCStorageService::createRow(const char* table, const char* context, const char* key, const char* value, time_t expiration)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("createRow");
-#endif
-
-    char timebuf[32];
-    timestampFromTime(expiration, timebuf);
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    string q  = string("INSERT INTO ") + table + " VALUES (?,?," + timebuf + ",1,?)";
-
-    SQLRETURN sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("SQLPrepare failed (t=%s, c=%s, k=%s)", table, context, key);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to insert record.");
-    }
-    m_log.debug("SQLPrepare succeeded. SQL: %s", q.c_str());
-
-    SQLLEN b_ind = SQL_NTS;
-    sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(context), &b_ind);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("SQLBindParam failed (context = %s)", context);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to insert record.");
-    }
-    m_log.debug("SQLBindParam succeeded (context = %s)", context);
-
-    sr = SQLBindParam(stmt, 2, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(key), &b_ind);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("SQLBindParam failed (key = %s)", key);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to insert record.");
-    }
-    m_log.debug("SQLBindParam succeeded (key = %s)", key);
-
-    if (strcmp(table, TEXT_TABLE)==0)
-        sr = SQLBindParam(stmt, 3, SQL_C_CHAR, SQL_LONGVARCHAR, strlen(value), 0, const_cast<char*>(value), &b_ind);
-    else
-        sr = SQLBindParam(stmt, 3, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(value), &b_ind);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("SQLBindParam failed (value = %s)", value);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to insert record.");
-    }
-    m_log.debug("SQLBindParam succeeded (value = %s)", value);
-    
-    int attempts = 3;
-    pair<bool,bool> logres;
-    do {
-        logres = make_pair(false,false);
-        attempts--;
-        sr = SQLExecute(stmt);
-        if (SQL_SUCCEEDED(sr)) {
-            m_log.debug("SQLExecute of insert succeeded");
-            return true;
-        }
-        m_log.error("insert record failed (t=%s, c=%s, k=%s)", table, context, key);
-        logres = log_error(stmt, SQL_HANDLE_STMT, "23000");
-        if (logres.second) {
-            // Supposedly integrity violation.
-            // Try and delete any expired record still hanging around until the final attempt.
-            if (attempts > 0) {
-                reap(table, context);
-                logres.first = true;    // force it to treat as a retryable error
-                continue;
-            }
-            return false;
-        }
-    } while (attempts && logres.first);
-
-    throw IOException("ODBC StorageService failed to insert record.");
-}
-
-int ODBCStorageService::readRow(const char *table, const char* context, const char* key, string* pvalue, time_t* pexpiration, int version)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("readRow");
-#endif
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    // Prepare and exectute select statement.
-    char timebuf[32];
-    timestampFromTime(time(nullptr), timebuf);
-    SQLString scontext(context);
-    SQLString skey(key);
-    string q("SELECT version");
-    if (pexpiration)
-        q += ",expires";
-    if (pvalue) {
-        pvalue->erase();
-        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.c_str());
-
-    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);
-        throw IOException("ODBC StorageService search failed.");
-    }
-
-    SQLSMALLINT ver;
-    SQLINTEGER widever;
-    SQL_TIMESTAMP_STRUCT expiration;
-
-    if (m_wideVersion)
-        SQLBindCol(stmt, 1, SQL_C_SLONG, &widever, 0, nullptr);
-    else
-        SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
-    if (pexpiration)
-        SQLBindCol(stmt, 2, SQL_C_TYPE_TIMESTAMP, &expiration, 0, nullptr);
-
-    if ((sr = SQLFetch(stmt)) == SQL_NO_DATA) {
-        if (m_log.isDebugEnabled())
-            m_log.debug("search returned no data (t=%s, c=%s, k=%s)", table, context, key);
-        return 0;
-    }
-
-    if (pexpiration)
-        *pexpiration = timeFromTimestamp(expiration);
-
-    if (version == (m_wideVersion ? widever : ver)) {
-        if (m_log.isDebugEnabled())
-            m_log.debug("versioned search detected no change (t=%s, c=%s, k=%s)", table, context, key);
-        return version; // nothing's changed, so just echo back the version
-    }
-
-    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) {
-            if (!SQL_SUCCEEDED(sr)) {
-                m_log.error("error while reading text field from result set");
-                log_error(stmt, SQL_HANDLE_STMT);
-                throw IOException("ODBC StorageService search failed to read data from result set.");
-            }
-            pvalue->append((char*)buf);
-        }
-    }
-    
-    return (m_wideVersion ? widever : ver);
-}
-
-int ODBCStorageService::updateRow(const char *table, const char* context, const char* key, const char* value, time_t expiration, int version)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("updateRow");
-#endif
-
-    if (!value && !expiration)
-        throw IOException("ODBC StorageService given invalid update instructions.");
-
-    // Get statement handle. Disable auto-commit mode to wrap select + update.
-    ODBCConn conn(getHDBC());
-    SQLRETURN sr = SQLSetConnectAttr(conn, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0);
-    if (!SQL_SUCCEEDED(sr))
-        throw IOException("ODBC StorageService failed to disable auto-commit mode.");
-    conn.autoCommit = false;
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    // First, fetch the current version for later, which also ensures the record still exists.
-    char timebuf[32];
-    timestampFromTime(time(nullptr), timebuf);
-    SQLString scontext(context);
-    SQLString skey(key);
-    string q("SELECT version FROM ");
-    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);
-    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);
-        throw IOException("ODBC StorageService search failed.");
-    }
-
-    SQLSMALLINT ver;
-    SQLINTEGER widever;
-    if (m_wideVersion)
-        SQLBindCol(stmt, 1, SQL_C_SLONG, &widever, 0, nullptr);
-    else
-        SQLBindCol(stmt, 1, SQL_C_SSHORT, &ver, 0, nullptr);
-    if ((sr = SQLFetch(stmt)) == SQL_NO_DATA) {
-        return 0;
-    }
-
-    // Check version?
-    if (version > 0 && version != (m_wideVersion ? widever : ver)) {
-        return -1;
-    }
-    else if ((m_wideVersion && widever == INT_MAX) || (!m_wideVersion && ver == 32767)) {
-        m_log.error("record version overflow (t=%s, c=%s, k=%s)", table, context, key);
-        throw IOException("Version overflow, record in ODBC StorageService could not be updated.");
-    }
-
-    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
-    stmt = getHSTMT(conn);
-
-    // Prepare and exectute update statement.
-    q = string("UPDATE ") + table + " SET ";
-
-    if (value)
-        q = q + "value=?, version=version+1";
-
-    if (expiration) {
-        timestampFromTime(expiration, timebuf);
-        if (value)
-            q += ',';
-        q = q + "expires = " + timebuf;
-    }
-
-    q = q + " WHERE context='" + scontext.tostr() + "' AND id='" + skey.tostr() + "'";
-
-    sr = SQLPrepare(stmt, (SQLCHAR*)q.c_str(), SQL_NTS);
-    if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("update of record failed (t=%s, c=%s, k=%s", table, context, key);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to update record.");
-    }
-    m_log.debug("SQLPrepare succeeded. SQL: %s", q.c_str());
-
-    SQLLEN b_ind = SQL_NTS;
-    if (value) {
-        if (strcmp(table, TEXT_TABLE)==0)
-            sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_LONGVARCHAR, strlen(value), 0, const_cast<char*>(value), &b_ind);
-        else
-            sr = SQLBindParam(stmt, 1, SQL_C_CHAR, SQL_VARCHAR, 255, 0, const_cast<char*>(value), &b_ind);
-        if (!SQL_SUCCEEDED(sr)) {
-            m_log.error("SQLBindParam failed (value = %s)", value);
-            log_error(stmt, SQL_HANDLE_STMT);
-            throw IOException("ODBC StorageService failed to update record.");
-        }
-        m_log.debug("SQLBindParam succeeded (value = %s)", value);
-    }
-
-    int attempts = 3;
-    pair<bool,bool> logres;
-    do {
-        logres = make_pair(false,false);
-        attempts--;
-        sr = SQLExecute(stmt);
-        if (sr == SQL_NO_DATA)
-            return 0;   // went missing?
-        else if (SQL_SUCCEEDED(sr)) {
-            m_log.debug("SQLExecute of update succeeded");
-            return (m_wideVersion ? widever : ver) + 1;
-        }
-
-        m_log.error("update of record failed (t=%s, c=%s, k=%s)", table, context, key);
-        logres = log_error(stmt, SQL_HANDLE_STMT);
-    } while (attempts && logres.first);
-
-    throw IOException("ODBC StorageService failed to update record.");
-}
-
-bool ODBCStorageService::deleteRow(const char *table, const char *context, const char* key)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("deleteRow");
-#endif
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    // Prepare and execute delete statement.
-    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)
-        return false;
-    else if (!SQL_SUCCEEDED(sr)) {
-        m_log.error("error deleting record (t=%s, c=%s, k=%s)", table, context, key);
-        log_error(stmt, SQL_HANDLE_STMT);
-        throw IOException("ODBC StorageService failed to delete record.");
-    }
-
-    return true;
-}
-
-
-void ODBCStorageService::cleanup()
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("cleanup");
-#endif
-
-    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.get(), m_cleanupInterval);
-        if (shutdown)
-            break;
-        try {
-            reap(nullptr);
-        }
-        catch (std::exception& ex) {
-            m_log.error("cleanup thread swallowed exception: %s", ex.what());
-        }
-    }
-
-    m_log.info("cleanup thread exiting...");
-
-    mutex->unlock();
-    Thread::exit(nullptr);
-}
-
-void* ODBCStorageService::cleanup_fn(void* cache_p)
-{
-  ODBCStorageService* cache = (ODBCStorageService*)cache_p;
-
-#ifndef WIN32
-  // First, let's block all signals
-  Thread::mask_all_signals();
-#endif
-
-  // Now run the cleanup process.
-  cache->cleanup();
-  return nullptr;
-}
-
-void ODBCStorageService::updateContext(const char *table, const char* context, time_t expiration)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("updateContext");
-#endif
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    char timebuf[32];
-    timestampFromTime(expiration, timebuf);
-
-    char nowbuf[32];
-    timestampFromTime(time(nullptr), nowbuf);
-
-    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)) {
-        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.");
-    }
-}
-
-void ODBCStorageService::reap(const char *table, const char* context)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("reap");
-#endif
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    // Prepare and execute delete statement.
-    char nowbuf[32];
-    timestampFromTime(time(nullptr), nowbuf);
-    string q;
-    if (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)) {
-        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.");
-    }
-}
-
-void ODBCStorageService::deleteContext(const char *table, const char* context)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("deleteContext");
-#endif
-
-    // Get statement handle.
-    ODBCConn conn(getHDBC());
-    SQLHSTMT stmt = getHSTMT(conn);
-
-    // Prepare and execute delete statement.
-    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)) {
-        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.");
-    }
-}
-
-extern "C" int ODBCSTORE_EXPORTS xmltooling_extension_init(void*)
-{
-    // Register this SS type
-    XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("ODBC", ODBCStorageServiceFactory);
-    return 0;
-}
-
-extern "C" void ODBCSTORE_EXPORTS xmltooling_extension_term()
-{
-    XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("ODBC");
-}
diff --git a/odbc-store/odbc-store.rc b/odbc-store/odbc-store.rc
deleted file mode 100644
index c080114e..00000000
--- a/odbc-store/odbc-store.rc
+++ /dev/null
@@ -1,97 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth ODBC Storage Service Plugin\0"
-            VALUE "InternalName", "odbc-store\0"
-            VALUE "OriginalFilename", "odbc-store.so\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
diff --git a/odbc-store/resource.h b/odbc-store/resource.h
deleted file mode 100644
index 3190f4a8..00000000
--- a/odbc-store/resource.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Visual C++ generated include file.
-// Used by odbc-store.rc
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/selinux/Makefile.am b/selinux/Makefile.am
deleted file mode 100644
index f404e4d2..00000000
--- a/selinux/Makefile.am
+++ /dev/null
@@ -1,25 +0,0 @@
-## $Id$ 
-
-AUTOMAKE_OPTIONS = foreign
-
-varrundir = $(localstatedir)/run
-BUILDFILES = shibshar.fc
-CLEANFILES = $(BUILDFILES)
-
-sepolicy = targeted
-selinuxdir = $(sysconfdir)/selinux/targeted/src/policy
-fcfiledir = $(selinuxdir)/file_contexts/program
-fcfile_DATA = shibshar.fc
-
-tefiledir = $(selinuxdir)/domains/program
-tefile_DATA = shibshar.te
-
-shibshar.fc: ${srcdir}/shibshar.fc.in Makefile ${top_builddir}/config.status
-	rm -f $@.tmp
-	sed < ${srcdir}/$@.in > $@.tmp \
-	    -e 's:@-SBINDIR-@:${sbindir}:' \
-	    -e 's:@-VARRUNDIR-@:${varrundir}:'
-	cmp -s $@ $@.tmp || mv $@.tmp $@
-	rm -f $@.tmp
-
-EXTRA_DIST = shibshar.fc.in shibshar.te
diff --git a/selinux/shibshar.fc.in b/selinux/shibshar.fc.in
deleted file mode 100644
index 34d9bd22..00000000
--- a/selinux/shibshar.fc.in
+++ /dev/null
@@ -1,4 +0,0 @@
-# Shibboleth SHAR
- at -SBINDIR-@/shibd	--	system_u:object_r:shibshar_exec_t
- at -VARRUNDIR-@/shib-shar\.sock	-s	system_u:object_r:shibshar_var_run_t
-
diff --git a/selinux/shibshar.te b/selinux/shibshar.te
deleted file mode 100644
index 321da2e8..00000000
--- a/selinux/shibshar.te
+++ /dev/null
@@ -1,33 +0,0 @@
-# Shibboleth SHAR
-
-# Define the shibshar daemon.
-daemon_domain(shibshar)
-
-# Transition the shar socket to the shibshar_var_run_t type
-# when the shar creates it
-file_type_auto_trans(shibshar_t, var_run_t, shibshar_var_run_t, sock_file)
-
-# Enable the shar to work
-can_exec(shibshar_t, shibshar_exec_t)
-uses_shlib(shibshar_t)
-can_network(shibshar_t)
-can_tcp_connect(shibshar_t, unconfined_t)
-allow shibshar_t port_type:tcp_socket name_connect;
-allow shibshar_t etc_t:file r_file_perms;
-allow shibshar_t bin_t:dir r_dir_perms;
-allow shibshar_t bin_t:file rx_file_perms;
-allow shibshar_t var_log_t:dir rw_dir_perms;
-allow shibshar_t var_log_t:file rw_file_perms;
-allow shibshar_t var_log_t:file { create };
-
-allow shibshar_t shibshar_t:unix_stream_socket create_stream_socket_perms;
-allow shibshar_t shibshar_t:netlink_route_socket { create bind getattr};
-allow shibshar_t usr_t:dir r_dir_perms;
-allow shibshar_t usr_t:file rx_file_perms;
-
-allow shibshar_t urandom_device_t:chr_file { getattr ioctl read };
- 
-# Enable HTTPD to connect to the shib-shar socket and read/write to it
-can_unix_connect(httpd_t, shibshar_var_run_t)
-allow httpd_t shibshar_var_run_t:sock_file { write };
-allow httpd_t shibshar_t:unix_stream_socket { connectto };
diff --git a/shibboleth.spec.in b/shibboleth.spec.in
deleted file mode 100644
index 3a9693e9..00000000
--- a/shibboleth.spec.in
+++ /dev/null
@@ -1,646 +0,0 @@
-Name:		shibboleth
-Version:	@PACKAGE_VERSION@
-Release:	1
-Summary:	Open source system for attribute-based Web SSO
-Group:		Productivity/Networking/Security
-Vendor:		Shibboleth Consortium
-License:	Apache-2.0
-URL:		http://shibboleth.net/
-Source:		%{name}-sp-%{version}.tar.bz2
-BuildRoot:	%{_tmppath}/%{name}-sp-%{version}-root
-Obsoletes:	shibboleth-sp = 2.5.0
-Requires:	openssl
-%if 0%{?rhel} >= 6 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-PreReq:		xmltooling-schemas%{?_isa} >= 3.2.0, opensaml-schemas%{?_isa} >= 3.2.0
-%else
-PreReq:		xmltooling-schemas >= 3.2.0, opensaml-schemas >= 3.2.0
-%endif
-%if 0%{?suse_version} > 1030 && 0%{?suse_version} < 1130
-PreReq:		%{insserv_prereq} %{fillup_prereq}
-%endif
-%if 0%{?rhel} >= 7
-Requires: hostname
-BuildRequires:  systemd-devel
-%else
-Requires: net-tools
-%endif
-%if 0%{?rhel} >= 8
-BuildRequires:  gdb
-%endif
-BuildRequires:  libxerces-c-devel >= 3.2
-BuildRequires:	libxml-security-c-devel >= 2.0.0
-BuildRequires:	libxmltooling-devel >= 3.2.0
-BuildRequires:	libsaml-devel >= 3.2.0
-%{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
-%{!?_with_log4cpp:BuildRequires: liblog4shib-devel >= 2}
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-Requires:	libcurl-openssl%{?_isa} >= 7.21.7
-BuildRequires:	chrpath
-%endif
-%if 0%{?suse_version} > 1300
-BuildRequires:	libtool
-%endif
-BuildRequires:  gcc-c++, pkgconfig, boost-devel >= 1.32.0
-%{!?_without_gssapi:BuildRequires: krb5-devel}
-%{!?_without_doxygen:BuildRequires: doxygen}
-%{!?_without_odbc:BuildRequires:unixODBC-devel}
-%{?_with_fastcgi:BuildRequires: fcgi-devel}
-%if 0%{?centos} == 6 || 0%{?centos} == 7
-BuildRequires:	libmemcached-devel
-%endif
-%{?_with_memcached:BuildRequires: libmemcached-devel}
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-%if 0%{?rhel} >= 6 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-%{!?_without_builtinapache:BuildRequires: httpd-devel%{?_isa}}
-%else
-%{!?_without_builtinapache:BuildRequires: httpd-devel}
-%endif
-BuildRequires: redhat-rpm-config
-Requires(pre): shadow-utils
-Requires(post): chkconfig
-Requires(preun): chkconfig, initscripts
-%endif
-%if "%{_vendor}" == "suse"
-Requires(pre): pwdutils
-%{!?_without_builtinapache:BuildRequires: apache2-devel}
-%{?systemd_requires}
-%if 0%{?suse_version} >= 1210
-BuildRequires: systemd-rpm-macros, systemd-devel
-%endif
-%endif
-
-%{!?_tmpfilesdir:%global _tmpfilesdir /usr/lib/tmpfiles.d}
-
-%define runuser shibd
-%if "%{_vendor}" == "suse"
-%define pkgdocdir %{_docdir}/shibboleth
-%else
-%define pkgdocdir %{_docdir}/shibboleth-%{version}
-%endif
-
-%description
-Shibboleth is a Web Single Sign-On implementations based on OpenSAML
-that supports multiple protocols, federated identity, and the extensible
-exchange of rich attributes subject to privacy controls.
-
-This package contains the Shibboleth Service Provider runtime libraries,
-daemon, default plugins, and Apache module(s).
-
-%package devel
-Summary:	Shibboleth Development Headers
-Group:		Development/Libraries/C and C++
-Requires:	%{name} = %{version}-%{release}
-Obsoletes:	shibboleth-sp-devel = 2.5.0
-Requires:	libxerces-c-devel >= 3.2
-Requires: 	libxml-security-c-devel >= 2.0.0
-Requires: 	libxmltooling-devel >= 3.2.0
-Requires: 	libsaml-devel >= 3.2.0
-%{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
-%{!?_with_log4cpp:Requires: liblog4shib-devel >= 2}
-
-%description devel
-Shibboleth is a Web Single Sign-On implementations based on OpenSAML
-that supports multiple protocols, federated identity, and the extensible
-exchange of rich attributes subject to privacy controls.
-
-This package includes files needed for development with Shibboleth.
-
-%prep
-%setup -n %{name}-sp-%{version}
-
-%build
-%if 0%{?suse_version} >= 1300
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_systemd:--enable-systemd} %{?shib_options} PKG_CONFIG_PATH=./pkgconfig-workarounds/opensuse13
-%else
-%if 0%{?suse_version} >= 1210
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_systemd:--enable-systemd} %{?shib_options}
-%else
-%if 0%{?rhel} >= 8
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with-memcached} %{!?_without_systemd:--enable-systemd} %{?shib_options}
-%else
-%if 0%{?rhel} >= 7
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_memcached:--with-memcached} %{!?_without_systemd:--enable-systemd} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig
-%else
-%if 0%{?centos} >= 6
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{!?_without_memcached:--with-memcached} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig:./pkgconfig-workarounds/rh6
-%else
-%if 0%{?rhel} >= 6
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with-memcached} %{?shib_options} PKG_CONFIG_PATH=/opt/shibboleth/%{_lib}/pkgconfig:./pkgconfig-workarounds/rh6
-%else
-%if 0%{?rhel} >= 5
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with_memcached} %{?shib_options} PKG_CONFIG_PATH=./pkgconfig-workarounds/rh5
-%else
-    %configure %{?_without_odbc:--disable-odbc} %{?_without_adfs:--disable-adfs} %{?_with_fastcgi} %{!?_without_gssapi:--with-gssapi} %{?_with_memcached} %{?shib_options}
-%endif
-%endif
-%endif
-%endif
-%endif
-%endif
-%endif
-%{__make} pkgdocdir=%{pkgdocdir}
-
-%install
-%{__make} install NOKEYGEN=1 DESTDIR=$RPM_BUILD_ROOT pkgdocdir=%{pkgdocdir}
-
-%if "%{_vendor}" == "suse"
-	%{__sed} -i "s/\/var\/log\/httpd/\/var\/log\/apache2/g" \
-		$RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/native.logger
-%endif
-
-# Plug the SP into the built-in Apache on a recognized system.
-touch rpm.filelist
-APACHE_CONFIG="no"
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_13.so ] ; then
-	APACHE_CONFIG="apache.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_20.so ] ; then
-	APACHE_CONFIG="apache2.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_22.so ] ; then
-	APACHE_CONFIG="apache22.config"
-fi
-if [ -f $RPM_BUILD_ROOT%{_libdir}/shibboleth/mod_shib_24.so ] ; then
-	APACHE_CONFIG="apache24.config"
-fi
-%{?_without_builtinapache:APACHE_CONFIG="no"}
-if [ "$APACHE_CONFIG" != "no" ] ; then
-	APACHE_CONFD="no"
-	if [ -d %{_sysconfdir}/httpd/conf.d ] ; then
-		APACHE_CONFD="%{_sysconfdir}/httpd/conf.d"
-	fi
-	if [ -d %{_sysconfdir}/apache2/conf.d ] ; then
-		APACHE_CONFD="%{_sysconfdir}/apache2/conf.d"
-	fi
-	if [ "$APACHE_CONFD" != "no" ] ; then
-		%{__mkdir} -p $RPM_BUILD_ROOT$APACHE_CONFD
-		%{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/$APACHE_CONFIG $RPM_BUILD_ROOT$APACHE_CONFD/shib.conf 
-		echo "%config(noreplace) $APACHE_CONFD/shib.conf" >> rpm.filelist
-	fi
-fi
-
-# Establish location of systemd file, if any.
-SYSTEMD_SHIBD="no"
-%if 0%{?suse_version} >= 1210 || 0%{?rhel} >= 7
-	%{__mkdir} -p $RPM_BUILD_ROOT%{_unitdir}
-	echo "%attr(0444,-,-) %{_unitdir}/shibd.service" >> rpm.filelist
-	SYSTEMD_SHIBD="$RPM_BUILD_ROOT%{_unitdir}/shibd.service"
-
-	# Get run directory created at boot time.
-	%{__mkdir} -p $RPM_BUILD_ROOT%{_tmpfilesdir}
-	echo "%attr(0444,-,-) %{_tmpfilesdir}/%{name}.conf" >> rpm.filelist
-	cat > $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf <<EOF
-d /run/%{name} 755 %{runuser} %{runuser} -
-EOF
-%endif
-
-# Otherwise, establish location of sysconfig file, if any.
-SYSCONFIG_SHIBD="no"
-if [ "$SYSTEMD_SHIBD" == "no" ] ; then
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-	%{__mkdir} -p $RPM_BUILD_ROOT%{_sysconfdir}/sysconfig
-	echo "%config(noreplace) %{_sysconfdir}/sysconfig/shibd" >> rpm.filelist
-	SYSCONFIG_SHIBD="$RPM_BUILD_ROOT%{_sysconfdir}/sysconfig/shibd"
-%endif
-%if "%{_vendor}" == "suse"
-	%{__mkdir} -p $RPM_BUILD_ROOT%{_localstatedir}/adm/fillup-templates
-	echo "%{_localstatedir}/adm/fillup-templates/sysconfig.shibd" >> rpm.filelist
-	SYSCONFIG_SHIBD="$RPM_BUILD_ROOT%{_localstatedir}/adm/fillup-templates/sysconfig.shibd"
-%endif
-fi
-
-if [ "$SYSTEMD_SHIBD" != "no" ] ; then
-	# Populate the systemd file
-	cat > $SYSTEMD_SHIBD <<EOF
-[Unit]
-Description=Shibboleth Service Provider Daemon
-Documentation=https://wiki.shibboleth.net/confluence/display/SP3/Home
-After=network-online.target
-Before=httpd.service
-
-[Service]
-Type=notify
-NotifyAccess=main
-User=%{runuser}
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-Environment=LD_LIBRARY_PATH=/opt/shibboleth/%{_lib}
-%endif
-ExecStart=%{_sbindir}/shibd -f -F
-StandardInput=null
-StandardOutput=null
-StandardError=journal
-TimeoutStopSec=1m
-TimeoutStartSec=5m
-Restart=on-failure
-RestartSec=30s
-
-[Install]
-WantedBy=multi-user.target
-EOF
-elif [ "$SYSCONFIG_SHIBD" != "no" ] ; then
-	# Populate the sysconfig file.
-	cat > $SYSCONFIG_SHIBD <<EOF
-# Shibboleth SP init script customization
-
-# User account for shibd
-SHIBD_USER=%{runuser}
-
-# Umask for shibd
-# SHIBD_UMASK=022
-
-# Wait period (secs) for configuration (and metadata) to load
-SHIBD_WAIT=30
-EOF
-	%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-		cat >> $SYSCONFIG_SHIBD <<EOF
-
-# Override OS-supplied libcurl
-export LD_LIBRARY_PATH=/opt/shibboleth/%{_lib}
-EOF
-	%endif
-fi
-
-%if 0%{?rhel} == 6 || 0%{?rhel} == 7 || 0%{?amzn} == 1 || 0%{?amzn} == 2
-	# Strip existing rpath to libcurl.
-	chrpath -d $RPM_BUILD_ROOT%{_sbindir}/shibd
-	chrpath -d $RPM_BUILD_ROOT%{_bindir}/mdquery
-	chrpath -d $RPM_BUILD_ROOT%{_bindir}/resolvertest
-%endif
-
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon" || "%{_vendor}" == "suse"
-if [ "$SYSTEMD_SHIBD" == "no" ] ; then
-	# %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
-	install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
-	install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/shibboleth/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
-%if "%{_vendor}" == "suse"
-	install -d -m 0755 $RPM_BUILD_ROOT/%{_sbindir}
-	%{__ln_s} -f %{_initrddir}/shibd $RPM_BUILD_ROOT%{_sbindir}/rcshibd
-%endif
-fi
-%endif
-
-%check
-%{__make} check
-
-%clean
-[ "$RPM_BUILD_ROOT" != "/" ] && %{__rm} -rf $RPM_BUILD_ROOT
-
-%pre
-getent group %{runuser} >/dev/null || groupadd -r %{runuser}
-getent passwd %{runuser} >/dev/null || useradd -r -g %{runuser} \
-	-d  %{_localstatedir}/run/shibboleth -s /sbin/nologin -c "Shibboleth SP daemon" %{runuser}
-%if 0%{?suse_version} >= 1210
-	%service_add_pre shibd.service
-%endif
-exit 0
-
-%post
-/sbin/ldconfig
-
-# Generate two keys on new installs.
-if [ $1 -eq 1 ] ; then
-	cd %{_sysconfdir}/shibboleth
-	/bin/sh ./keygen.sh -b -n sp-signing -u %{runuser} -g %{runuser}
-	/bin/sh ./keygen.sh -b -n sp-encrypt -u %{runuser} -g %{runuser}
-fi
-
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-if [ $1 -gt 1 ] ; then
-		# On Red Hat with shib.conf installed, clean up old Alias commands
-		# by pointing them at new version-independent /usr/share/share tree.
-		# Any Aliases we didn't create we assume are custom files.
-		# This is to accomodate making shib.conf a noreplace config file.
-		# We can't do this for SUSE, because they disallow changes to
-		# packaged files in scriplets.
-		APACHE_CONF="no"
-		if [ -f %{_sysconfdir}/httpd/conf.d/shib.conf ] ; then
-			APACHE_CONF="%{_sysconfdir}/httpd/conf.d/shib.conf"
-		fi
-		if [ "$APACHE_CONF" != "no" ] ; then
-			%{__sed} -i "s/\/usr\/share\/doc\/shibboleth\(\-\(.\)\{1,\}\)\{0,1\}\/main\.css/\/usr\/share\/shibboleth\/main.css/g" \
-				$APACHE_CONF
-			%{__sed} -i "s/\/usr\/share\/doc\/shibboleth\(\-\(.\)\{1,\}\)\{0,1\}\/logo\.jpg/\/usr\/share\/shibboleth\/logo.jpg/g" \
-				$APACHE_CONF
-		fi
-	fi
-
-%if 0%{?rhel} >= 7
-	# Initial prep for systemd
-	%systemd_post shibd.service
-	if [ $1 -gt 1 ] ; then
-		systemctl daemon-reload
-	fi
-%else
-	# Add the proper /etc/rc*.d links for the script
-	/sbin/chkconfig --add shibd
-%endif
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
-	%service_add_post shibd.service
-	systemd-tmpfiles --create %{_tmpfilesdir}/%{name}.conf
-%else
-	# This adds the proper /etc/rc*.d links for the script
-	# and populates the sysconfig/shibd file.
-	cd /
-	%{fillup_only -n shibd}
-	%insserv_force_if_yast shibd
-%endif
-%endif
-
-%preun
-# On final removal, stop shibd and remove service, restart Apache if running.
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-%if 0%{?rhel} >= 7
-	%systemd_preun shibd.service
-%else
-	if [ $1 -eq 0 ] ; then
-		/sbin/service shibd stop >/dev/null 2>&1
-		/sbin/chkconfig --del shibd
-	fi
-%endif
-	if [ $1 -eq 0 ] ; then
-		%{!?_without_builtinapache:/sbin/service httpd status 1>/dev/null && /sbin/service httpd restart 1>/dev/null}
-		exit 0
-	fi
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
-        %service_del_preun shibd.service
-%else
-	%stop_on_removal shibd
-%endif
-	if [ $1 -eq 0 ] ; then
-		%{!?_without_builtinapache:/sbin/service apache2 status 1>/dev/null && /sbin/service apache2 restart 1>/dev/null}
-		exit 0
-	fi
-%endif
-exit 0
-
-%postun
-/sbin/ldconfig
-%if "%{_vendor}" == "redhat" || "%{_vendor}" == "amazon"
-# On upgrade, restart components if they're already running.
-%if 0%{?rhel} >= 7
-	%systemd_postun_with_restart shibd.service
-%else
-	if [ $1 -ge 1 ] ; then
-		/sbin/service shibd status 1>/dev/null && /sbin/service shibd restart 1>/dev/null
-	fi
-%endif
-	if [ $1 -ge 1 ] ; then
-		%{!?_without_builtinapache:/sbin/service httpd status 1>/dev/null && /sbin/service httpd restart 1>/dev/null}
-		exit 0
-	fi
-%endif
-%if "%{_vendor}" == "suse"
-%if 0%{?suse_version} >= 1210
-	%service_del_postun shibd.service
-%else
-	cd / 
-	%restart_on_update shibd
-	%{insserv_cleanup}
-%endif
-	%{!?_without_builtinapache:%restart_on_update apache2}
-%endif
-
-%posttrans
-# One-time extra restart of shibd and Apache to work around
-# SUSE bug that breaks old %restart_on_update macro.
-# If we remove, upgrades from pre-systemd to post-systemd
-# will stop doing the final restart.
-%if "%{_vendor}" == "suse" && 0%{?suse_version} >= 1210
-	/usr/bin/systemctl try-restart shibd >/dev/null 2>&1 || :
-	/usr/bin/systemctl try-restart apache2 >/dev/null 2>&1 || :
-%endif
-exit 0
-
-%files -f rpm.filelist
-%defattr(-,root,root,-)
-%{_sbindir}/shibd
-%{_bindir}/mdquery
-%{_bindir}/resolvertest
-%{_libdir}/libshibsp.so.*
-%{_libdir}/libshibsp-lite.so.*
-%exclude %{_libdir}/*.la
-%dir %{_libdir}/shibboleth
-%{_libdir}/shibboleth/*.so
-%exclude %{_libdir}/shibboleth/*.la
-%{?_with_fastcgi:%{_libdir}/shibboleth/shibauthorizer}
-%{?_with_fastcgi:%{_libdir}/shibboleth/shibresponder} 
-%attr(0750,%{runuser},%{runuser}) %dir %{_localstatedir}/log/shibboleth
-%if 0%{?suse_version} < 1300
-%attr(0755,%{runuser},%{runuser}) %dir %{_localstatedir}/run/shibboleth
-%endif
-%attr(0755,%{runuser},%{runuser}) %dir %{_localstatedir}/cache/shibboleth
-%dir %{_datadir}/xml/shibboleth
-%{_datadir}/xml/shibboleth/*
-%dir %{_datadir}/shibboleth
-%{_datadir}/shibboleth/*
-%dir %{_sysconfdir}/shibboleth
-%config(missingok, noreplace) %{_sysconfdir}/shibboleth/shibboleth2.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/attribute-map.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/attribute-policy.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/example-metadata.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/protocols.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/security-policy.xml
-%config(noreplace) %{_sysconfdir}/shibboleth/*.html
-%config(noreplace) %{_sysconfdir}/shibboleth/*.logger
-%if "%{_vendor}" == "redhat"
-%if 0%{?rhel} >= 7
-%else
-%config %{_initrddir}/shibd
-%endif
-%endif
-%if "%{_vendor}" == "amazon"
-%config %{_initrddir}/shibd
-%endif
-%if "%{_vendor}" == "suse" && 0%{?suse_version} < 1210
-%config %{_initrddir}/shibd
-%{_sbindir}/rcshibd
-%endif
-%if 0%{?suse_version} >= 1210 || 0%{?rhel} >= 7
-%{_tmpfilesdir}/%{name}.conf
-%endif
-%{_sysconfdir}/shibboleth/example-shibboleth2.xml
-%{_sysconfdir}/shibboleth/*.dist
-%{_sysconfdir}/shibboleth/apache*.config
-%{_sysconfdir}/shibboleth/shibd-*
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/keygen.sh
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/metagen.sh
-%attr(0755,root,root) %{_sysconfdir}/shibboleth/seckeygen.sh
-%doc %{pkgdocdir}
-%exclude %{pkgdocdir}/api
-
-%files devel
-%defattr(-,root,root,-)
-%{_includedir}/*
-%{_libdir}/libshibsp.so
-%{_libdir}/libshibsp-lite.so
-%{_libdir}/pkgconfig/*.pc
-%doc %{pkgdocdir}/api
-
-%changelog
-* Wed Nov 2 2022 Scott Cantor <cantor.2 at osu.edu> - 3.4.0-1
-- Version bump
-
-* Thu Apr 22 2021 Scott Cantor <cantor.2 at osu.edu> - 3.2.2-1
-- Fix devel dependency versions
-
-* Tue Dec 1 2020 Scott Cantor <cantor.2 at osu.edu> - 3.2.0-1
-- Version and lib bump
-
-* Mon Feb 3 2020 Scott Cantor <cantor.2 at osu.edu> - 3.1.0-1
-- Version and lib bump
-- Add hostname dependency for keygen script
-
-* Mon Sep 30 2019 Scott Cantor <cantor.2 at osu.edu> - 3.0.4-1
-- CentOS 8 cleanup
-
-* Mon Apr 30 2018 Scott Cantor <cantor.2 at osu.edu> - 3.0.0-1
-- Bump dependency versions
-- Require updated libraries across the board
-- Generate two keys on new installs
-
-* Tue May 03 2016 Scott Cantor <cantor.2 at osu.edu> - 2.6.0-1
-- Bump opensaml dependency version
-- Bump max wait time for shibd systemd unit file
-
-* Thu Jul 23 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.5-2
-- Fix use of /var/run/shibboleth on newer tmpfs platforms
-
-* Thu Jul 2 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.5-1
-- Revamp with systemd support for RH/CentOS 7+ and SUSE 12.1+
-
-* Mon Mar 9 2015 Scott Cantor <cantor.2 at osu.edu> - 2.5.4-1
-- Add Amazon VM support
-- Add a separate native logging directory
-- Remove hard-coded init.d usage
-- Switch to bz2 sources to prevent future issues with SuSE
-
-* Mon Nov 17 2014 Scott Cantor <cantor.2 at osu.edu> - 2.5.3-2
-- Add libtool dep for OpenSUSE 13
-- Remove /var/run/shibboleth for OpenSUSE 13
-
-* Tue May 13 2014 Ian Young <ian at iay.org.uk> - 2.5.3-1.2
-- Update package dependencies for RHEL/CentOS 7
-- Fix bogus dates in changelog
-
-* Sat Jun 8 2013   Scott Cantor  <cantor.2 at osu.edu>  - 2.5.2-1
-- Add --with-gssapi using MIT K5 by default
-
-* Tue Sep 25 2012  Scott Cantor  <cantor.2 at osu.edu>  - 2.5.1-1
-- Merge back various changes used in released packages
-- Prep for 2.5.1 by pulling extra restart out
-
-* Tue Aug 7 2012  Scott Cantor  <cantor.2 at osu.edu>  - 2.5.0-2
-- Changed package name back to shibboleth because of upgrade bugs
-- Put back extra restart for this release only.
-
-* Thu Mar 1 2012  Scott Cantor  <cantor.2 at osu.edu>  - 2.5.0-1
-- Move logo and stylesheet to version-independent tree
-- Make shib.conf noreplace
-- Post-fixup of Alias commands in older shib.conf
-- Changes to run shibd as non-root shibboleth user
-- Move init customizations to /etc/sysconfig/shibd
-- Copy shibd restart for Red Hat to postun
-- Add boost-devel dependency
-- Build memcache plugin on RH6
-- Add cachedir to install
-- Add Apache 2.4 to install
-
-* Sun Jun 26 2011  Scott Cantor  <cantor.2 at osu.edu>  - 2.4.3-1
-- Log files shouldn't be world readable.
-- Explicit requirement for libcurl-openssl on RHEL6
-- Uncomment LD_LIBRARY_PATH in init script for RHEL6 
-- Remove rpath from binaries for RHEL6
-
-* Fri Dec 25 2009  Scott Cantor  <cantor.2 at osu.edu>  - 2.4-1
-- Update dependencies.
-
-* Mon Nov 23 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.3.1-1
-- Reset revision for 2.3.1 release
-
-* Wed Aug 19 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.2.1-2
-- SuSE init script changes
-- Restart Apache on removal, not just upgrade
-- Fix scriptlet exit values when Apache is stopped
-
-* Mon Aug 10 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.2.1-1
-- Doc handling changes
-- SuSE init script
-
-* Tue Aug 4 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.2.1-1
-- Initial version for 2.2.1, with shibd/httpd restart on upgrade
-
-* Thu Jun 25 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.2-3
-- Add additional cleanup to posttrans fix
-
-* Tue Jun 23 2009 Scott Cantor  <cantor.2 at osu.edu>  - 2.2-2
-- Reverse without_builtinapache macro test
-- Fix init script handling on Red Hat to handle upgrades
-
-* Wed Dec 3 2008  Scott Cantor  <cantor.2 at osu.edu>  - 2.2-1
-- Bump minor version.
-- Make keygen.sh executable.
-- Fixing SUSE Xerces dependency name.
-- Optionally package shib.conf.
-
-* Tue Jun 10 2008  Scott Cantor  <cantor.2 at osu.edu>  - 2.1-1
-- Change shib.conf handling to treat as config file.
-
-* Mon Mar 17 2008  Scott Cantor  <cantor.2 at osu.edu>  - 2.0-6
-- Official release.
-
-* Fri Jan 18 2008  Scott Cantor  <cantor.2 at osu.edu>  - 2.0-5
-- Release candidate 1.
-
-* Sun Oct 21 2007 Scott Cantor  <cantor.2 at osu.edu>  - 2.0-4
-- libexec -> lib/shibboleth changes
-- Added doc subpackage
-
-* Thu Aug 16 2007 Scott Cantor  <cantor.2 at osu.edu>  - 2.0-3
-- First public beta.
-
-* Fri Jul 13 2007 Scott Cantor	<cantor.2 at osu.edu>  - 2.0-2
-- Second alpha release.
-
-* Sun Jun 10 2007 Scott Cantor	<cantor.2 at osu.edu>  - 2.0-1
-- First alpha release.
-
-* Mon Oct 2 2006 Scott Cantor	<cantor.2 at osu.edu>  - 1.3-11
-- Applied fix for secadv 20061002
-- Fix for metadata loader loop
-
-* Thu Jun 15 2006 Scott Cantor  <cantor.2 at osu.edu>  - 1.3-10
-- Applied fix for sec 20060615
-
-* Sat Apr 15 2006 Scott Cantor  <cantor.2 at osu.edu>  - 1.3-9
-- Misc. patches, SuSE, Apache 2.2, gcc 4.1, and 64-bit support
-
-* Mon Jan 9 2006 Scott Cantor  <cantor.2 at osu.edu>  - 1.3-8
-- Applied new fix for secadv 20060109
-
-* Tue Nov 8 2005 Scott Cantor  <cantor.2 at osu.edu>  - 1.3-7
-- Applied new fix for secadv 20050901 plus rollup
-
-* Fri Sep 23 2005 Scott Cantor  <cantor.2 at osu.edu>  - 1.3-6
-- Minor patches and default config changes
-- pidfile patch
-- Fix shib.conf creation
-- Integrated init.d script
-- Prevent replacement of config files
-
-* Thu Sep 1 2005  Scott Cantor  <cantor.2 at osu.edu>  - 1.3-5
-- Applied fix for secadv 20050901 plus rollup of NSAPI fixes
-
-* Sun Apr 24 2005  Scott Cantor  <cantor.2 at osu.edu>  - 1.3-1
-- Updated test programs and location of schemas.
-- move siterefresh to to sbindir
-
-* Fri Apr  1 2005  Derek Atkins  <derek at ihtfp.com>  - 1.3-1
-- Add selinux-targeted-policy package
-- move shar to sbindir
-
-* Tue Oct 19 2004  Derek Atkins  <derek at ihtfp.com>  - 1.2-1
-- Create SPEC file based on various versions in existence.
diff --git a/shibd/Makefile.am b/shibd/Makefile.am
deleted file mode 100644
index 596de41f..00000000
--- a/shibd/Makefile.am
+++ /dev/null
@@ -1,22 +0,0 @@
-AUTOMAKE_OPTIONS = foreign
-
-sbin_PROGRAMS = shibd
-
-shibd_SOURCES = shibd.cpp
-
-shibd_CXXFLAGS = \
-  $(AM_CXXFLAGS) \
-  $(PTHREAD_CFLAGS) \
-  $(SYSTEMD_CFLAGS) \
-  $(opensaml_CFLAGS) \
-  $(xerces_CFLAGS) \
-  $(xmltooling_CFLAGS)
-shibd_LDADD = \
-  $(top_builddir)/shibsp/libshibsp.la \
-  $(PTHREAD_LIBS) \
-  $(SYSTEMD_LIBS) \
-  $(opensaml_LIBS) \
-  $(xerces_LIBS) \
-  $(xmltooling_LIBS)
-
-EXTRA_DIST = shibd_win32.cpp resource.h shibd.rc
diff --git a/shibd/resource.h b/shibd/resource.h
deleted file mode 100644
index b5e13998..00000000
--- a/shibd/resource.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by shibd.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
diff --git a/shibd/shibd.cpp b/shibd/shibd.cpp
deleted file mode 100644
index 5a31f7e1..00000000
--- a/shibd/shibd.cpp
+++ /dev/null
@@ -1,484 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/*
- * shibd.cpp -- the shibd "main" code.
- */
-
-
-// eventually we might be able to support autoconf via cygwin...
-#if defined (_MSC_VER) || defined(__BORLANDC__)
-# include "config_win32.h"
-#else
-# include "config.h"
-#endif
-
-#ifdef WIN32
-# define _CRT_NONSTDC_NO_DEPRECATE 1
-# define _CRT_SECURE_NO_DEPRECATE 1
-#endif
-
-#include <shibsp/SPConfig.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# include <sys/select.h>
-#endif
-
-#if defined(HAVE_GRP_H) && defined(HAVE_PWD_H)
-# include <pwd.h>
-# include <grp.h>
-#endif
-
-#include <stdio.h>
-#include <signal.h>
-#include <shibsp/ServiceProvider.h>
-#include <shibsp/remoting/ListenerService.h>
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifdef HAVE_SD_NOTIFY
-#include <systemd/sd-daemon.h>
-#else
-#define SD_EMERG   ""
-#define SD_ALERT   ""
-#define SD_CRIT    ""
-#define SD_ERR     ""
-#define SD_WARNING ""
-#define SD_NOTICE  ""
-#define SD_INFO    ""
-#define SD_DEBUG   ""
-#endif
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace std;
-
-bool shibd_shutdown = false;
-const char* shar_config = nullptr;
-const char* shar_schemadir = nullptr;
-const char* shar_prefix = nullptr;
-bool shar_checkonly = false;
-bool shar_version = false;
-static bool unlink_socket = false;
-const char* pidfile = nullptr;
-
-#ifdef WIN32
-
-//#include <CRTDBG.H>
-
-#define nNoMansLandSize 4
-typedef struct _CrtMemBlockHeader
-{
-        struct _CrtMemBlockHeader * pBlockHeaderNext;
-        struct _CrtMemBlockHeader * pBlockHeaderPrev;
-        char *                      szFileName;
-        int                         nLine;
-        size_t                      nDataSize;
-        int                         nBlockUse;
-        long                        lRequest;
-        unsigned char               gap[nNoMansLandSize];
-        /* followed by:
-         *  unsigned char           data[nDataSize];
-         *  unsigned char           anotherGap[nNoMansLandSize];
-         */
-} _CrtMemBlockHeader;
-
-/*
-int MyAllocHook(int nAllocType, void *pvData,
-      size_t nSize, int nBlockUse, long lRequest,
-      const unsigned char * szFileName, int nLine)
-{
-    if ( nBlockUse == _CRT_BLOCK )
-      return( TRUE );
-    if (nAllocType == _HOOK_FREE) {
-        _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);
-        if (ptr->nDataSize == 8192)
-            fprintf(stderr,"free  request %u size %u\n", ptr->lRequest, ptr->nDataSize);
-    }
-    else if (nAllocType == _HOOK_ALLOC && nSize == 8192)
-        fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);
-    return (TRUE);
-}
-*/
-
-int real_main(int preinit)
-{
-    if (shar_version) {
-        if (preinit)
-            fprintf(stdout, PACKAGE_STRING"\n");
-        return 0;
-    }
-
-    SPConfig& conf = SPConfig::getConfig();
-    if (preinit) {
-        // Initialize the SP library.
-        conf.setFeatures(
-            SPConfig::Listener |
-            SPConfig::Caching |
-            SPConfig::Metadata |
-            SPConfig::Trust |
-            SPConfig::Credentials |
-            SPConfig::AttributeResolution |
-            SPConfig::Handlers |
-            SPConfig::OutOfProcess |
-            (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
-            );
-        if (!conf.init(shar_schemadir, shar_prefix)) {
-            fprintf(stderr, "configuration is invalid, see console or log for specific problems\n");
-            return -1;
-        }
-
-        if (!conf.instantiate(shar_config)) {
-            fprintf(stderr, "configuration is invalid, check console or log for specific problems\n");
-            conf.term();
-            return -2;
-        }
-
-        // If just a test run, bail.
-        if (shar_checkonly) {
-            fprintf(stdout, "overall configuration is loadable, check console or log for non-fatal problems\n");
-            return 0;
-        }
-    }
-    else {
-
-        //_CrtSetAllocHook(MyAllocHook);
-
-        if (!shar_checkonly) {
-            // Run the listener.
-            ListenerService* listener = conf.getServiceProvider()->getListenerService();
-            if (!listener->init(unlink_socket)) {
-                fprintf(stderr, "listener failed to initialize\n");
-                conf.term();
-                return -3;
-            }
-            else if (!listener->run(&shibd_shutdown)) {
-                fprintf(stderr, "listener failed during service\n");
-                listener->term();
-                conf.term();
-                return -3;
-            }
-            listener->term();
-        }
-
-        conf.term();
-    }
-    return 0;
-}
-
-#else
-
-int daemon_wait = 3;
-bool shibd_running = false;
-bool daemonize = true;
-const char* runasuser = nullptr;
-const char* runasgroup = nullptr;
-
-static void term_handler(int arg)
-{
-    shibd_shutdown = true;
-}
-
-static void run_handler(int arg)
-{
-    shibd_running = true;
-}
-
-static void child_handler(int arg)
-{
-    // Terminate the parent's wait/sleep if the newly born daemon dies early.
-}
-
-static int setup_signals(void)
-{
-    struct sigaction sa;
-    memset(&sa, 0, sizeof (sa));
-    sa.sa_handler = SIG_IGN;
-    sa.sa_flags = SA_RESTART;
-
-    if (sigaction(SIGPIPE, &sa, nullptr) < 0) {
-        return -1;
-    }
-
-    memset(&sa, 0, sizeof (sa));
-    sa.sa_handler = term_handler;
-    sa.sa_flags = SA_RESTART;
-
-    if (sigaction(SIGHUP, &sa, nullptr) < 0) {
-        return -1;
-    }
-    if (sigaction(SIGINT, &sa, nullptr) < 0) {
-        return -1;
-    }
-    if (sigaction(SIGQUIT, &sa, nullptr) < 0) {
-        return -1;
-    }
-    if (sigaction(SIGTERM, &sa, nullptr) < 0) {
-        return -1;
-    }
-
-    if (daemonize) {
-        memset(&sa, 0, sizeof (sa));
-        sa.sa_handler = run_handler;
-
-        if (sigaction(SIGUSR1, &sa, nullptr) < 0) {
-            return -1;
-        }
-
-        memset(&sa, 0, sizeof (sa));
-        sa.sa_handler = child_handler;
-
-        if (sigaction(SIGCHLD, &sa, nullptr) < 0) {
-            return -1;
-        }
-    }
-
-    return 0;
-}
-
-static void usage(char* whoami)
-{
-    fprintf(stderr, "usage: %s [-dcxtfFpwugvh]\n", whoami);
-    fprintf(stderr, "  -d\tinstallation prefix to use\n");
-    fprintf(stderr, "  -c\tconfig file to use\n");
-    fprintf(stderr, "  -x\tXML schema catalogs to use\n");
-    fprintf(stderr, "  -t\ttest configuration file for problems\n");
-    fprintf(stderr, "  -f\tforce removal of listener socket\n");
-    fprintf(stderr, "  -F\tstay in the foreground\n");
-    fprintf(stderr, "  -p\tpid file to use\n");
-    fprintf(stderr, "  -w\tseconds to wait for successful daemonization\n");
-    fprintf(stderr, "  -u\tuser to run under\n");
-    fprintf(stderr, "  -g\tgroup to run under\n");
-    fprintf(stderr, "  -v\tprint software version\n");
-    fprintf(stderr, "  -h\tprint this help message\n");
-    exit(1);
-}
-
-static int parse_args(int argc, char* argv[])
-{
-    int opt;
-
-    while ((opt = getopt(argc, argv, "d:c:x:p:w:u:g:fFtvh")) > 0) {
-        switch (opt) {
-            case 'd':
-                shar_prefix=optarg;
-                break;
-            case 'c':
-                shar_config=optarg;
-                break;
-            case 'x':
-                shar_schemadir=optarg;
-                break;
-            case 'f':
-                unlink_socket = true;
-                break;
-            case 'F':
-                daemonize = false;
-                break;
-            case 't':
-                shar_checkonly=true;
-                daemonize=false;
-                break;
-            case 'v':
-                shar_version=true;
-                break;
-            case 'p':
-                pidfile=optarg;
-                break;
-            case 'w':
-                if (optarg)
-                    daemon_wait = atoi(optarg);
-                if (daemon_wait <= 0)
-                    daemon_wait = 3;
-                break;
-            case 'u':
-                if (optarg)
-                    runasuser = optarg;
-                break;
-            case 'g':
-                if (optarg)
-                    runasgroup = optarg;
-                break;
-            default:
-                return -1;
-        }
-    }
-    return 0;
-}
-
-int main(int argc, char *argv[])
-{
-    if (parse_args(argc, argv) != 0)
-        usage(argv[0]);
-    else if (shar_version) {
-        fprintf(stdout, PACKAGE_STRING"\n");
-        return 0;
-    }
-
-    if (setup_signals() != 0)
-        return -1;
-
-    if (runasgroup) {
-#ifdef HAVE_GETGRNAM
-        struct group* grp = getgrnam(runasgroup);
-        if (!grp) {
-            fprintf(stderr, "getgrnam failed, check -g option\n");
-            return -1;
-        }
-        if (setgid(grp->gr_gid) != 0) {
-            fprintf(stderr, "setgid failed, check -g option\n");
-            return -1;
-        }
-#else
-        fprintf(stderr, "-g not supported on this platform");
-        return -1;
-#endif
-    }
-
-    if (runasuser) {
-#ifdef HAVE_GETPWNAM
-        struct passwd* pwd = getpwnam(runasuser);
-        if (!pwd) {
-            fprintf(stderr, "getpwnam failed, check -u option\n");
-            return -1;
-        }
-#ifdef HAVE_INITGROUPS
-        // w/out initgroups/setgroups process retains supplementary groups
-        if (initgroups(pwd->pw_name, pwd->pw_gid) != 0) {
-            fprintf(stderr, "initgroups failed, check -u option\n");
-            return -1;
-        }
-#endif
-        if (setuid(pwd->pw_uid) != 0) {
-            fprintf(stderr, "setuid failed, check -u option\n");
-            return -1;
-        }
-#else
-        fprintf(stderr, "-u not supported on this platform");
-        return -1;
-#endif
-    }
-
-    // initialize the shib-target library
-    SPConfig& conf=SPConfig::getConfig();
-    conf.setFeatures(
-        SPConfig::Listener |
-        SPConfig::Caching |
-        SPConfig::Metadata |
-        SPConfig::Trust |
-        SPConfig::Credentials |
-        SPConfig::AttributeResolution |
-        SPConfig::Handlers |
-        SPConfig::OutOfProcess |
-        (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)
-        );
-    if (!conf.init(shar_schemadir, shar_prefix)) {
-        fprintf(stderr, SD_ERR "configuration is invalid, check console or log for specific problems\n");
-        return -1;
-    }
-
-    if (daemonize) {
-        // We must fork() early, while we're single threaded.
-        // StorageService cleanup thread is about to start.
-        switch (fork()) {
-            case 0:
-                break;
-            case -1:
-                perror("forking");
-                exit(EXIT_FAILURE);
-            default:
-                sleep(daemon_wait);
-                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);
-        }
-    }
-
-    if (!conf.instantiate(shar_config)) {
-        fprintf(stderr, SD_ERR "configuration is invalid, check console or log for specific problems\n");
-        conf.term();
-        return -2;
-    }
-
-    if (shar_checkonly)
-        fprintf(stderr, "overall configuration is loadable, check console or log for non-fatal problems\n");
-    else {
-        // Init the listener.
-        ListenerService* listener = conf.getServiceProvider()->getListenerService();
-        if (!listener->init(unlink_socket)) {
-            fprintf(stderr, SD_ERR "listener failed to initialize\n");
-            conf.term();
-            return -3;
-        }
-
-        if (daemonize) {
-            if (setsid() == -1) {
-                perror("setsid");
-                exit(EXIT_FAILURE);
-            }
-            if (chdir("/") == -1) {
-                perror("chdir to root");
-                exit(EXIT_FAILURE);
-            }
-
-            if (pidfile) {
-                FILE* pidf = fopen(pidfile, "w");
-                if (pidf) {
-                    fprintf(pidf, "%d\n", getpid());
-                    fclose(pidf);
-                }
-                else {
-                    perror(pidfile);
-                }
-            }
-
-            freopen("/dev/null", "r", stdin);
-            freopen("/dev/null", "w", stdout);
-            freopen("/dev/null", "w", stderr);
-
-            // Signal our parent that we are A-OK.
-            kill(getppid(), SIGUSR1);
-        }
-
-        // Run the listener.
-#ifdef HAVE_SD_NOTIFY
-        sd_notify(0, "READY=1");
-#endif
-        if (!listener->run(&shibd_shutdown)) {
-            fprintf(stderr, SD_ERR "listener failure during service\n");
-            listener->term();
-            conf.term();
-            if (daemonize && pidfile)
-                unlink(pidfile);
-            return -3;
-        }
-        listener->term();
-    }
-#ifdef HAVE_SD_NOTIFY
-    sd_notify(0, "STOPPING=1");
-#endif
-    conf.term();
-    if (daemonize && pidfile)
-        unlink(pidfile);
-    return 0;
-}
-
-#endif
diff --git a/shibd/shibd.rc b/shibd/shibd.rc
deleted file mode 100644
index 32650888..00000000
--- a/shibd/shibd.rc
+++ /dev/null
@@ -1,101 +0,0 @@
-//Microsoft Developer Studio generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include "afxres.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifndef _MAC
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION RC_FILE_VERSION ,0
- PRODUCTVERSION RC_PRODUCT_VERSION ,0
- FILEFLAGSMASK 0x3fL
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x40004L
- FILETYPE 0x1L
- FILESUBTYPE 0x0L
-BEGIN
-    BLOCK "StringFileInfo"
-    BEGIN
-        BLOCK "040904b0"
-        BEGIN
-#include "..\util\resourceCommon.rci"
-            VALUE "FileDescription", "Shibboleth Daemon Service\0"
-            VALUE "InternalName", "shibd\0"
-            VALUE "OriginalFilename", "shibd.exe\0"
-        END
-    END
-    BLOCK "VarFileInfo"
-    BEGIN
-        VALUE "Translation", 0x409, 1200
-    END
-END
-
-#endif    // !_MAC
-
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "resource.h\0"
-END
-
-2 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "#include ""afxres.h""\r\n"
-    "\0"
-END
-
-3 TEXTINCLUDE DISCARDABLE 
-BEGIN
-    "\r\n"
-    "\0"
-END
-
-#endif    // APSTUDIO_INVOKED
-
-#endif    // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif    // not APSTUDIO_INVOKED
-
diff --git a/shibd/shibd_win32.cpp b/shibd/shibd_win32.cpp
deleted file mode 100644
index 4d88a570..00000000
--- a/shibd/shibd_win32.cpp
+++ /dev/null
@@ -1,550 +0,0 @@
-/**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
- *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
- * either express or implied. See the License for the specific
- * language governing permissions and limitations under the License.
- */
-
-/*
- * shar_win32.cpp -- the SHAR "main" code on Win32
- */
-
-#include "config_win32.h"
-
-#define _CRT_NONSTDC_NO_DEPRECATE 1
-#define _CRT_SECURE_NO_DEPRECATE 1
-
-#include <shibsp/base.h>
-#include <xmltooling/logging.h>
-
-#include <string>
-#include <windows.h>
-
-using namespace std;
-
-using xmltooling::logging::Priority;
-using xmltooling::logging::Category;
-
-extern bool shibd_shutdown;                    // signals shutdown to Unix side
-extern const char* shar_schemadir;
-extern const char* shar_config;
-extern const char* shar_prefix;
-extern bool shar_checkonly;
-extern bool shar_version;
-
-// internal variables
-SERVICE_STATUS          ssStatus;       // current status of the service
-SERVICE_STATUS_HANDLE   sshStatusHandle;
-DWORD                   dwErr = 0;
-BOOL                    bConsole = FALSE;
-char                    szErr[256];
-LPCSTR                  lpszInstall = nullptr;
-LPCSTR                  lpszRemove = nullptr;
-LPCSTR                  lpszStdout = nullptr;
-LPCSTR                  lpszStderr = nullptr;
-
-// internal function prototypes
-VOID WINAPI service_ctrl(DWORD dwCtrlCode);
-VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);
-VOID CmdInstallService(LPCSTR);
-VOID CmdRemoveService(LPCSTR);
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );
-
-BOOL LogEvent(
-    WORD wType,
-    Priority::PriorityLevel priority,
-    DWORD dwEventID,
-    LPCTSTR message);
-
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
-VOID ServiceStop();
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
-
-BOOL WINAPI BreakHandler(DWORD dwCtrlType)
-{
-   switch(dwCtrlType)
-    {
-        case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate
-        case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in console mode
-            ServiceStop();
-            return TRUE;
-    }
-    return FALSE;
-}
-
-
-int real_main(int);  // The revised two-phase main() in shibd.cpp
-
-int main(int argc, char *argv[])
-{
-    int i=1;
-    while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))
-    {
-        if (_stricmp("install", argv[i]+1) == 0)
-        {
-            if (argc > ++i)
-                lpszInstall = argv[i++];
-        }
-        else if (_stricmp("remove", argv[i]+1) == 0)
-        {
-            if (argc > ++i)
-                lpszRemove = argv[i++];
-        }
-        else if (_stricmp("stdout", argv[i]+1) == 0)
-        {
-            if (argc > ++i) {
-                lpszStdout = argv[i++];
-                freopen(lpszStdout, "a+", stdout);
-            }
-        }
-        else if (_stricmp("stderr", argv[i]+1) == 0)
-        {
-            if (argc > ++i) {
-                lpszStderr = argv[i++];
-                freopen(lpszStderr, "a+", stderr);
-            }
-        }
-        else if (_stricmp( "console", argv[i]+1) == 0)
-        {
-            i++;
-            bConsole = TRUE;
-        }
-        else if (_stricmp( "check", argv[i]+1) == 0)
-        {
-            i++;
-            bConsole = TRUE;
-            shar_checkonly = true;
-        }
-        else if (_stricmp( "version", argv[i]+1) == 0)
-        {
-            i++;
-            bConsole = TRUE;
-            shar_version = true;
-        }
-        else if (_stricmp( "config", argv[i]+1) == 0)
-        {
-            if (argc > ++i)
-                shar_config = argv[i++];
-        }
-        else if (_stricmp( "prefix", argv[i]+1) == 0)
-        {
-            if (argc > ++i)
-                shar_prefix = argv[i++];
-        }
-        else if (_stricmp( "catalogs", argv[i]+1) == 0)
-        {
-            if (argc > ++i)
-                shar_schemadir = argv[i++];
-        }
-        else
-        {
-            goto dispatch;
-        }
-    }
-    
-    if (bConsole)
-    {
-        // Install break handler, then run the C routine twice, once to setup, once to start running.
-        SetConsoleCtrlHandler(&BreakHandler,TRUE);
-        if ((i=real_main(1))!=0)
-        {
-            Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("daemon startup failed, check log for details");
-            return i;
-        }
-        return real_main(0);
-    }
-    else if (lpszInstall)
-    {
-        CmdInstallService(lpszInstall);
-        return 0;
-    }
-    else if (lpszRemove)
-    {
-        CmdRemoveService(lpszRemove);
-        return 0;
-    }
-    
-
-    // if it doesn't match any of the above parameters
-    // the service control manager may be starting the service
-    // so we must call StartServiceCtrlDispatcher
-    dispatch:
-        // this is just to be friendly
-        printf("%s -install <name>   to install the named service\n", argv[0]);
-        printf("%s -remove <name>    to remove the named service\n", argv[0]);
-        printf("%s -console          to run as a console app for debugging\n", argv[0]);
-        printf("%s -check            to run as a console app and check configuration\n", argv[0]);
-        printf("%s -version          to run as a console app and print the version\n", argv[0]);
-        printf("\t-stdout <path> to redirect stdout stream\n");
-        printf("\t-stderr <path> to redirect stderr stream\n");
-        printf("\t-prefix <dir> to specify the installation directory\n");
-        printf("\t-config <file> to specify the config file to use\n");
-        printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");
-        printf("\nService starting.\nThis may take several seconds. Please wait.\n" );
-
-    static char svcname[] = "SHIBD";
-
-    SERVICE_TABLE_ENTRY dispatchTable[] =
-    {
-        { svcname, (LPSERVICE_MAIN_FUNCTION)service_main },
-        { nullptr, nullptr }
-    };
-
-    if (!StartServiceCtrlDispatcher(dispatchTable))
-        Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("StartServiceCtrlDispatcher failed");
-    return 0;
-}
-
-//
-//  FUNCTION: ServiceStart
-//
-//  PURPOSE: Actual code of the service
-//          that does the work.
-//
-VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)
-{
-
-    if (real_main(1)!=0)
-    {
-        Category::getInstance(SHIBSP_LOGCAT ".shibd").fatal("daemon startup failed, check log for details");
-        return;
-    }
-
-    Category::getInstance(SHIBSP_LOGCAT ".shibd").info("daemon service startup complete");
-
-    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
-        return;
-
-    real_main(0);
-}
-
-
-//
-//  FUNCTION: ServiceStop
-//
-//   PURPOSE: Stops the service
-//
-VOID ServiceStop()
-{
-    if (!bConsole)
-        Category::getInstance(SHIBSP_LOGCAT ".shibd").info("daemon service stopping...");
-    shibd_shutdown=true;
-}
-
-
-void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)
-{
-
-    // register our service control handler:
-    sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
-    if (!sshStatusHandle)
-        goto cleanup;
-
-    // SERVICE_STATUS members that don't change in example
-    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
-    ssStatus.dwServiceSpecificExitCode = 0;
-
-
-    // report the status to the service control manager.
-    if (!ReportStatusToSCMgr(
-        SERVICE_START_PENDING, // service state
-        NO_ERROR,              // exit code
-        3000))                 // wait hint
-        goto cleanup;
-
-
-    ServiceStart(dwArgc, lpszArgv);
-
-cleanup:
-
-    // try to report the stopped status to the service control manager.
-    //
-    if (sshStatusHandle)
-        (VOID)ReportStatusToSCMgr(
-                            SERVICE_STOPPED,
-                            dwErr,
-                            0);
-
-    return;
-}
-
-
-//
-//  FUNCTION: service_ctrl
-//
-//  PURPOSE: This function is called by the SCM whenever
-//           ControlService() is called on this service.
-//
-//  PARAMETERS:
-//    dwCtrlCode - type of control requested
-//
-//  RETURN VALUE:
-//    none
-//
-VOID WINAPI service_ctrl(DWORD dwCtrlCode)
-{
-    // Handle the requested control code.
-    //
-    switch(dwCtrlCode)
-    {
-        // Stop the service.
-        //
-        case SERVICE_CONTROL_STOP:
-            ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
-            ServiceStop();
-            break;
-
-        // Update the service status.
-        //
-        case SERVICE_CONTROL_INTERROGATE:
-            break;
-
-        // invalid control code
-        //
-        default:
-            break;
-
-    }
-
-    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
-}
-
-
-//
-//  FUNCTION: ReportStatusToSCMgr()
-//
-//  PURPOSE: Sets the current status of the service and
-//           reports it to the Service Control Manager
-//
-//  PARAMETERS:
-//    dwCurrentState - the state of the service
-//    dwWin32ExitCode - error code to report
-//    dwWaitHint - worst case estimate to next checkpoint
-//
-//  RETURN VALUE:
-//    TRUE  - success
-//    FALSE - failure
-//
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
-                         DWORD dwWin32ExitCode,
-                         DWORD dwWaitHint)
-{
-    static DWORD dwCheckPoint = 1;
-    BOOL fResult = TRUE;
-
-
-    if (!bConsole) // when console we don't report to the SCM
-    {
-        if (dwCurrentState == SERVICE_START_PENDING)
-            ssStatus.dwControlsAccepted = 0;
-        else
-            ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
-
-        ssStatus.dwCurrentState = dwCurrentState;
-        ssStatus.dwWin32ExitCode = dwWin32ExitCode;
-        ssStatus.dwWaitHint = dwWaitHint;
-
-        if ( ( dwCurrentState == SERVICE_RUNNING ) ||
-             ( dwCurrentState == SERVICE_STOPPED ) )
-            ssStatus.dwCheckPoint = 0;
-        else
-            ssStatus.dwCheckPoint = dwCheckPoint++;
-
-
-        // Report the status of the service to the service control manager.
-        //
-        if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))
-            Category::getInstance(SHIBSP_LOGCAT ".shibd").error("SetServiceStatus failed");
-    }
-    return fResult;
-}
-
-
-///////////////////////////////////////////////////////////////////
-//
-//  The following code handles service installation and removal
-//
-//
-void CmdInstallService(LPCSTR name)
-{
-    SC_HANDLE   schService;
-    SC_HANDLE   schSCManager;
-
-    char szPath[256];
-
-    if ( GetModuleFileName( nullptr, szPath, 256 ) == 0 )
-    {
-        printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
-        return;
-    }
-    
-    string dispName = string("Shibboleth SP Daemon (") + name + ")";
-    string realName = string("shibd_") + name;
-    string cmd(szPath);
-    if (shar_prefix)
-        cmd = cmd + " -prefix " + shar_prefix;
-    if (shar_config)
-        cmd = cmd + " -config " + shar_config;
-    if (shar_schemadir)
-        cmd = cmd + " -schemadir " + shar_schemadir;
-    if (lpszStdout)
-        cmd = cmd + " -stdout " + lpszStdout;
-    if (lpszStderr)
-        cmd = cmd + " -stderr " + lpszStderr;
-
-    schSCManager = OpenSCManager(
-                        nullptr,                   // machine (nullptr == local)
-                        nullptr,                   // database (nullptr == default)
-                        SC_MANAGER_ALL_ACCESS   // access required
-                        );
-    
-    
-    if ( schSCManager )
-    {
-        schService = CreateService(
-            schSCManager,               // SCManager database
-            realName.c_str(),           // name of service
-            dispName.c_str(),           // name to display
-            SERVICE_ALL_ACCESS,         // desired access
-            SERVICE_WIN32_OWN_PROCESS,  // service type
-            SERVICE_AUTO_START,         // start type
-            SERVICE_ERROR_NORMAL,       // error control type
-            cmd.c_str(),                // service's command line
-            nullptr,                       // no load ordering group
-            nullptr,                       // no tag identifier
-            nullptr,                       // dependencies
-            nullptr,                       // LocalSystem account
-            nullptr);                      // no password
-
-        if ( schService )
-        {
-            printf("%s installed.\n", realName.c_str());
-            CloseServiceHandle(schService);
-        }
-        else
-        {
-            printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));
-        }
-
-        CloseServiceHandle(schSCManager);
-    }
-    else
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
-}
-
-void CmdRemoveService(LPCSTR name)
-{
-    SC_HANDLE   schService;
-    SC_HANDLE   schSCManager;
-    char        realName[512];
-
-    _snprintf(realName,sizeof(realName),"shibd_%s",name);
-
-    schSCManager = OpenSCManager(
-                        nullptr,                   // machine (nullptr == local)
-                        nullptr,                   // database (nullptr == default)
-                        SC_MANAGER_ALL_ACCESS   // access required
-                        );
-    if ( schSCManager )
-    {
-        schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);
-
-        if (schService)
-        {
-            // try to stop the service
-            if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
-            {
-                printf("Stopping shibd (%s).", name);
-                Sleep( 1000 );
-
-                while( QueryServiceStatus( schService, &ssStatus ) )
-                {
-                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
-                    {
-                        printf(".");
-                        Sleep( 1000 );
-                    }
-                    else
-                        break;
-                }
-
-                if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
-                    printf("\n%s stopped.\n", realName);
-                else
-                    printf("\n%s failed to stop.\n", realName);
-
-            }
-
-            // now remove the service
-            if( DeleteService(schService) )
-                printf("%s removed.\n", realName);
-            else
-                printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));
-
-
-            CloseServiceHandle(schService);
-        }
-        else
-            printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));
-
-        CloseServiceHandle(schSCManager);
-    }
-    else
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));
-}
-
-
-//
-//  FUNCTION: GetLastErrorText
-//
-//  PURPOSE: copies error message text to string
-//
-//  PARAMETERS:
-//    lpszBuf - destination buffer
-//    dwSize - size of buffer
-//
-//  RETURN VALUE:
-//    destination buffer
-//
-//  COMMENTS:
-//
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )
-{
-    DWORD dwRet;
-    LPSTR lpszTemp = nullptr;
-
-    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
-                           nullptr,
-                           GetLastError(),
-                           LANG_NEUTRAL,
-                           (LPSTR)&lpszTemp,
-                           0,
-                           nullptr );
-
-    // supplied buffer is not long enough
-    if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
-        lpszBuf[0] = '\0';
-    else
-    {
-        lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character
-        sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );
-    }
-
-    if ( lpszTemp )
-        LocalFree((HLOCAL) lpszTemp );
-
-    return lpszBuf;
-}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list