Imported Upstream version 2.3+dfsg
authorRuss Allbery <rra@debian.org>
Tue, 10 Nov 2009 22:59:40 +0000 (14:59 -0800)
committerRuss Allbery <rra@debian.org>
Tue, 10 Nov 2009 22:59:40 +0000 (14:59 -0800)
225 files changed:
Makefile.in
Portfile
adfs/Makefile.am
adfs/Makefile.in
adfs/adfs.cpp
adfs/adfs.rc
adfs/resource.h
apache/Makefile.in
apache/mod_apache.cpp
apache/mod_shib20.vcproj
apache/mod_shib22.vcproj
apache/mod_shib_13.rc
apache/mod_shib_20.rc
apache/mod_shib_22.rc
config.guess
config.h.in
config.sub
config_win32.h
configs/Makefile.am
configs/Makefile.in
configs/accessError.html
configs/apache.config.in
configs/apache2.config.in
configs/apache22.config.in
configs/globalLogout.html
configs/keygen.bat
configs/keygen.sh
configs/localLogout.html
configs/metadataError.html
configs/partialLogout.html [new file with mode: 0644]
configs/sessionError.html
configs/shibboleth2.xml
configs/shibd-debian.in
configs/shibd-redhat.in
configs/shibd-suse.in
configs/sslError.html
configure
configure.ac
doc/CREDITS.txt [changed mode: 0755->0644]
doc/Makefile.in
doc/README.txt
doc/RELEASE.txt
fastcgi/Makefile.am
fastcgi/Makefile.in
fastcgi/resource.h
fastcgi/shibauthorizer.cpp
fastcgi/shibauthorizer.rc
fastcgi/shibresponder.cpp
fastcgi/shibresponder.rc
isapi_shib/isapi_shib.cpp
isapi_shib/isapi_shib.cpp.mine [deleted file]
isapi_shib/isapi_shib.cpp.r3059 [deleted file]
isapi_shib/isapi_shib.cpp.r3097 [deleted file]
isapi_shib/isapi_shib.rc
ltmain.sh
memcache-store/Makefile.am
memcache-store/Makefile.in
memcache-store/memcache-store.cpp
memcache-store/memcache-store.rc
memcache-store/resource.h
nsapi_shib/Makefile.in
nsapi_shib/nsapi_shib.cpp
nsapi_shib/nsapi_shib.rc
odbc-store/Makefile.in
odbc-store/odbc-store.cpp
odbc-store/odbc-store.rc
odbc-store/resource.h
pkginfo
postinstall
schemas/Makefile.am
schemas/Makefile.in
schemas/shibboleth-2.0-afp.xsd
schemas/shibboleth-2.0-attribute-map.xsd
schemas/shibboleth-2.0-native-sp-config.xsd
selinux/Makefile.am
selinux/Makefile.in
shibboleth.spec
shibboleth.spec.in
shibd/Makefile.am
shibd/Makefile.in
shibd/shibd.cpp
shibd/shibd.rc
shibd/shibd_win32.cpp
shibsp/AbstractSPRequest.cpp
shibsp/AbstractSPRequest.h
shibsp/AccessControl.h
shibsp/Application.cpp
shibsp/Application.h
shibsp/Makefile.am
shibsp/Makefile.in
shibsp/RequestMapper.h
shibsp/SPConfig.cpp
shibsp/SPConfig.h
shibsp/SPRequest.h
shibsp/ServiceProvider.cpp
shibsp/ServiceProvider.h
shibsp/SessionCache.h
shibsp/SessionCacheEx.h
shibsp/TransactionLog.h
shibsp/attribute/Attribute.cpp
shibsp/attribute/Attribute.h
shibsp/attribute/AttributeDecoder.h
shibsp/attribute/DOMAttributeDecoder.cpp
shibsp/attribute/ExtensibleAttribute.cpp
shibsp/attribute/ExtensibleAttribute.h
shibsp/attribute/KeyInfoAttributeDecoder.cpp
shibsp/attribute/NameIDAttribute.cpp [new file with mode: 0644]
shibsp/attribute/NameIDAttribute.h
shibsp/attribute/NameIDAttributeDecoder.cpp
shibsp/attribute/ScopedAttribute.cpp [new file with mode: 0644]
shibsp/attribute/ScopedAttribute.h
shibsp/attribute/ScopedAttributeDecoder.cpp
shibsp/attribute/SimpleAttribute.cpp [new file with mode: 0644]
shibsp/attribute/SimpleAttribute.h
shibsp/attribute/StringAttributeDecoder.cpp
shibsp/attribute/XMLAttribute.cpp [new file with mode: 0644]
shibsp/attribute/XMLAttribute.h
shibsp/attribute/XMLAttributeDecoder.cpp
shibsp/attribute/filtering/AttributeFilter.h
shibsp/attribute/filtering/BasicFilteringContext.h
shibsp/attribute/filtering/FilterPolicyContext.h
shibsp/attribute/filtering/FilteringContext.h
shibsp/attribute/filtering/MatchFunctor.h
shibsp/attribute/filtering/impl/AndMatchFunctor.cpp
shibsp/attribute/filtering/impl/AnyMatchFunctor.cpp
shibsp/attribute/filtering/impl/AttributeFilter.cpp
shibsp/attribute/filtering/impl/AttributeIssuerInEntityGroupFunctor.cpp
shibsp/attribute/filtering/impl/AttributeIssuerRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeIssuerStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeRequesterInEntityGroupFunctor.cpp
shibsp/attribute/filtering/impl/AttributeRequesterRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeRequesterStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeMatchesShibMDScopeFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeScopeStringFunctor.cpp
shibsp/attribute/filtering/impl/AttributeValueRegexFunctor.cpp
shibsp/attribute/filtering/impl/AttributeValueStringFunctor.cpp
shibsp/attribute/filtering/impl/AuthenticationMethodRegexFunctor.cpp
shibsp/attribute/filtering/impl/AuthenticationMethodStringFunctor.cpp
shibsp/attribute/filtering/impl/BasicFilteringContext.cpp [new file with mode: 0644]
shibsp/attribute/filtering/impl/MatchFunctor.cpp
shibsp/attribute/filtering/impl/NotMatchFunctor.cpp
shibsp/attribute/filtering/impl/NumberOfAttributeValuesFunctor.cpp
shibsp/attribute/filtering/impl/OrMatchFunctor.cpp
shibsp/attribute/filtering/impl/XMLAttributeFilter.cpp
shibsp/attribute/resolver/AttributeExtractor.h
shibsp/attribute/resolver/AttributeResolver.h
shibsp/attribute/resolver/ResolutionContext.h
shibsp/attribute/resolver/impl/ChainingAttributeExtractor.cpp
shibsp/attribute/resolver/impl/ChainingAttributeResolver.cpp
shibsp/attribute/resolver/impl/DelegationAttributeExtractor.cpp
shibsp/attribute/resolver/impl/KeyDescriptorAttributeExtractor.cpp
shibsp/attribute/resolver/impl/QueryAttributeResolver.cpp
shibsp/attribute/resolver/impl/SimpleAggregationAttributeResolver.cpp
shibsp/attribute/resolver/impl/XMLAttributeExtractor.cpp
shibsp/binding/ArtifactResolver.h
shibsp/binding/SOAPClient.h
shibsp/binding/impl/ArtifactResolver.cpp
shibsp/binding/impl/SOAPClient.cpp
shibsp/exceptions.h
shibsp/handler/AbstractHandler.h
shibsp/handler/AssertionConsumerService.h
shibsp/handler/Handler.h
shibsp/handler/LogoutHandler.h
shibsp/handler/RemotedHandler.h
shibsp/handler/SessionInitiator.h
shibsp/handler/impl/AbstractHandler.cpp
shibsp/handler/impl/AssertionConsumerService.cpp
shibsp/handler/impl/AssertionLookup.cpp
shibsp/handler/impl/LocalLogoutInitiator.cpp
shibsp/handler/impl/LogoutHandler.cpp
shibsp/handler/impl/MetadataGenerator.cpp
shibsp/handler/impl/RemotedHandler.cpp
shibsp/handler/impl/SAML1Consumer.cpp
shibsp/handler/impl/SAML2ArtifactResolution.cpp
shibsp/handler/impl/SAML2Consumer.cpp
shibsp/handler/impl/SAML2Logout.cpp
shibsp/handler/impl/SAML2LogoutInitiator.cpp
shibsp/handler/impl/SAML2NameIDMgmt.cpp
shibsp/handler/impl/SAML2SessionInitiator.cpp
shibsp/handler/impl/SAMLDSSessionInitiator.cpp
shibsp/handler/impl/SessionInitiator.cpp
shibsp/handler/impl/Shib1SessionInitiator.cpp
shibsp/handler/impl/StatusHandler.cpp
shibsp/handler/impl/WAYFSessionInitiator.cpp
shibsp/impl/ChainingAccessControl.cpp
shibsp/impl/StorageServiceSessionCache.cpp
shibsp/impl/XMLAccessControl.cpp
shibsp/impl/XMLRequestMapper.cpp
shibsp/impl/XMLServiceProvider.cpp
shibsp/lite/CommonDomainCookie.cpp
shibsp/lite/CommonDomainCookie.h
shibsp/lite/SAMLConstants.h
shibsp/metadata/DynamicMetadataProvider.cpp
shibsp/metadata/MetadataExt.h
shibsp/metadata/MetadataExtImpl.cpp
shibsp/metadata/MetadataExtSchemaValidators.cpp
shibsp/metadata/MetadataProviderCriteria.cpp [new file with mode: 0644]
shibsp/metadata/MetadataProviderCriteria.h
shibsp/paths.h
shibsp/paths.h.in
shibsp/remoting/ListenerService.h
shibsp/remoting/ddf.h
shibsp/remoting/impl/ListenerService.cpp
shibsp/remoting/impl/ddf.cpp
shibsp/resource.h
shibsp/security/PKIXTrustEngine.cpp
shibsp/security/SecurityPolicy.cpp
shibsp/security/SecurityPolicy.h
shibsp/shibsp-lite.vcproj
shibsp/shibsp.rc
shibsp/shibsp.vcproj
shibsp/util/CGIParser.cpp
shibsp/util/CGIParser.h
shibsp/util/DOMPropertySet.cpp
shibsp/util/DOMPropertySet.h
shibsp/util/PropertySet.h
shibsp/util/SPConstants.cpp
shibsp/util/SPConstants.h
shibsp/util/TemplateParameters.cpp
shibsp/util/TemplateParameters.h
shibsp/version.h
util/Makefile.in
util/mdquery.cpp
util/resolvertest.cpp

index b296c95..5763f79 100644 (file)
@@ -110,6 +110,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 50c87a1..6a37645 100644 (file)
--- a/Portfile
+++ b/Portfile
@@ -1,7 +1,7 @@
 PortSystem 1.0
 
 name               shibboleth
-version            2.2.1
+version            2.3
 categories         security www shibboleth
 maintainers        scantor snc
 description        Shibboleth Native Service Provider
index 82913b5..196504b 100644 (file)
@@ -1,25 +1,25 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = adfs.la adfs-lite.la\r
-\r
-adfs_la_LIBADD = \\r
-       $(top_builddir)/shibsp/libshibsp.la\r
-\r
-adfs_la_SOURCES = \\r
-       adfs.cpp\r
-\r
-adfs_lite_la_LIBADD = \\r
-       $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-adfs_lite_la_SOURCES = \\r
-       adfs.cpp\r
-\r
-adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)\r
-adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE\r
-\r
-install-exec-hook:\r
-       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = adfs.la adfs-lite.la
+
+adfs_la_LIBADD = \
+       $(top_builddir)/shibsp/libshibsp.la
+
+adfs_la_SOURCES = \
+       adfs.cpp
+
+adfs_lite_la_LIBADD = \
+       $(top_builddir)/shibsp/libshibsp-lite.la
+
+adfs_lite_la_SOURCES = \
+       adfs.cpp
+
+adfs_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+adfs_lite_la_LDFLAGS = -module -avoid-version $(LITE_LIBS)
+adfs_lite_la_CPPFLAGS = -DSHIBSP_LITE
+
+install-exec-hook:
+       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = adfs.vcproj adfs-lite.vcproj resource.h adfs.rc
index 602bba9..85861e1 100644 (file)
@@ -84,6 +84,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index bc84c2f..41c78e6 100644 (file)
 # define ADFS_EXPORTS
 #endif
 
-#include <memory>
-
 #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/handler/AssertionConsumerService.h>
 #include <shibsp/handler/LogoutHandler.h>
 #include <shibsp/handler/SessionInitiator.h>
 #include <xmltooling/logging.h>
+#include <xmltooling/util/DateTime.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/URLEncoder.h>
 #include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/XMLUniDefs.hpp>
+#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/saml1/profile/AssertionValidator.h>
 # include <saml/saml2/core/Assertions.h>
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/EndpointManager.h>
-# include <saml/saml2/profile/AssertionValidator.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
@@ -112,7 +114,7 @@ namespace {
     {
     public:
         ADFSSessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS")), m_appId(appId), m_binding(WSFED_NS) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.ADFS"), NULL, &m_remapper), m_appId(appId), m_binding(WSFED_NS) {
             // If Location isn't set, defer address registration until the setParent call.
             pair<bool,const char*> loc = getString("Location");
             if (loc.first) {
@@ -334,7 +336,7 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
         if (option) {
             ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
         }
 
         option = request.getParameter("target");
@@ -361,30 +363,36 @@ pair<bool,long> ADFSSessionInitiator::run(SPRequest& request, string& entityID,
             acClass = getString("authnContextClassRef");
     }
 
-    // Since we're not passing by index, we need to fully compute the return URL.
     if (!ACS) {
-        pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+        pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
         if (index.first) {
             ACS = app.getAssertionConsumerServiceByIndex(index.second);
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
+        }
+        if (!ACS) {
+            const vector<const Handler*>& endpoints = app.getAssertionConsumerServicesByBinding(m_binding.get());
+            if (endpoints.empty()) {
+                m_log.error("unable to locate a compatible ACS");
+                throw ConfigurationException("Unable to locate an ADFS-compatible ACS in the configuration.");
+            }
+            ACS = endpoints.front();
         }
-        if (!ACS)
-            ACS = app.getDefaultAssertionConsumerService();
     }
 
     // Validate the ACS for use with this protocol.
-    pair<bool,const XMLCh*> ACSbinding = ACS ? ACS->getXMLString("Binding") : pair<bool,const XMLCh*>(false,NULL);
+    pair<bool,const XMLCh*> ACSbinding = ACS->getXMLString("Binding");
     if (ACSbinding.first) {
         if (!XMLString::equals(ACSbinding.second, m_binding.get())) {
-            m_log.info("configured or requested ACS has non-ADFS binding");
-            return make_pair(false,0L);
+            m_log.error("configured or requested ACS has non-ADFS binding");
+            throw ConfigurationException("Configured or requested ACS has non-ADFS binding ($1).", params(1, ACSbinding.second));
         }
     }
 
+    // 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());
-    pair<bool,const char*> loc=ACS ? ACS->getString("Location") : pair<bool,const char*>(false,NULL);
+    pair<bool,const char*> loc=ACS->getString("Location");
     if (loc.first) ACSloc+=loc.second;
 
     if (isHandler) {
@@ -619,30 +627,29 @@ void ADFSConsumer::implementProtocol(
     // 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()) : NULL;
+    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.
+    // 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.");
 
-    time_t now = time(NULL);
-
-    const PropertySet* sessionProps = application.getPropertySet("Sessions");
-    const EntityDescriptor* entity = policy.getIssuerMetadata() ? dynamic_cast<const EntityDescriptor*>(policy.getIssuerMetadata()->getParent()) : NULL;
-
     saml1::NameIdentifier* saml1name=NULL;
     saml2::NameID* saml2name=NULL;
     const XMLCh* authMethod=NULL;
     const XMLCh* authInstant=NULL;
-    time_t sessionExp = 0;
+    time_t now = time(NULL), sessionExp = 0;
+    const PropertySet* sessionProps = application.getPropertySet("Sessions");
 
     const saml1::Assertion* saml1token = dynamic_cast<const saml1::Assertion*>(token);
     if (saml1token) {
-        // Now do profile and core semantic validation to ensure we can use it for SSO.
-        saml1::AssertionValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now);
-        ssoValidator.validateAssertion(*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())
@@ -679,9 +686,7 @@ void ADFSConsumer::implementProtocol(
         if (!saml2token)
             throw FatalProfileException("Incoming message did not contain a recognized type of SAML assertion.");
 
-        // Now do profile and core semantic validation to ensure we can use it for SSO.
-        saml2::AssertionValidator ssoValidator(application.getRelyingParty(entity)->getXMLString("entityID").second, application.getAudiences(), now);
-        ssoValidator.validateAssertion(*saml2token);
+        // 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())
@@ -875,7 +880,7 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
     if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
         session->unlock();
         application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
-        return sendLogoutPage(application, httpRequest, httpResponse, true, "Partial logout failure.");
+        return sendLogoutPage(application, httpRequest, httpResponse, "partial");
     }
 
 #ifndef SHIBSP_LITE
@@ -903,7 +908,8 @@ pair<bool,long> ADFSLogoutInitiator::doRequest(
             ).getByBinding(m_binding.get());
         if (!ep) {
             throw MetadataException(
-                "Unable to locate ADFS single logout service for identity provider ($entityID).", namedparams(1, "entityID", session->getEntityID())
+                "Unable to locate ADFS single logout service for identity provider ($entityID).",
+                namedparams(1, "entityID", session->getEntityID())
                 );
         }
 
@@ -982,5 +988,5 @@ pair<bool,long> ADFSLogout::run(SPRequest& request, bool isHandler) const
 
     if (param)
         return make_pair(true, request.sendRedirect(param));
-    return sendLogoutPage(app, request, request, false, "Logout complete.");
+    return sendLogoutPage(app, request, request, "global");
 }
index 7db3d05..9e46d04 100644 (file)
@@ -54,8 +54,8 @@ END
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -73,7 +73,7 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth ADFSv1 Plugin\0"\r
-            VALUE "FileVersion", "2, 2, 1, 0\0"\r
+            VALUE "FileVersion", "2, 3, 0, 0\0"\r
 #ifdef SHIBSP_LITE\r
             VALUE "InternalName", "adfs-lite\0"\r
 #else\r
@@ -87,8 +87,8 @@ BEGIN
             VALUE "OriginalFilename", "adfs.so\0"\r
 #endif\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
-            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.3\0"\r
+            VALUE "ProductVersion", "2, 3, 0, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index 95f2c63..3ba1cce 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by adfs.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{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
index 8d3aece..f493949 100644 (file)
@@ -106,6 +106,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 661b448..efe531e 100644 (file)
@@ -69,6 +69,7 @@
 #include <apr_pools.h>
 #endif
 
+#include <set>
 #include <memory>
 #include <fstream>
 #include <sstream>
@@ -523,6 +524,7 @@ public:
       m_req->content_type = ap_psprintf(m_req->pool, type);
   }
   void setResponseHeader(const char* name, const char* value) {
+   HTTPResponse::setResponseHeader(name, value);
 #ifdef SHIB_DEFERRED_HEADERS
    if (!m_rc)
       // this happens on subrequests
@@ -552,6 +554,7 @@ public:
     return DONE;
   }
   long sendRedirect(const char* url) {
+    HTTPResponse::sendRedirect(url);
     ap_table_set(m_req->headers_out, "Location", url);
     return REDIRECT;
   }
index 91d85c5..f767d76 100644 (file)
@@ -52,7 +52,7 @@
                                Name="VCCLCompilerTool"
                                Optimization="2"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
+                               AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
                                StringPooling="true"
                                RuntimeLibrary="2"
@@ -80,7 +80,7 @@
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2\lib"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.0.63\Apache2\lib"
                                RandomizedBaseAddress="1"
                                DataExecutionPrevention="0"
                                TargetMachine="1"
                                Name="VCCLCompilerTool"
                                Optimization="2"
                                InlineFunctionExpansion="1"
-                               AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
+                               AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
                                PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS"
                                StringPooling="true"
                                RuntimeLibrary="2"
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="1"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2\lib"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2.0.63\Apache2\lib"
                                ProgramDatabaseFile=".\mod_shib20___Win32_Release/mod_shib_20.pdb"
                                RandomizedBaseAddress="1"
                                DataExecutionPrevention="0"
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
+                               AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
                                PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="3"
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2\lib"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.0.63\Apache2\lib"
                                GenerateDebugInformation="true"
                                RandomizedBaseAddress="1"
                                DataExecutionPrevention="0"
                        <Tool
                                Name="VCCLCompilerTool"
                                Optimization="0"
-                               AdditionalIncludeDirectories="..;\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
+                               AdditionalIncludeDirectories="..;\Apache2.0.63\Apache2\include;&quot;..\..\cpp-xmltooling&quot;"
                                PreprocessorDefinitions="_WINDOWS;WIN32;_DEBUG"
                                BasicRuntimeChecks="3"
                                RuntimeLibrary="3"
                                OutputFile="$(OutDir)\mod_shib_20.so"
                                LinkIncremental="2"
                                SuppressStartupBanner="true"
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2\lib"
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)&quot;;\Apache2.0.63\Apache2\lib"
                                GenerateDebugInformation="true"
                                RandomizedBaseAddress="1"
                                DataExecutionPrevention="0"
index c6e2fd6..e372cd5 100644 (file)
@@ -52,7 +52,7 @@
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories="..;\Apache2.2.14\include;&quot;..\..\cpp-xmltooling&quot;"\r
                                PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
                                StringPooling="true"\r
                                RuntimeLibrary="2"\r
@@ -79,7 +79,7 @@
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
                                LinkIncremental="1"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2\lib"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2.14\lib"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
                                TargetMachine="1"\r
                                Name="VCCLCompilerTool"\r
                                Optimization="2"\r
                                InlineFunctionExpansion="1"\r
-                               AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories="..;\httpd-2.2-x64\include;&quot;..\..\cpp-xmltooling&quot;"\r
                                PreprocessorDefinitions="NDEBUG;WIN32;_WINDOWS"\r
                                StringPooling="true"\r
                                RuntimeLibrary="2"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories="..;\Apache2.2.14\include;&quot;..\..\cpp-xmltooling&quot;"\r
                                PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
                                OutputFile="$(OutDir)\mod_shib_22.so"\r
                                LinkIncremental="2"\r
                                SuppressStartupBanner="true"\r
-                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2\lib"\r
+                               AdditionalLibraryDirectories="&quot;..\..\cpp-xmltooling\$(ConfigurationName)&quot;;\Apache2.2.14\lib"\r
                                GenerateDebugInformation="true"\r
                                RandomizedBaseAddress="1"\r
                                DataExecutionPrevention="0"\r
                        <Tool\r
                                Name="VCCLCompilerTool"\r
                                Optimization="0"\r
-                               AdditionalIncludeDirectories="..;\Apache2.2\include;&quot;..\..\cpp-xmltooling&quot;"\r
+                               AdditionalIncludeDirectories="..;\httpd-2.2-x64\include;&quot;..\..\cpp-xmltooling&quot;"\r
                                PreprocessorDefinitions="_DEBUG;WIN32;_WINDOWS"\r
                                MinimalRebuild="true"\r
                                BasicRuntimeChecks="3"\r
index 503cf30..1ef85b6 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 1.3 Module\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "mod_shib_13\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_13.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index d3e619e..79dd05e 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 2.0 Module\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "mod_shib_20\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_20.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 5f92326..24182bd 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Apache 2.2 Module\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "mod_shib_22\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "mod_shib_22.so\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 917bbc5..2fc3acc 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
-timestamp='2005-07-08'
+timestamp='2003-06-17'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -17,15 +17,13 @@ timestamp='2005-07-08'
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
-
 # Originally written by Per Bothner <per@bothner.com>.
 # Please send patches to <config-patches@gnu.org>.  Submit a context
 # diff and a properly formatted ChangeLog entry.
@@ -55,7 +53,7 @@ version="\
 GNU config.guess ($timestamp)
 
 Originally written by Per Bothner.
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -68,11 +66,11 @@ Try \`$me --help' for more information."
 while test $# -gt 0 ; do
   case $1 in
     --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
+       echo "$timestamp" ; exit ;;
     --version | -v )
-       echo "$version" ; exit ;;
+       echo "$version" ; exit ;;
     --help | --h* | -h )
-       echo "$usage"; exit ;;
+       echo "$usage"; exit ;;
     -- )     # Stop option processing
        shift; break ;;
     - )        # Use stdin as input.
@@ -125,7 +123,7 @@ case $CC_FOR_BUILD,$HOST_CC,$CC in
        ;;
  ,,*)   CC_FOR_BUILD=$CC ;;
  ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-esac ; set_cc_for_build= ;'
+esac ;'
 
 # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
 # (ghazi@noc.rutgers.edu 1994-08-24)
@@ -138,6 +136,13 @@ UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
 UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
 UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
 
+## for Red Hat Linux
+if test -f /etc/redhat-release ; then
+    VENDOR=redhat ;
+else
+    VENDOR= ;
+fi
+
 # Note: order is significant - the case branches are not exclusive.
 
 case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
@@ -198,29 +203,50 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        # contains redundant information, the shorter form:
        # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
        echo "${machine}-${os}${release}"
-       exit ;;
+       exit 0 ;;
+    amiga:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    arc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    hp300:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mac68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    macppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme68k:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvme88k:OpenBSD:*:*)
+       echo m88k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    mvmeppc:OpenBSD:*:*)
+       echo powerpc-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    pmax:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sgi:OpenBSD:*:*)
+       echo mipseb-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    sun3:OpenBSD:*:*)
+       echo m68k-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
+    wgrisc:OpenBSD:*:*)
+       echo mipsel-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     *:OpenBSD:*:*)
-       UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
-       echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
-       exit ;;
-    *:ekkoBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
-       exit ;;
-    macppc:MirBSD:*:*)
-       echo powerppc-unknown-mirbsd${UNAME_RELEASE}
-       exit ;;
-    *:MirBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
-       exit ;;
+       echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+       exit 0 ;;
     alpha:OSF1:*:*)
-       case $UNAME_RELEASE in
-       *4.0)
+       if test $UNAME_RELEASE = "V4.0"; then
                UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
-               ;;
-       *5.*)
-               UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
-               ;;
-       esac
+       fi
        # According to Compaq, /usr/sbin/psrinfo has been available on
        # OSF/1 and Tru64 systems produced since 1995.  I hope that
        # covers most systems running today.  This code pipes the CPU
@@ -258,49 +284,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
            "EV7.9 (21364A)")
                UNAME_MACHINE="alphaev79" ;;
        esac
-       # A Pn.n version is a patched version.
        # A Vn.n version is a released version.
        # A Tn.n version is a released field test version.
        # A Xn.n version is an unreleased experimental baselevel.
        # 1.2 uses "1.2" for uname -r.
-       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-       exit ;;
+       echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+       exit 0 ;;
+    Alpha*:OpenVMS:*:*)
+       echo alpha-hp-vms
+       exit 0 ;;
     Alpha\ *:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # Should we change UNAME_MACHINE based on the output of uname instead
        # of the specific Alpha model?
        echo alpha-pc-interix
-       exit ;;
+       exit ;;
     21064:Windows_NT:50:3)
        echo alpha-dec-winnt3.5
-       exit ;;
+       exit ;;
     Amiga*:UNIX_System_V:4.0:*)
        echo m68k-unknown-sysv4
-       exit ;;
+       exit 0;;
     *:[Aa]miga[Oo][Ss]:*:*)
        echo ${UNAME_MACHINE}-unknown-amigaos
-       exit ;;
+       exit ;;
     *:[Mm]orph[Oo][Ss]:*:*)
        echo ${UNAME_MACHINE}-unknown-morphos
-       exit ;;
+       exit ;;
     *:OS/390:*:*)
        echo i370-ibm-openedition
-       exit ;;
-    *:z/VM:*:*)
-       echo s390-ibm-zvmoe
-       exit ;;
-    *:OS400:*:*)
-        echo powerpc-ibm-os400
-       exit ;;
+       exit 0 ;;
     arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
        echo arm-acorn-riscix${UNAME_RELEASE}
-       exit ;;
-    arm:riscos:*:*|arm:RISCOS:*:*)
-       echo arm-unknown-riscos
-       exit ;;
+       exit 0;;
     SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
        echo hppa1.1-hitachi-hiuxmpp
-       exit ;;
+       exit 0;;
     Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
        # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
        if test "`(/bin/universe) 2>/dev/null`" = att ; then
@@ -308,32 +327,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        else
                echo pyramid-pyramid-bsd
        fi
-       exit ;;
+       exit ;;
     NILE*:*:*:dcosx)
        echo pyramid-pyramid-svr4
-       exit ;;
+       exit ;;
     DRS?6000:unix:4.0:6*)
        echo sparc-icl-nx6
-       exit ;;
-    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+       exit ;;
+    DRS?6000:UNIX_SV:4.2*:7*)
        case `/usr/bin/uname -p` in
-           sparc) echo sparc-icl-nx7; exit ;;
+           sparc) echo sparc-icl-nx7 && exit 0 ;;
        esac ;;
     sun4H:SunOS:5.*:*)
        echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
        echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     i86pc:SunOS:5.*:*)
        echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:6*:*)
        # According to config.sub, this is the proper way to canonicalize
        # SunOS6.  Hard to guess exactly what SunOS6 will be like, but
        # it's likely to be more like Solaris than SunOS4.
        echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     sun4*:SunOS:*:*)
        case "`/usr/bin/arch -k`" in
            Series*|S4*)
@@ -342,10 +361,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
        esac
        # Japanese Language versions have a version number like `4.1.3-JL'.
        echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
-       exit ;;
+       exit ;;
     sun3*:SunOS:*:*)
        echo m68k-sun-sunos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     sun*:*:4.2BSD:*)
        UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
        test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
@@ -357,10 +376,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
                echo sparc-sun-sunos${UNAME_RELEASE}
                ;;
        esac
-       exit ;;
+       exit ;;
     aushp:SunOS:*:*)
        echo sparc-auspex-sunos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     # The situation for MiNT is a little confusing.  The machine name
     # can be virtually everything (everything which is not
     # "atarist" or "atariste" at least should have a processor
@@ -371,40 +390,37 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
     # be no problem.
     atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
         echo m68k-atari-mint${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
        echo m68k-atari-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
         echo m68k-atari-mint${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
         echo m68k-milan-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
         echo m68k-hades-mint${UNAME_RELEASE}
-        exit ;;
+        exit ;;
     *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
         echo m68k-unknown-mint${UNAME_RELEASE}
-        exit ;;
-    m68k:machten:*:*)
-       echo m68k-apple-machten${UNAME_RELEASE}
-       exit ;;
+        exit 0 ;;
     powerpc:machten:*:*)
        echo powerpc-apple-machten${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     RISC*:Mach:*:*)
        echo mips-dec-mach_bsd4.3
-       exit ;;
+       exit ;;
     RISC*:ULTRIX:*:*)
        echo mips-dec-ultrix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     VAX*:ULTRIX*:*:*)
        echo vax-dec-ultrix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     2020:CLIX:*:* | 2430:CLIX:*:*)
        echo clipper-intergraph-clix${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     mips:*:*:UMIPS | mips:*:*:RISCos)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -428,33 +444,32 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
          exit (-1);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c &&
-         dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
-         SYSTEM_NAME=`$dummy $dummyarg` &&
-           { echo "$SYSTEM_NAME"; exit; }
+       $CC_FOR_BUILD -o $dummy $dummy.c \
+         && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+         && exit 0
        echo mips-mips-riscos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     Motorola:PowerMAX_OS:*:*)
        echo powerpc-motorola-powermax
-       exit ;;
+       exit ;;
     Motorola:*:4.3:PL8-*)
        echo powerpc-harris-powermax
-       exit ;;
+       exit ;;
     Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
        echo powerpc-harris-powermax
-       exit ;;
+       exit ;;
     Night_Hawk:Power_UNIX:*:*)
        echo powerpc-harris-powerunix
-       exit ;;
+       exit ;;
     m88k:CX/UX:7*:*)
        echo m88k-harris-cxux7
-       exit ;;
+       exit ;;
     m88k:*:4*:R4*)
        echo m88k-motorola-sysv4
-       exit ;;
+       exit ;;
     m88k:*:3*:R3*)
        echo m88k-motorola-sysv3
-       exit ;;
+       exit ;;
     AViiON:dgux:*:*)
         # DG/UX returns AViiON for all architectures
         UNAME_PROCESSOR=`/usr/bin/uname -p`
@@ -470,29 +485,29 @@ EOF
        else
            echo i586-dg-dgux${UNAME_RELEASE}
        fi
-       exit ;;
+       exit ;;
     M88*:DolphinOS:*:*)        # DolphinOS (SVR3)
        echo m88k-dolphin-sysv3
-       exit ;;
+       exit ;;
     M88*:*:R3*:*)
        # Delta 88k system running SVR3
        echo m88k-motorola-sysv3
-       exit ;;
+       exit ;;
     XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
        echo m88k-tektronix-sysv3
-       exit ;;
+       exit ;;
     Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
        echo m68k-tektronix-bsd
-       exit ;;
+       exit ;;
     *:IRIX*:*:*)
        echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
-       exit ;;
+       exit ;;
     ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-       echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
-       exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+       echo romp-ibm-aix      # uname -m gives an 8 hex-code CPU id
+       exit 0 ;;              # Note that: echo "'`uname -s`'" gives 'AIX '
     i*86:AIX:*:*)
        echo i386-ibm-aix
-       exit ;;
+       exit ;;
     ia64:AIX:*:*)
        if [ -x /usr/bin/oslevel ] ; then
                IBM_REV=`/usr/bin/oslevel`
@@ -500,7 +515,7 @@ EOF
                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
        fi
        echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
-       exit ;;
+       exit ;;
     *:AIX:2:3)
        if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
                eval $set_cc_for_build
@@ -515,18 +530,14 @@ EOF
                        exit(0);
                        }
 EOF
-               if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
-               then
-                       echo "$SYSTEM_NAME"
-               else
-                       echo rs6000-ibm-aix3.2.5
-               fi
+               $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
+               echo rs6000-ibm-aix3.2.5
        elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
                echo rs6000-ibm-aix3.2.4
        else
                echo rs6000-ibm-aix3.2
        fi
-       exit ;;
+       exit ;;
     *:AIX:*:[45])
        IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
        if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
@@ -540,28 +551,28 @@ EOF
                IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
        fi
        echo ${IBM_ARCH}-ibm-aix${IBM_REV}
-       exit ;;
+       exit ;;
     *:AIX:*:*)
        echo rs6000-ibm-aix
-       exit ;;
+       exit ;;
     ibmrt:4.4BSD:*|romp-ibm:BSD:*)
        echo romp-ibm-bsd4.4
-       exit ;;
+       exit ;;
     ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
        echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
-       exit ;;                             # report: romp-ibm BSD 4.3
+       exit 0 ;;                           # report: romp-ibm BSD 4.3
     *:BOSX:*:*)
        echo rs6000-bull-bosx
-       exit ;;
+       exit ;;
     DPX/2?00:B.O.S.:*:*)
        echo m68k-bull-sysv3
-       exit ;;
+       exit ;;
     9000/[34]??:4.3bsd:1.*:*)
        echo m68k-hp-bsd
-       exit ;;
+       exit ;;
     hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
        echo m68k-hp-bsd4.4
-       exit ;;
+       exit ;;
     9000/[34678]??:HP-UX:*:*)
        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        case "${UNAME_MACHINE}" in
@@ -623,19 +634,9 @@ EOF
        esac
        if [ ${HP_ARCH} = "hppa2.0w" ]
        then
-           eval $set_cc_for_build
-
-           # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
-           # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
-           # generating 64-bit code.  GNU and HP use different nomenclature:
-           #
-           # $ CC_FOR_BUILD=cc ./config.guess
-           # => hppa2.0w-hp-hpux11.23
-           # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
-           # => hppa64-hp-hpux11.23
-
-           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
-               grep __LP64__ >/dev/null
+           # avoid double evaluation of $set_cc_for_build
+           test -n "$CC_FOR_BUILD" || eval $set_cc_for_build
+           if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null
            then
                HP_ARCH="hppa2.0w"
            else
@@ -643,11 +644,11 @@ EOF
            fi
        fi
        echo ${HP_ARCH}-hp-hpux${HPUX_REV}
-       exit ;;
+       exit ;;
     ia64:HP-UX:*:*)
        HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
        echo ia64-hp-hpux${HPUX_REV}
-       exit ;;
+       exit ;;
     3050*:HI-UX:*:*)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -675,166 +676,150 @@ EOF
          exit (0);
        }
 EOF
-       $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
-               { echo "$SYSTEM_NAME"; exit; }
+       $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0
        echo unknown-hitachi-hiuxwe2
-       exit ;;
+       exit ;;
     9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
        echo hppa1.1-hp-bsd
-       exit ;;
+       exit ;;
     9000/8??:4.3bsd:*:*)
        echo hppa1.0-hp-bsd
-       exit ;;
+       exit ;;
     *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
        echo hppa1.0-hp-mpeix
-       exit ;;
+       exit ;;
     hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
        echo hppa1.1-hp-osf
-       exit ;;
+       exit ;;
     hp8??:OSF1:*:*)
        echo hppa1.0-hp-osf
-       exit ;;
+       exit ;;
     i*86:OSF1:*:*)
        if [ -x /usr/sbin/sysversion ] ; then
            echo ${UNAME_MACHINE}-unknown-osf1mk
        else
            echo ${UNAME_MACHINE}-unknown-osf1
        fi
-       exit ;;
+       exit ;;
     parisc*:Lites*:*:*)
        echo hppa1.1-hp-lites
-       exit ;;
+       exit ;;
     C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
        echo c1-convex-bsd
-        exit ;;
+        exit ;;
     C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
        if getsysinfo -f scalar_acc
        then echo c32-convex-bsd
        else echo c2-convex-bsd
        fi
-        exit ;;
+        exit ;;
     C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
        echo c34-convex-bsd
-        exit ;;
+        exit ;;
     C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
        echo c38-convex-bsd
-        exit ;;
+        exit ;;
     C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
        echo c4-convex-bsd
-        exit ;;
+        exit ;;
     CRAY*Y-MP:*:*:*)
        echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*[A-Z]90:*:*:*)
        echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
        | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
              -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
              -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*TS:*:*:*)
        echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*T3E:*:*:*)
        echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     CRAY*SV1:*:*:*)
        echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       exit ;;
     *:UNICOS/mp:*:*)
-       echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
-       exit ;;
+       echo nv1-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' 
+       exit ;;
     F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
        FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
         FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
         FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
         echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-        exit ;;
-    5000:UNIX_System_V:4.*:*)
-        FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
-        FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
-        echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-       exit ;;
+        exit 0 ;;
     i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
        echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     sparc*:BSD/OS:*:*)
        echo sparc-unknown-bsdi${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:BSD/OS:*:*)
        echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
-       exit ;;
-    *:FreeBSD:*:*)
-       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-       exit ;;
+       exit 0 ;;
+    *:FreeBSD:*:*|*:GNU/FreeBSD:*:*)
+       # Determine whether the default compiler uses glibc.
+       eval $set_cc_for_build
+       sed 's/^        //' << EOF >$dummy.c
+       #include <features.h>
+       #if __GLIBC__ >= 2
+       LIBC=gnu
+       #else
+       LIBC=
+       #endif
+EOF
+       eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+       echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC}
+       exit 0 ;;
     i*:CYGWIN*:*)
        echo ${UNAME_MACHINE}-pc-cygwin
-       exit ;;
+       exit ;;
     i*:MINGW*:*)
        echo ${UNAME_MACHINE}-pc-mingw32
-       exit ;;
-    i*:windows32*:*)
-       # uname -m includes "-pc" on this system.
-       echo ${UNAME_MACHINE}-mingw32
-       exit ;;
+       exit 0 ;;
     i*:PW*:*)
        echo ${UNAME_MACHINE}-pc-pw32
-       exit ;;
+       exit ;;
     x86:Interix*:[34]*)
        echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//'
-       exit ;;
+       exit ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
        echo i${UNAME_MACHINE}-pc-mks
-       exit ;;
+       exit ;;
     i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
        # How do we know it's Interix rather than the generic POSIX subsystem?
        # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
        # UNAME_MACHINE based on the output of uname instead of i386?
        echo i586-pc-interix
-       exit ;;
+       exit ;;
     i*:UWIN*:*)
        echo ${UNAME_MACHINE}-pc-uwin
-       exit ;;
-    amd64:CYGWIN*:*:*)
-       echo x86_64-unknown-cygwin
-       exit ;;
+       exit 0 ;;
     p*:CYGWIN*:*)
        echo powerpcle-unknown-cygwin
-       exit ;;
+       exit ;;
     prep*:SunOS:5.*:*)
        echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
-       exit ;;
+       exit ;;
     *:GNU:*:*)
-       # the GNU system
        echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
-       exit ;;
-    *:GNU/*:*:*)
-       # other systems with GNU libc and userland
-       echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu
-       exit ;;
+       exit 0 ;;
     i*86:Minix:*:*)
        echo ${UNAME_MACHINE}-pc-minix
-       exit ;;
+       exit ;;
     arm*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     cris:Linux:*:*)
        echo cris-axis-linux-gnu
-       exit ;;
-    crisv32:Linux:*:*)
-       echo crisv32-axis-linux-gnu
-       exit ;;
-    frv:Linux:*:*)
-       echo frv-unknown-linux-gnu
-       exit ;;
+       exit 0 ;;
     ia64:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
-    m32r*:Linux:*:*)
-       echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       echo ${UNAME_MACHINE}-${VENDOR:-unknown}-linux-gnu
+       exit 0 ;;
     m68*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     mips:Linux:*:*)
        eval $set_cc_for_build
        sed 's/^        //' << EOF >$dummy.c
@@ -852,7 +837,7 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
        ;;
     mips64:Linux:*:*)
        eval $set_cc_for_build
@@ -871,14 +856,14 @@ EOF
        #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
-       test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
+       test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0
        ;;
     ppc:Linux:*:*)
-       echo powerpc-unknown-linux-gnu
-       exit ;;
+       echo powerpc-${VENDOR:-unknown}-linux-gnu
+       exit ;;
     ppc64:Linux:*:*)
-       echo powerpc64-unknown-linux-gnu
-       exit ;;
+       echo powerpc64-${VENDOR:-unknown}-linux-gnu
+       exit ;;
     alpha:Linux:*:*)
        case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
          EV5)   UNAME_MACHINE=alphaev5 ;;
@@ -892,7 +877,7 @@ EOF
        objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
        if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
        echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
-       exit ;;
+       exit ;;
     parisc:Linux:*:* | hppa:Linux:*:*)
        # Look for CPU level
        case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -900,25 +885,25 @@ EOF
          PA8*) echo hppa2.0-unknown-linux-gnu ;;
          *)    echo hppa-unknown-linux-gnu ;;
        esac
-       exit ;;
+       exit ;;
     parisc64:Linux:*:* | hppa64:Linux:*:*)
        echo hppa64-unknown-linux-gnu
-       exit ;;
+       exit ;;
     s390:Linux:*:* | s390x:Linux:*:*)
-       echo ${UNAME_MACHINE}-ibm-linux
-       exit ;;
+       echo ${UNAME_MACHINE}-${VENDOR:-ibm}-linux-gnu
+       exit ;;
     sh64*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     sh*:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     sparc:Linux:*:* | sparc64:Linux:*:*)
        echo ${UNAME_MACHINE}-unknown-linux-gnu
-       exit ;;
+       exit ;;
     x86_64:Linux:*:*)
-       echo x86_64-unknown-linux-gnu
-       exit ;;
+       echo x86_64-${VENDOR:-unknown}-linux-gnu
+       exit ;;
     i*86:Linux:*:*)
        # The BFD linker knows what the default object file format is, so
        # first see if it will tell us. cd to the root directory to prevent
@@ -936,15 +921,15 @@ EOF
                ;;
          a.out-i386-linux)
                echo "${UNAME_MACHINE}-pc-linux-gnuaout"
-               exit ;;
+               exit ;;
          coff-i386)
                echo "${UNAME_MACHINE}-pc-linux-gnucoff"
-               exit ;;
+               exit ;;
          "")
                # Either a pre-BFD a.out linker (linux-gnuoldld) or
                # one that does not give us useful --help.
                echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
-               exit ;;
+               exit ;;
        esac
        # Determine whether the default compiler is a.out or elf
        eval $set_cc_for_build
@@ -967,23 +952,17 @@ EOF
        LIBC=gnuaout
        #endif
        #endif
-       #ifdef __dietlibc__
-       LIBC=dietlibc
-       #endif
 EOF
        eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
-       test x"${LIBC}" != x && {
-               echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
-               exit
-       }
-       test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
+       test x"${LIBC}" != x && echo "${UNAME_MACHINE}-${VENDOR:-pc}-linux-${LIBC}" && exit 0
+       test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
        ;;
     i*86:DYNIX/ptx:4*:*)
        # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
        # earlier versions are messed up and put the nodename in both
        # sysname and nodename.
        echo i386-sequent-sysv4
-       exit ;;
+       exit ;;
     i*86:UNIX_SV:4.2MP:2.*)
         # Unixware is an offshoot of SVR4, but it has its own version
         # number series starting with 2...
@@ -991,27 +970,24 @@ EOF
        # I just have to hope.  -- rms.
         # Use sysv4.2uw... so that sysv4* matches it.
        echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
-       exit ;;
+       exit ;;
     i*86:OS/2:*:*)
        # If we were able to find `uname', then EMX Unix compatibility
        # is probably installed.
        echo ${UNAME_MACHINE}-pc-os2-emx
-       exit ;;
+       exit ;;
     i*86:XTS-300:*:STOP)
        echo ${UNAME_MACHINE}-unknown-stop
-       exit ;;
+       exit ;;
     i*86:atheos:*:*)
        echo ${UNAME_MACHINE}-unknown-atheos
-       exit ;;
-    i*86:syllable:*:*)
-       echo ${UNAME_MACHINE}-pc-syllable
-       exit ;;
+       exit 0 ;;
     i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
        echo i386-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     i*86:*DOS:*:*)
        echo ${UNAME_MACHINE}-pc-msdosdjgpp
-       exit ;;
+       exit ;;
     i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
        UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
        if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
@@ -1019,16 +995,15 @@ EOF
        else
                echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
        fi
-       exit ;;
-    i*86:*:5:[678]*)
-       # UnixWare 7.x, OpenUNIX and OpenServer 6.
+       exit 0 ;;
+    i*86:*:5:[78]*)
        case `/bin/uname -X | grep "^Machine"` in
            *486*)           UNAME_MACHINE=i486 ;;
            *Pentium)        UNAME_MACHINE=i586 ;;
            *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
        esac
        echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
-       exit ;;
+       exit ;;
     i*86:*:3.2:*)
        if test -f /usr/options/cb.name; then
                UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
@@ -1046,73 +1021,73 @@ EOF
        else
                echo ${UNAME_MACHINE}-pc-sysv32
        fi
-       exit ;;
+       exit ;;
     pc:*:*:*)
        # Left here for compatibility:
         # uname -m prints for DJGPP always 'pc', but it prints nothing about
         # the processor, so we play safe by assuming i386.
        echo i386-pc-msdosdjgpp
-        exit ;;
+        exit ;;
     Intel:Mach:3*:*)
        echo i386-pc-mach3
-       exit ;;
+       exit ;;
     paragon:*:*:*)
        echo i860-intel-osf1
-       exit ;;
+       exit ;;
     i860:*:4.*:*) # i860-SVR4
        if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
          echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
        else # Add other i860-SVR4 vendors below as they are discovered.
          echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
        fi
-       exit ;;
+       exit ;;
     mini*:CTIX:SYS*5:*)
        # "miniframe"
        echo m68010-convergent-sysv
-       exit ;;
+       exit ;;
     mc68k:UNIX:SYSTEM5:3.51m)
        echo m68k-convergent-sysv
-       exit ;;
+       exit ;;
     M680?0:D-NIX:5.3:*)
        echo m68k-diab-dnix
-       exit ;;
-    M68*:*:R3V[5678]*:*)
-       test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+       exit ;;
+    M68*:*:R3V[567]*:*)
+       test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+    3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0)
        OS_REL=''
        test -r /etc/.relid \
        && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
        /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-         && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+         && echo i486-ncr-sysv4.3${OS_REL} && exit 0
        /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-         && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+         && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
     3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
         /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-          && { echo i486-ncr-sysv4; exit; } ;;
+          && echo i486-ncr-sysv4 && exit 0 ;;
     m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
        echo m68k-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     mc68030:UNIX_System_V:4.*:*)
        echo m68k-atari-sysv4
-       exit ;;
+       exit ;;
     TSUNAMI:LynxOS:2.*:*)
        echo sparc-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     rs6000:LynxOS:2.*:*)
        echo rs6000-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
        echo powerpc-unknown-lynxos${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SM[BE]S:UNIX_SV:*:*)
        echo mips-dde-sysv${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     RM*:ReliantUNIX-*:*:*)
        echo mips-sni-sysv4
-       exit ;;
+       exit ;;
     RM*:SINIX-*:*:*)
        echo mips-sni-sysv4
-       exit ;;
+       exit ;;
     *:SINIX-*:*:*)
        if uname -p 2>/dev/null >/dev/null ; then
                UNAME_MACHINE=`(uname -p) 2>/dev/null`
@@ -1120,73 +1095,68 @@ EOF
        else
                echo ns32k-sni-sysv
        fi
-       exit ;;
+       exit ;;
     PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
                       # says <Richard.M.Bartel@ccMail.Census.GOV>
         echo i586-unisys-sysv4
-        exit ;;
+        exit ;;
     *:UNIX_System_V:4*:FTX*)
        # From Gerald Hewes <hewes@openmarket.com>.
        # How about differentiating between stratus architectures? -djm
        echo hppa1.1-stratus-sysv4
-       exit ;;
+       exit ;;
     *:*:*:FTX*)
        # From seanf@swdc.stratus.com.
        echo i860-stratus-sysv4
-       exit ;;
-    i*86:VOS:*:*)
-       # From Paul.Green@stratus.com.
-       echo ${UNAME_MACHINE}-stratus-vos
-       exit ;;
+       exit 0 ;;
     *:VOS:*:*)
        # From Paul.Green@stratus.com.
        echo hppa1.1-stratus-vos
-       exit ;;
+       exit ;;
     mc68*:A/UX:*:*)
        echo m68k-apple-aux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     news*:NEWS-OS:6*:*)
        echo mips-sony-newsos6
-       exit ;;
+       exit ;;
     R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
        if [ -d /usr/nec ]; then
                echo mips-nec-sysv${UNAME_RELEASE}
        else
                echo mips-unknown-sysv${UNAME_RELEASE}
        fi
-        exit ;;
+        exit ;;
     BeBox:BeOS:*:*)    # BeOS running on hardware made by Be, PPC only.
        echo powerpc-be-beos
-       exit ;;
+       exit ;;
     BeMac:BeOS:*:*)    # BeOS running on Mac or Mac clone, PPC only.
        echo powerpc-apple-beos
-       exit ;;
+       exit ;;
     BePC:BeOS:*:*)     # BeOS running on Intel PC compatible.
        echo i586-pc-beos
-       exit ;;
+       exit ;;
     SX-4:SUPER-UX:*:*)
        echo sx4-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SX-5:SUPER-UX:*:*)
        echo sx5-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     SX-6:SUPER-UX:*:*)
        echo sx6-nec-superux${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     Power*:Rhapsody:*:*)
        echo powerpc-apple-rhapsody${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Rhapsody:*:*)
        echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Darwin:*:*)
-       UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
-       case $UNAME_PROCESSOR in
+       case `uname -p` in
            *86) UNAME_PROCESSOR=i686 ;;
-           unknown) UNAME_PROCESSOR=powerpc ;;
+           powerpc) UNAME_PROCESSOR=powerpc ;;
        esac
        echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:procnto*:*:* | *:QNX:[0123456789]*:*)
        UNAME_PROCESSOR=`uname -p`
        if test "$UNAME_PROCESSOR" = "x86"; then
@@ -1194,25 +1164,22 @@ EOF
                UNAME_MACHINE=pc
        fi
        echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:QNX:*:4*)
        echo i386-pc-qnx
-       exit ;;
-    NSE-?:NONSTOP_KERNEL:*:*)
-       echo nse-tandem-nsk${UNAME_RELEASE}
-       exit ;;
-    NSR-?:NONSTOP_KERNEL:*:*)
+       exit 0 ;;
+    NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*)
        echo nsr-tandem-nsk${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:NonStop-UX:*:*)
        echo mips-compaq-nonstopux
-       exit ;;
+       exit ;;
     BS2000:POSIX*:*:*)
        echo bs2000-siemens-sysv
-       exit ;;
+       exit ;;
     DS/*:UNIX_System_V:*:*)
        echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
-       exit ;;
+       exit ;;
     *:Plan9:*:*)
        # "uname -m" is not consistent, so use $cputype instead. 386
        # is converted to i386 for consistency with other x86
@@ -1223,44 +1190,28 @@ EOF
            UNAME_MACHINE="$cputype"
        fi
        echo ${UNAME_MACHINE}-unknown-plan9
-       exit ;;
+       exit ;;
     *:TOPS-10:*:*)
        echo pdp10-unknown-tops10
-       exit ;;
+       exit ;;
     *:TENEX:*:*)
        echo pdp10-unknown-tenex
-       exit ;;
+       exit ;;
     KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
        echo pdp10-dec-tops20
-       exit ;;
+       exit ;;
     XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
        echo pdp10-xkl-tops20
-       exit ;;
+       exit ;;
     *:TOPS-20:*:*)
        echo pdp10-unknown-tops20
-       exit ;;
+       exit ;;
     *:ITS:*:*)
        echo pdp10-unknown-its
-       exit ;;
+       exit ;;
     SEI:*:*:SEIUX)
         echo mips-sei-seiux${UNAME_RELEASE}
-       exit ;;
-    *:DragonFly:*:*)
-       echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
-       exit ;;
-    *:*VMS:*:*)
-       UNAME_MACHINE=`(uname -p) 2>/dev/null`
-       case "${UNAME_MACHINE}" in
-           A*) echo alpha-dec-vms ; exit ;;
-           I*) echo ia64-dec-vms ; exit ;;
-           V*) echo vax-dec-vms ; exit ;;
-       esac ;;
-    *:XENIX:*:SysV)
-       echo i386-pc-xenix
-       exit ;;
-    i*86:skyos:*:*)
-       echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
-       exit ;;
+       exit 0 ;;
 esac
 
 #echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1292,7 +1243,7 @@ main ()
 #endif
 
 #if defined (__arm) && defined (__acorn) && defined (__unix)
-  printf ("arm-acorn-riscix\n"); exit (0);
+  printf ("arm-acorn-riscix"); exit (0);
 #endif
 
 #if defined (hp300) && !defined (hpux)
@@ -1381,12 +1332,11 @@ main ()
 }
 EOF
 
-$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` &&
-       { echo "$SYSTEM_NAME"; exit; }
+$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0
 
 # Apollos put the system type in the environment.
 
-test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; }
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
 
 # Convex versions that predate uname can use getsysinfo(1)
 
@@ -1395,22 +1345,22 @@ then
     case `getsysinfo -f cpu_type` in
     c1*)
        echo c1-convex-bsd
-       exit ;;
+       exit ;;
     c2*)
        if getsysinfo -f scalar_acc
        then echo c32-convex-bsd
        else echo c2-convex-bsd
        fi
-       exit ;;
+       exit ;;
     c34*)
        echo c34-convex-bsd
-       exit ;;
+       exit ;;
     c38*)
        echo c38-convex-bsd
-       exit ;;
+       exit ;;
     c4*)
        echo c4-convex-bsd
-       exit ;;
+       exit ;;
     esac
 fi
 
@@ -1421,9 +1371,7 @@ This script, last modified $timestamp, has failed to recognize
 the operating system you are using. It is advised that you
 download the most up to date version of the config scripts from
 
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.guess
-and
-  http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/config/config/config.sub
+    ftp://ftp.gnu.org/pub/gnu/config/
 
 If the version you run ($0) is already up to date, please
 send the following data and any information you think might be
index e74571c..1126858 100644 (file)
@@ -79,6 +79,9 @@
 /* Define to 1 if you have the <unistd.h> header file. */
 #undef HAVE_UNISTD_H
 
+/* Define if xmltooling library was found */
+#undef HAVE_XMLTOOLING
+
 /* Name of package */
 #undef PACKAGE
 
index 1c366df..6b2ff9f 100755 (executable)
@@ -1,9 +1,9 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
 
-timestamp='2005-07-08'
+timestamp='2003-06-18'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -21,15 +21,14 @@ timestamp='2005-07-08'
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
-# 02110-1301, USA.
-#
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
 # configuration script generated by Autoconf, you may include it under
 # the same distribution terms that you use for the rest of that program.
 
-
 # Please send patches to <config-patches@gnu.org>.  Submit a context
 # diff and a properly formatted ChangeLog entry.
 #
@@ -71,7 +70,7 @@ Report bugs and patches to <config-patches@gnu.org>."
 version="\
 GNU config.sub ($timestamp)
 
-Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
 Free Software Foundation, Inc.
 
 This is free software; see the source for copying conditions.  There is NO
@@ -84,11 +83,11 @@ Try \`$me --help' for more information."
 while test $# -gt 0 ; do
   case $1 in
     --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
+       echo "$timestamp" ; exit ;;
     --version | -v )
-       echo "$version" ; exit ;;
+       echo "$version" ; exit ;;
     --help | --h* | -h )
-       echo "$usage"; exit ;;
+       echo "$usage"; exit ;;
     -- )     # Stop option processing
        shift; break ;;
     - )        # Use stdin as input.
@@ -100,7 +99,7 @@ while test $# -gt 0 ; do
     *local*)
        # First pass through any local machine types.
        echo $1
-       exit ;;
+       exit 0;;
 
     * )
        break ;;
@@ -119,8 +118,7 @@ esac
 # Here we must recognize all the valid KERNEL-OS combinations.
 maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
 case $maybe_os in
-  nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \
-  kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
+  nto-qnx* | linux-gnu* | freebsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*)
     os=-$maybe_os
     basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
     ;;
@@ -146,7 +144,7 @@ case $os in
        -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
        -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
        -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-       -apple | -axis | -knuth | -cray)
+       -apple | -axis)
                os=
                basic_machine=$1
                ;;
@@ -230,16 +228,14 @@ case $basic_machine in
        | a29k \
        | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
        | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
-       | am33_2.0 \
        | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
-       | bfin \
        | c4x | clipper \
        | d10v | d30v | dlx | dsp16xx \
        | fr30 | frv \
        | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
        | i370 | i860 | i960 | ia64 \
-       | ip2k | iq2000 \
-       | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \
+       | ip2k \
+       | m32r | m68000 | m68k | m88k | mcore \
        | mips | mipsbe | mipseb | mipsel | mipsle \
        | mips16 \
        | mips64 | mips64el \
@@ -248,37 +244,31 @@ case $basic_machine in
        | mips64vr4100 | mips64vr4100el \
        | mips64vr4300 | mips64vr4300el \
        | mips64vr5000 | mips64vr5000el \
-       | mips64vr5900 | mips64vr5900el \
        | mipsisa32 | mipsisa32el \
        | mipsisa32r2 | mipsisa32r2el \
        | mipsisa64 | mipsisa64el \
-       | mipsisa64r2 | mipsisa64r2el \
        | mipsisa64sb1 | mipsisa64sb1el \
        | mipsisa64sr71k | mipsisa64sr71kel \
        | mipstx39 | mipstx39el \
        | mn10200 | mn10300 \
-       | ms1 \
        | msp430 \
        | ns16k | ns32k \
-       | or32 \
+       | openrisc | or32 \
        | pdp10 | pdp11 | pj | pjl \
        | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
        | pyramid \
-       | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+       | s390 | s390x \
+       | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
        | sh64 | sh64le \
-       | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
-       | sparcv8 | sparcv9 | sparcv9b \
+       | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \
        | strongarm \
        | tahoe | thumb | tic4x | tic80 | tron \
        | v850 | v850e \
        | we32k \
-       | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+       | x86 | xscale | xstormy16 | xtensa \
        | z8k)
                basic_machine=$basic_machine-unknown
                ;;
-       m32c)
-               basic_machine=$basic_machine-unknown
-               ;;
        m6811 | m68hc11 | m6812 | m68hc12)
                # Motorola 68HC11/12.
                basic_machine=$basic_machine-unknown
@@ -306,19 +296,19 @@ case $basic_machine in
        | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
        | arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
        | avr-* \
-       | bfin-* | bs2000-* \
+       | bs2000-* \
        | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
-       | clipper-* | craynv-* | cydra-* \
+       | clipper-* | cydra-* \
        | d10v-* | d30v-* | dlx-* \
        | elxsi-* \
        | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
        | h8300-* | h8500-* \
        | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
        | i*86-* | i860-* | i960-* | ia64-* \
-       | ip2k-* | iq2000-* \
-       | m32r-* | m32rle-* \
+       | ip2k-* \
+       | m32r-* \
        | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
-       | m88110-* | m88k-* | maxq-* | mcore-* \
+       | m88110-* | m88k-* | mcore-* \
        | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
        | mips16-* \
        | mips64-* | mips64el-* \
@@ -327,40 +317,34 @@ case $basic_machine in
        | mips64vr4100-* | mips64vr4100el-* \
        | mips64vr4300-* | mips64vr4300el-* \
        | mips64vr5000-* | mips64vr5000el-* \
-       | mips64vr5900-* | mips64vr5900el-* \
        | mipsisa32-* | mipsisa32el-* \
        | mipsisa32r2-* | mipsisa32r2el-* \
        | mipsisa64-* | mipsisa64el-* \
-       | mipsisa64r2-* | mipsisa64r2el-* \
        | mipsisa64sb1-* | mipsisa64sb1el-* \
        | mipsisa64sr71k-* | mipsisa64sr71kel-* \
        | mipstx39-* | mipstx39el-* \
-       | mmix-* \
-       | ms1-* \
        | msp430-* \
-       | none-* | np1-* | ns16k-* | ns32k-* \
+       | none-* | np1-* | nv1-* | ns16k-* | ns32k-* \
        | orion-* \
        | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
        | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
        | pyramid-* \
        | romp-* | rs6000-* \
-       | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+       | s390-* | s390x-* \
+       | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \
        | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-       | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
-       | sparclite-* \
+       | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
        | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
        | tahoe-* | thumb-* \
        | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
        | tron-* \
        | v850-* | v850e-* | vax-* \
        | we32k-* \
-       | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
-       | xstormy16-* | xtensa-* \
+       | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+       | xtensa-* \
        | ymp-* \
        | z8k-*)
                ;;
-       m32c-*)
-               ;;
        # Recognize the various machine names and aliases which stand
        # for a CPU type and a company and sometimes even an OS.
        386bsd)
@@ -377,9 +361,6 @@ case $basic_machine in
                basic_machine=a29k-amd
                os=-udi
                ;;
-       abacus)
-               basic_machine=abacus-unknown
-               ;;
        adobe68k)
                basic_machine=m68010-adobe
                os=-scout
@@ -397,9 +378,6 @@ case $basic_machine in
        amd64)
                basic_machine=x86_64-pc
                ;;
-       amd64-*)
-               basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
-               ;;
        amdahl)
                basic_machine=580-amdahl
                os=-sysv
@@ -459,27 +437,12 @@ case $basic_machine in
                basic_machine=j90-cray
                os=-unicos
                ;;
-       craynv)
-               basic_machine=craynv-cray
-               os=-unicosmp
-               ;;
-       cr16c)
-               basic_machine=cr16c-unknown
-               os=-elf
-               ;;
        crds | unos)
                basic_machine=m68k-crds
                ;;
-       crisv32 | crisv32-* | etraxfs*)
-               basic_machine=crisv32-axis
-               ;;
        cris | cris-* | etrax*)
                basic_machine=cris-axis
                ;;
-       crx)
-               basic_machine=crx-unknown
-               os=-elf
-               ;;
        da30 | da30-*)
                basic_machine=m68k-da30
                ;;
@@ -502,10 +465,6 @@ case $basic_machine in
                basic_machine=m88k-motorola
                os=-sysv3
                ;;
-       djgpp)
-               basic_machine=i586-pc
-               os=-msdosdjgpp
-               ;;
        dpx20 | dpx20-*)
                basic_machine=rs6000-bull
                os=-bosx
@@ -684,6 +643,10 @@ case $basic_machine in
        mips3*)
                basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
                ;;
+       mmix*)
+               basic_machine=mmix-knuth
+               os=-mmixware
+               ;;
        monitor)
                basic_machine=m68k-rom68k
                os=-coff
@@ -764,6 +727,10 @@ case $basic_machine in
        np1)
                basic_machine=np1-gould
                ;;
+       nv1)
+               basic_machine=nv1-cray
+               os=-unicosmp
+               ;;
        nsr-tandem)
                basic_machine=nsr-tandem
                ;;
@@ -771,12 +738,9 @@ case $basic_machine in
                basic_machine=hppa1.1-oki
                os=-proelf
                ;;
-       openrisc | openrisc-*)
+       or32 | or32-*)
                basic_machine=or32-unknown
-               ;;
-       os400)
-               basic_machine=powerpc-ibm
-               os=-os400
+               os=-coff
                ;;
        OSE68000 | ose68000)
                basic_machine=m68000-ericsson
@@ -869,12 +833,6 @@ case $basic_machine in
        rtpc | rtpc-*)
                basic_machine=romp-ibm
                ;;
-       s390 | s390-*)
-               basic_machine=s390-ibm
-               ;;
-       s390x | s390x-*)
-               basic_machine=s390x-ibm
-               ;;
        sa29200)
                basic_machine=a29k-amd
                os=-udi
@@ -998,10 +956,6 @@ case $basic_machine in
        tower | tower-32)
                basic_machine=m68k-ncr
                ;;
-       tpf)
-               basic_machine=s390x-ibm
-               os=-tpf
-               ;;
        udi29k)
                basic_machine=a29k-amd
                os=-udi
@@ -1045,10 +999,6 @@ case $basic_machine in
                basic_machine=hppa1.1-winbond
                os=-proelf
                ;;
-       xbox)
-               basic_machine=i686-pc
-               os=-mingw32
-               ;;
        xps | xps100)
                basic_machine=xps100-honeywell
                ;;
@@ -1079,9 +1029,6 @@ case $basic_machine in
        romp)
                basic_machine=romp-ibm
                ;;
-       mmix)
-               basic_machine=mmix-knuth
-               ;;
        rs6000)
                basic_machine=rs6000-ibm
                ;;
@@ -1098,9 +1045,12 @@ case $basic_machine in
        we32k)
                basic_machine=we32k-att
                ;;
-       sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
+       sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele)
                basic_machine=sh-unknown
                ;;
+       sh64)
+               basic_machine=sh64-unknown
+               ;;
        sparc | sparcv8 | sparcv9 | sparcv9b)
                basic_machine=sparc-sun
                ;;
@@ -1174,21 +1124,19 @@ case $os in
              | -aos* \
              | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
              | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
-             | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \
-             | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
-             | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+             | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+             | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
              | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
              | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
              | -chorusos* | -chorusrdb* \
              | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
-             | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \
+             | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
              | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
              | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
              | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
              | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
              | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
-             | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-             | -skyos* | -haiku*)
+             | -powermax* | -dnix* | -nx6 | -nx7 | -sei*)
        # Remember, each alternative MUST END IN *, to match a version number.
                ;;
        -qnx*)
@@ -1206,15 +1154,12 @@ case $os in
                os=`echo $os | sed -e 's|nto|nto-qnx|'`
                ;;
        -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
-             | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+             | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
              | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
                ;;
        -mac*)
                os=`echo $os | sed -e 's|mac|macos|'`
                ;;
-       -linux-dietlibc)
-               os=-linux-dietlibc
-               ;;
        -linux*)
                os=`echo $os | sed -e 's|linux|linux-gnu|'`
                ;;
@@ -1227,9 +1172,6 @@ case $os in
        -opened*)
                os=-openedition
                ;;
-        -os400*)
-               os=-os400
-               ;;
        -wince*)
                os=-wince
                ;;
@@ -1251,9 +1193,6 @@ case $os in
        -atheos*)
                os=-atheos
                ;;
-       -syllable*)
-               os=-syllable
-               ;;
        -386bsd)
                os=-bsd
                ;;
@@ -1276,9 +1215,6 @@ case $os in
        -sinix*)
                os=-sysv4
                ;;
-        -tpf*)
-               os=-tpf
-               ;;
        -triton*)
                os=-sysv3
                ;;
@@ -1315,9 +1251,6 @@ case $os in
        -kaos*)
                os=-kaos
                ;;
-       -zvmoe)
-               os=-zvmoe
-               ;;
        -none)
                ;;
        *)
@@ -1349,9 +1282,9 @@ case $basic_machine in
        arm*-semi)
                os=-aout
                ;;
-    c4x-* | tic4x-*)
-        os=-coff
-        ;;
+       c4x-* | tic4x-*)
+               os=-coff
+               ;;
        # This must come before the *-dec entry.
        pdp10-*)
                os=-tops20
@@ -1395,15 +1328,9 @@ case $basic_machine in
        *-be)
                os=-beos
                ;;
-       *-haiku)
-               os=-haiku
-               ;;
        *-ibm)
                os=-aix
                ;;
-       *-knuth)
-               os=-mmixware
-               ;;
        *-wec)
                os=-proelf
                ;;
@@ -1536,15 +1463,9 @@ case $basic_machine in
                        -mvs* | -opened*)
                                vendor=ibm
                                ;;
-                       -os400*)
-                               vendor=ibm
-                               ;;
                        -ptx*)
                                vendor=sequent
                                ;;
-                       -tpf*)
-                               vendor=ibm
-                               ;;
                        -vxsim* | -vxworks* | -windiss*)
                                vendor=wrs
                                ;;
@@ -1569,7 +1490,7 @@ case $basic_machine in
 esac
 
 echo $basic_machine$os
-exit
+exit 0
 
 # Local variables:
 # eval: (add-hook 'write-file-hooks 'time-stamp)
index 04b4dd2..9778d65 100644 (file)
 #define PACKAGE_NAME "shibboleth"
 
 /* Define to the full name and version of this package. */
-#define PACKAGE_STRING "shibboleth 2.2.1"
+#define PACKAGE_STRING "shibboleth 2.3"
 
 /* Define to the one symbol short name of this package. */
 #define PACKAGE_TARNAME "shibboleth"
 
 /* Define to the version of this package. */
-#define PACKAGE_VERSION "2.2.1"
+#define PACKAGE_VERSION "2.3"
 
 /* Define to the necessary symbol if this constant uses a non-standard name on
    your system. */
 /* #undef TM_IN_SYS_TIME */
 
 /* Version number of package */
-#define VERSION "2.2.1"
+#define VERSION "2.3"
 
 /* Define to empty if `const' does not conform to ANSI C. */
 /* #undef const */
index cd01d03..5a18b62 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am 3088 2009-08-10 16:43:09Z cantor $ 
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $ 
 
 AUTOMAKE_OPTIONS = foreign
 
@@ -46,6 +46,7 @@ CONFIGFILES = \
     postTemplate.html \
        localLogout.html \
        globalLogout.html \
+       partialLogout.html \
        sslError.html
 
 #
index 40939a8..e621f3c 100644 (file)
@@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
@@ -302,6 +304,7 @@ CONFIGFILES = \
     postTemplate.html \
        localLogout.html \
        globalLogout.html \
+       partialLogout.html \
        sslError.html
 
 CLEANFILES = \
index 546ea4f..ee25974 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title>Authorization Failed</title>
 </head>
 <img src="<shibmlp logoLocation/>" alt="Logo" />
 <h1>Authorization Failed</h1>
 
+<p>
 Based on the information provided to this application about you, you are
 not authorized to access the resource at "<shibmlp requestURL/>"
+</p>
 
-<p/>
-
+<p>
 Please contact the administrator of this service or application if you
 believe this to be an error at <a href="mailto:<shibmlp supportContact/>"><shibmlp supportContact/></a>
+</p>
 
 </body>
 </html>
index bce4a7e..4eaa51f 100644 (file)
@@ -1,11 +1,11 @@
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
 # RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
 
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
 
 #
 # Load the Shibboleth module.
@@ -20,7 +20,7 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_13.so
 <Files *.sso>
 SetHandler shib-handler
 </Files>
-#
+
 # Another way of addressing this is to apply Shibboleth
 # globally to the site in "lazy" session mode:
 # <Location />
@@ -37,16 +37,15 @@ SetHandler shib-handler
 </IfModule>
 
 #
-# Configure the module for content
+# Configure the module for content.
 #
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
 # any requests, and there MUST be a require command as well. To
 # enable Shibboleth but not specify any session/access requirements
 # use "require shibboleth".
 #
 <Location /secure>
   AuthType shibboleth
-  ShibRequireSession On
+  ShibRequestSetting requireSession 1
   require valid-user
 </Location>
index 7ea0bb7..ec3df49 100644 (file)
@@ -1,14 +1,14 @@
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
 # RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
 
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
 
 #
-# Load the SHIBBOLETH module
+# Load the Shibboleth module.
 #
 LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_20.so
 
@@ -24,16 +24,15 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_20.so
 </IfModule>
 
 #
-# Configure the module for content
+# Configure the module for content.
 #
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
 # any requests, and there MUST be a require command as well. To
 # enable Shibboleth but not specify any session/access requirements
 # use "require shibboleth".
 #
 <Location /secure>
   AuthType shibboleth
-  ShibRequireSession On
+  ShibRequestSetting requireSession 1
   require valid-user
 </Location>
index 6823db5..853dd42 100644 (file)
@@ -1,14 +1,14 @@
+# https://spaces.internet2.edu/display/SHIB2/NativeSPApacheConfig
+
 # RPM installations on platforms with a conf.d directory will
-# result in this file being copied into that directory for you.
-# For non-RPM installs, you can add this file to your
-# configuration using an Include command in httpd.conf
+# result in this file being copied into that directory for you
+# and preserved across upgrades.
 
-######
-## SHIB Config
-######
+# For non-RPM installs, you should copy the relevant contents of
+# this file to a configuration location you control.
 
 #
-# Load the SHIBBOLETH module
+# Load the Shibboleth module.
 #
 LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_22.so
 
@@ -24,16 +24,15 @@ LoadModule mod_shib @-PKGLIBDIR-@/mod_shib_22.so
 </IfModule>
 
 #
-# Configure the module for content
+# Configure the module for content.
 #
-# You can now do most of this in shibboleth.xml using the RequestMap
-# but you MUST enable AuthType shibboleth for the module to process
+# You MUST enable AuthType shibboleth for the module to process
 # any requests, and there MUST be a require command as well. To
 # enable Shibboleth but not specify any session/access requirements
 # use "require shibboleth".
 #
 <Location /secure>
   AuthType shibboleth
-  ShibRequireSession On
+  ShibRequestSetting requireSession 1
   require valid-user
 </Location>
index bbdf64e..64b3bdc 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title>Global Logout</title>
 </head>
 
 <p><strong>Status of Global Logout:</strong> <shibmlp logoutStatus/></p>
 
-<shibmlpif statusCode>
-       <p>Error from your identity provider:</p>
-       <blockquote>
-               <strong>Status:</strong> <shibmlp statusCode/><br>
-               <shibmlpif statusCode2>
-                       <strong>Sub-Status:</strong> <shibmlp statusCode2/><br>
-               </shibmlpif>
-               <shibmlpif statusMessage>
-                       <strong>Message:</strong> <shibmlp statusMessage/><br>
-               </shibmlpif>
-       </blockquote>
-</shibmlpif>
-
 <p>If the message above indicates success, you have been logged out of all
 the applications and systems that support the logout mechanism.</p>
 
-<p>It is still strongly advised that you close your browser to complete the
-logout process.</p>
+<p>Regardless of the outcome, it is strongly advised that you close your browser
+to ensure that you complete the logout process.</p>
 
 </body>
 </html>
index 401269c..501942b 100644 (file)
@@ -1,98 +1,98 @@
-@echo off\r
-setlocal\r
-\r
-set DAYS=\r
-set YEARS=\r
-set FQDN=\r
-set ENTITYID=\r
-set TEMP_DOMAIN_NAME=\r
-set PARAM=\r
-\r
-set PREFIX=%~dp0\r
-\r
-:opt_start\r
-set PARAM=%1\r
-if not defined PARAM goto opt_end\r
-if %1==-h goto opt_fqdn\r
-if %1==-e goto opt_entityid\r
-if %1==-y goto opt_years\r
-if %1==-f goto opt_force\r
-goto usage\r
-:opt_end\r
-\r
-if exist "%PREFIX%sp-key.pem" goto protect\r
-if exist "%PREFIX%sp-cert.pem" goto protect\r
-\r
-if not defined YEARS set YEARS=10\r
-set /a DAYS=%YEARS%*365\r
-\r
-if not defined FQDN goto guess_fqdn\r
-\r
-:generate\r
-set PATH=%PREFIX%..\..\lib;%PREFIX%..\..\bin\r
-set CNF="%PREFIX%sp-cert.cnf"\r
-echo # OpenSSL configuration file for creating sp-cert.pem    >%CNF%\r
-echo [req]                                                   >>%CNF%\r
-echo prompt=no                                               >>%CNF%\r
-echo default_bits=2048                                       >>%CNF%\r
-echo encrypt_key=no                                          >>%CNF%\r
-echo default_md=sha1                                         >>%CNF%\r
-echo distinguished_name=dn                                   >>%CNF%\r
-echo # PrintableStrings only                                 >>%CNF%\r
-echo string_mask=MASK:0002                                   >>%CNF%\r
-echo x509_extensions=ext                                     >>%CNF%\r
-echo [dn]                                                    >>%CNF%\r
-echo CN=%FQDN%                                               >>%CNF%\r
-echo [ext]                                                   >>%CNF%\r
-if defined ENTITYID (echo subjectAltName=DNS:%FQDN%,URI:%ENTITYID% >>%CNF%) else (echo subjectAltName=DNS:%FQDN% >>%CNF%)\r
-echo subjectKeyIdentifier=hash                               >>%CNF%\r
-%PREFIX%..\..\bin\openssl.exe req -config %PREFIX%sp-cert.cnf -new -x509 -days %DAYS% -keyout %PREFIX%sp-key.pem -out %PREFIX%sp-cert.pem\r
-del %CNF%\r
-exit /b\r
-\r
-:protect\r
-echo The files sp-key.pem and/or sp-cert.pem already exist!\r
-echo Use -f option to force recreation of keypair.\r
-exit /b\r
-\r
-:opt_force\r
-if exist "%PREFIX%sp-key.pem" del "%PREFIX%sp-key.pem"\r
-if exist "%PREFIX%sp-cert.pem" del "%PREFIX%sp-cert.pem"\r
-shift\r
-goto opt_start\r
-\r
-:opt_fqdn\r
-set FQDN=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:opt_entityid\r
-set ENTITYID=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:opt_years\r
-set YEARS=%2\r
-shift\r
-shift\r
-goto opt_start\r
-\r
-:usage\r
-echo usage: keygen [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert]\r
-exit /b\r
-\r
-:guess_fqdn\r
-for /F "tokens=2 delims=:" %%i in ('"ipconfig /all | findstr /c:"Primary DNS Suffix" /c:"Primary Dns Suffix""') do set TEMP_DOMAIN_NAME=%%i\r
-if defined TEMP_DOMAIN_NAME set FQDN=%TEMP_DOMAIN_NAME: =%\r
-set TEMP_DOMAIN_NAME=\r
-if defined USERDNSDOMAIN set FQDN=%USERDNSDOMAIN%\r
-\r
-for /F %%i in ('hostname') do set HOST=%%i\r
-if defined FQDN (set FQDN=%HOST%.%FQDN%) else (set FQDN=%HOST%)\r
-\r
-echo >%FQDN%\r
-for /F %%i in ('dir /b/l %FQDN%') do set FQDN=%%i\r
-del %FQDN%\r
-goto generate\r
+@echo off
+setlocal
+
+set DAYS=
+set YEARS=
+set FQDN=
+set ENTITYID=
+set TEMP_DOMAIN_NAME=
+set PARAM=
+
+set PREFIX=%~dp0
+
+:opt_start
+set PARAM=%1
+if not defined PARAM goto opt_end
+if %1==-h goto opt_fqdn
+if %1==-e goto opt_entityid
+if %1==-y goto opt_years
+if %1==-f goto opt_force
+goto usage
+:opt_end
+
+if exist "%PREFIX%sp-key.pem" goto protect
+if exist "%PREFIX%sp-cert.pem" goto protect
+
+if not defined YEARS set YEARS=10
+set /a DAYS=%YEARS%*365
+
+if not defined FQDN goto guess_fqdn
+
+:generate
+set PATH=%PREFIX%..\..\lib;%PREFIX%..\..\bin
+set CNF="%PREFIX%sp-cert.cnf"
+echo # OpenSSL configuration file for creating sp-cert.pem    >%CNF%
+echo [req]                                                   >>%CNF%
+echo prompt=no                                               >>%CNF%
+echo default_bits=2048                                       >>%CNF%
+echo encrypt_key=no                                          >>%CNF%
+echo default_md=sha1                                         >>%CNF%
+echo distinguished_name=dn                                   >>%CNF%
+echo # PrintableStrings only                                 >>%CNF%
+echo string_mask=MASK:0002                                   >>%CNF%
+echo x509_extensions=ext                                     >>%CNF%
+echo [dn]                                                    >>%CNF%
+echo CN=%FQDN%                                               >>%CNF%
+echo [ext]                                                   >>%CNF%
+if defined ENTITYID (echo subjectAltName=DNS:%FQDN%,URI:%ENTITYID% >>%CNF%) else (echo subjectAltName=DNS:%FQDN% >>%CNF%)
+echo subjectKeyIdentifier=hash                               >>%CNF%
+%PREFIX%..\..\bin\openssl.exe req -config %PREFIX%sp-cert.cnf -new -x509 -days %DAYS% -keyout %PREFIX%sp-key.pem -out %PREFIX%sp-cert.pem
+del %CNF%
+exit /b
+
+:protect
+echo The files sp-key.pem and/or sp-cert.pem already exist!
+echo Use -f option to force recreation of keypair.
+exit /b
+
+:opt_force
+if exist "%PREFIX%sp-key.pem" del "%PREFIX%sp-key.pem"
+if exist "%PREFIX%sp-cert.pem" del "%PREFIX%sp-cert.pem"
+shift
+goto opt_start
+
+:opt_fqdn
+set FQDN=%2
+shift
+shift
+goto opt_start
+
+:opt_entityid
+set ENTITYID=%2
+shift
+shift
+goto opt_start
+
+:opt_years
+set YEARS=%2
+shift
+shift
+goto opt_start
+
+:usage
+echo usage: keygen [-h hostname for cert] [-y years to issue cert] [-e entityID to embed in cert]
+exit /b
+
+:guess_fqdn
+for /F "tokens=2 delims=:" %%i in ('"ipconfig /all | findstr /c:"Primary DNS Suffix" /c:"Primary Dns Suffix""') do set TEMP_DOMAIN_NAME=%%i
+if defined TEMP_DOMAIN_NAME set FQDN=%TEMP_DOMAIN_NAME: =%
+set TEMP_DOMAIN_NAME=
+if defined USERDNSDOMAIN set FQDN=%USERDNSDOMAIN%
+
+for /F %%i in ('hostname') do set HOST=%%i
+if defined FQDN (set FQDN=%HOST%.%FQDN%) else (set FQDN=%HOST%)
+
+echo >%FQDN%
+for /F %%i in ('dir /b/l %FQDN%') do set FQDN=%%i
+del %FQDN%
+goto generate
index 0729fe3..5ae60db 100755 (executable)
@@ -66,5 +66,8 @@ else
     openssl req -config sp-cert.cnf -new -x509 -days $DAYS -keyout sp-key.pem -out sp-cert.pem 2> /dev/null
 fi
 
-chmod 600 sp-key.pem
 rm sp-cert.cnf
+
+if  [ -s sp-key.pem ] ; then
+    chmod 600 sp-key.pem
+fi
index 1bcb1d1..5d749a9 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title>Local Logout</title>
 </head>
index d0e667a..3144e1c 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title>Unknown Identity Provider</title>
 </head>
diff --git a/configs/partialLogout.html b/configs/partialLogout.html
new file mode 100644 (file)
index 0000000..daafda6
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html 
+       PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
+       "DTD/xhtml1-strict.dtd">
+       
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+       <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
+       <title>Partial Logout</title>
+</head>
+
+<body>
+
+<img src="<shibmlp logoLocation/>" alt="Logo" />
+<h1>Partial Logout</h1>
+
+<p>You remain logged into one or more applications accessed during your session.
+To complete the logout process, please close/exit your browser completely.</p>
+
+</body>
+</html>
index 2273174..fbfe9e5 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title><shibmlp errorType/></title>
 </head>
        <blockquote>
                <strong>Status:</strong> <shibmlp statusCode/><br>
                <shibmlpif statusCode2>
-                       <strong>Sub-Status:</strong> <shibmlp statusCode2/><br>
+                       <strong>Sub-Status:</strong> <shibmlp statusCode2/><br/>
                </shibmlpif>
                <shibmlpif statusMessage>
-                       <strong>Message:</strong> <shibmlp statusMessage/><br>
+                       <strong>Message:</strong> <shibmlp statusMessage/><br/>
                </shibmlpif>
        </blockquote>
 </shibmlpif>
index d02da4c..d935c7f 100644 (file)
             <!-- Default example directs to a specific IdP's SSO service (favoring SAML 2 over Shib 1). -->
             <SessionInitiator type="Chaining" Location="/Login" isDefault="true" id="Intranet"
                     relayState="cookie" entityID="https://idp.example.org/shibboleth">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
-                <SessionInitiator type="Shib1" defaultACSIndex="5"/>
+                <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+                <SessionInitiator type="Shib1" acsIndex="5"/>
             </SessionInitiator>
             
             <!-- An example using an old-style WAYF, which means Shib 1 only unless an entityID is provided. -->
             <SessionInitiator type="Chaining" Location="/WAYF" id="WAYF" relayState="cookie">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
-                <SessionInitiator type="Shib1" defaultACSIndex="5"/>
-                <SessionInitiator type="WAYF" defaultACSIndex="5" URL="https://wayf.example.org/WAYF"/>
+                <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+                <SessionInitiator type="Shib1" acsIndex="5"/>
+                <SessionInitiator type="WAYF" acsIndex="5" URL="https://wayf.example.org/WAYF"/>
             </SessionInitiator>
 
             <!-- An example supporting the new-style of discovery service. -->
             <SessionInitiator type="Chaining" Location="/DS" id="DS" relayState="cookie">
-                <SessionInitiator type="SAML2" defaultACSIndex="1" template="bindingTemplate.html"/>
-                <SessionInitiator type="Shib1" defaultACSIndex="5"/>
+                <SessionInitiator type="SAML2" acsIndex="1" template="bindingTemplate.html"/>
+                <SessionInitiator type="Shib1" acsIndex="5"/>
                 <SessionInitiator type="SAMLDS" URL="https://ds.example.org/DS/WAYF"/>
             </SessionInitiator>
             
         </Sessions>
 
         <!--
-        You should customize these pages! You can add attributes with values that can be plugged
-        into your templates. You can remove the access attribute to cause the module to return a
-        standard 403 Forbidden error code if authorization fails, and then customize that condition
-        using your web server.
+        Allows overriding of error template filenames. You can also add attributes with values
+        that can be plugged into the templates.
         -->
-        <Errors session="sessionError.html"
-            metadata="metadataError.html"
-            access="accessError.html"
-            ssl="sslError.html"
-            localLogout="localLogout.html"
-            globalLogout="globalLogout.html"
-            supportContact="root@localhost"
+        <Errors supportContact="root@localhost"
             logoLocation="/shibboleth-sp/logo.jpg"
             styleSheet="/shibboleth-sp/main.css"/>
         
         </TrustEngine>
 
         <!-- Map to extract attributes from SAML assertions. -->
-        <AttributeExtractor type="XML" path="attribute-map.xml"/>
+        <AttributeExtractor type="XML" validate="true" path="attribute-map.xml"/>
         
         <!-- Use a SAML query if no attributes are supplied during SSO. -->
         <AttributeResolver type="Query"/>
 
         <!-- Default filtering policy for recognized attributes, lets other data pass. -->
-        <AttributeFilter type="XML" path="attribute-policy.xml"/>
+        <AttributeFilter type="XML" validate="true" path="attribute-policy.xml"/>
 
         <!-- Simple file-based resolver for using a single keypair. -->
         <CredentialResolver type="File" key="sp-key.pem" certificate="sp-cert.pem"/>
         </Policy>
     </SecurityPolicies>
 
-</SPConfig>
\ No newline at end of file
+</SPConfig>
index 13e8240..59f0995 100644 (file)
@@ -39,6 +39,9 @@ DAEMON_OPTS="$DAEMON_OPTS -c $SHIBSP_CONFIG"
 # Specify pid file to use
 DAEMON_OPTS="$DAEMON_OPTS -p $PIDFILE"
 
+# Specify wait time to use
+DAEMON_OPTS="$DAEMON_OPTS -w 30"
+
 # Exit if the package is not installed.
 [ -x "$DAEMON" ] || exit 0
 
index 02e3426..fd80ee5 100644 (file)
@@ -14,6 +14,7 @@ shibd="@-PREFIX-@/sbin/shibd"
 SHIBD_USER=root
 pidfile=@-PKGRUNDIR-@/shibd.pid
 prog=shibd
+VER=`cat /etc/redhat-release | awk '{print $3}' | awk -F . '{print $1}'`
 RETVAL=0
 
 start() {
@@ -24,7 +25,7 @@ start() {
                        if checkpid $kpid 2>&1; then
                                echo "process already running"
                                        return -1
-                       else
+                               else
                                        echo "lock file found but no process running for pid $kpid, continuing"
                        fi
                fi
@@ -36,7 +37,11 @@ start() {
        if [ -x /usr/sbin/selinuxenabled ] && /usr/sbin/selinuxenabled; then
                /sbin/restorecon $pidfile
        fi
-       daemon --user $SHIBD_USER --pidfile $pidfile $shibd -p $pidfile -f -w 3
+       if [ 5 -le $VER ] ; then
+               daemon --user $SHIBD_USER --pidfile $pidfile $shibd -p $pidfile -f -w 30
+       else
+               daemon --user $SHIBD_USER $shibd -p $pidfile -f -w 30
+       fi
 
        RETVAL=$?
        echo
@@ -46,10 +51,10 @@ start() {
 
 stop() {
        echo -n $"Stopping $prog: "
-       if [ -f $pidfile ]; then
+       if [ -f $pidfile -a 5 -le $VER ] ; then
                killproc -p $pidfile shibd
        else
-        killproc shibd
+               killproc shibd
        fi
 
        RETVAL=$?
@@ -66,7 +71,7 @@ case "$1" in
        stop
        ;;
   status)
-        status $shibd
+       status $shibd
        RETVAL=$?
        ;;
   restart)
index 1dceeda..62a1619 100644 (file)
@@ -32,6 +32,9 @@ DAEMON_OPTS="$DAEMON_OPTS -c $SHIB_CONFIG"
  
 # Specify pid file to use
 DAEMON_OPTS="$DAEMON_OPTS -p $PID_FILE"
+
+# Specify wait time to use
+DAEMON_OPTS="$DAEMON_OPTS -w 30"
  
 # Exit if the package is not installed.
 test -x "$DAEMON" || exit 5
index 2d25f3c..350d45a 100644 (file)
@@ -5,7 +5,7 @@
        
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
 <head>
-       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+       <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <link rel="stylesheet" type="text/css" href="<shibmlp styleSheet/>" />
        <title>POST Failed</title>
 </head>
 <img src="<shibmlp logoLocation/>" alt="Logo" />
 <h1>POST Failed</h1>
 
-
+<p>
 You have attemped to submit information without the protection
-of SSL to this site.<br>
+of SSL to this site.<br/>
+</p>
 
+<p>
 For the protection of your submission and the integrity of the site,
 this is not permitted. Please try accessing the server with a
 URL starting with <strong>https://</strong> and report this problem
 to <a href="mailto:<shibmlp supportContact/>"><shibmlp supportContact/></a>
+</p>
 
 </body>
 </html>
index cd4b0c2..1471e1e 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.59 for shibboleth 2.2.1.
+# Generated by GNU Autoconf 2.59 for shibboleth 2.3.
 #
 # Report bugs to <shibboleth-users@internet2.edu>.
 #
@@ -423,8 +423,8 @@ SHELL=${CONFIG_SHELL-/bin/sh}
 # Identity of this package.
 PACKAGE_NAME='shibboleth'
 PACKAGE_TARNAME='shibboleth'
-PACKAGE_VERSION='2.2.1'
-PACKAGE_STRING='shibboleth 2.2.1'
+PACKAGE_VERSION='2.3'
+PACKAGE_STRING='shibboleth 2.3'
 PACKAGE_BUGREPORT='shibboleth-users@internet2.edu'
 
 # Factoring default headers for most tests.
@@ -464,7 +464,7 @@ ac_includes_default="\
 # include <unistd.h>
 #endif"
 
-ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DX_PROJECT DX_CONFIG DX_DOCDIR DX_ENV DX_FLAG_doc DX_DOXYGEN ac_pt_DX_DOXYGEN DX_PERL ac_pt_DX_PERL DX_COND_doc_TRUE DX_COND_doc_FALSE DX_FLAG_dot DX_DOT ac_pt_DX_DOT DX_COND_dot_TRUE DX_COND_dot_FALSE DX_FLAG_man DX_COND_man_TRUE DX_COND_man_FALSE DX_FLAG_rtf DX_COND_rtf_TRUE DX_COND_rtf_FALSE DX_FLAG_xml DX_COND_xml_TRUE DX_COND_xml_FALSE DX_FLAG_chm DX_HHC ac_pt_DX_HHC DX_COND_chm_TRUE DX_COND_chm_FALSE DX_FLAG_chi DX_COND_chi_TRUE DX_COND_chi_FALSE DX_FLAG_html DX_COND_html_TRUE DX_COND_html_FALSE DX_FLAG_ps DX_LATEX ac_pt_DX_LATEX DX_MAKEINDEX ac_pt_DX_MAKEINDEX DX_DVIPS ac_pt_DX_DVIPS DX_EGREP ac_pt_DX_EGREP DX_COND_ps_TRUE DX_COND_ps_FALSE DX_FLAG_pdf DX_PDFLATEX ac_pt_DX_PDFLATEX DX_COND_pdf_TRUE DX_COND_pdf_FALSE DX_COND_latex_TRUE DX_COND_latex_FALSE DOXYGEN_PAPER_SIZE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS PKG_CONFIG LOG4SHIB_CONFIG LOG4CPP_CONFIG XMLTOOLINGXMLDIR OPENSAMLXMLDIR LITE_LIBS XMLSEC_LIBS NSAPI_INCLUDE BUILD_NSAPI_TRUE BUILD_NSAPI_FALSE FASTCGI_INCLUDE FASTCGI_LDFLAGS FASTCGI_LIBS BUILD_FASTCGI_TRUE BUILD_FASTCGI_FALSE MEMCACHED_INCLUDE MEMCACHED_LDFLAGS MEMCACHED_LIBS BUILD_MEMCACHED_TRUE BUILD_MEMCACHED_FALSE xs APXS APXS_CFLAGS APXS_INCLUDE APXS2 APR_CONFIG APXS2_CFLAGS APXS2_INCLUDE APXS22 APR1_CONFIG APXS22_CFLAGS APXS22_INCLUDE BUILD_AP13_TRUE BUILD_AP13_FALSE BUILD_AP20_TRUE BUILD_AP20_FALSE BUILD_AP22_TRUE BUILD_AP22_FALSE ODBC_CONFIG ODBC_CFLAGS ODBC_LIBS WANT_SUBDIRS LIBOBJS LTLIBOBJS'
+ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA CYGPATH_W PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM mkdir_p AWK SET_MAKE am__leading_dot AMTAR am__tar am__untar DX_PROJECT DX_CONFIG DX_DOCDIR DX_ENV DX_FLAG_doc DX_DOXYGEN ac_pt_DX_DOXYGEN DX_PERL ac_pt_DX_PERL DX_COND_doc_TRUE DX_COND_doc_FALSE DX_FLAG_dot DX_DOT ac_pt_DX_DOT DX_COND_dot_TRUE DX_COND_dot_FALSE DX_FLAG_man DX_COND_man_TRUE DX_COND_man_FALSE DX_FLAG_rtf DX_COND_rtf_TRUE DX_COND_rtf_FALSE DX_FLAG_xml DX_COND_xml_TRUE DX_COND_xml_FALSE DX_FLAG_chm DX_HHC ac_pt_DX_HHC DX_COND_chm_TRUE DX_COND_chm_FALSE DX_FLAG_chi DX_COND_chi_TRUE DX_COND_chi_FALSE DX_FLAG_html DX_COND_html_TRUE DX_COND_html_FALSE DX_FLAG_ps DX_LATEX ac_pt_DX_LATEX DX_MAKEINDEX ac_pt_DX_MAKEINDEX DX_DVIPS ac_pt_DX_DVIPS DX_EGREP ac_pt_DX_EGREP DX_COND_ps_TRUE DX_COND_ps_FALSE DX_FLAG_pdf DX_PDFLATEX ac_pt_DX_PDFLATEX DX_COND_pdf_TRUE DX_COND_pdf_FALSE DX_COND_latex_TRUE DX_COND_latex_FALSE DOXYGEN_PAPER_SIZE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE am__fastdepCC_TRUE am__fastdepCC_FALSE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE am__fastdepCXX_TRUE am__fastdepCXX_FALSE build build_cpu build_vendor build_os host host_cpu host_vendor host_os EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CPP CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL acx_pthread_config PTHREAD_CC PTHREAD_LIBS PTHREAD_CFLAGS PKG_CONFIG LOG4SHIB_CONFIG LOG4CPP_CONFIG XMLTOOLINGXMLDIR OPENSAMLXMLDIR LITE_LIBS XMLSEC_LIBS NSAPI_INCLUDE BUILD_NSAPI_TRUE BUILD_NSAPI_FALSE FASTCGI_INCLUDE FASTCGI_LDFLAGS FASTCGI_LIBS BUILD_FASTCGI_TRUE BUILD_FASTCGI_FALSE MEMCACHED_INCLUDE MEMCACHED_LDFLAGS MEMCACHED_LIBS BUILD_MEMCACHED_TRUE BUILD_MEMCACHED_FALSE xs APXS APXS_CFLAGS APXS_INCLUDE APXS2 APR_CONFIG APU_CONFIG APXS2_CFLAGS APXS2_INCLUDE APXS22 APR1_CONFIG APU1_CONFIG APXS22_CFLAGS APXS22_INCLUDE BUILD_AP13_TRUE BUILD_AP13_FALSE BUILD_AP20_TRUE BUILD_AP20_FALSE BUILD_AP22_TRUE BUILD_AP22_FALSE ODBC_CONFIG ODBC_CFLAGS ODBC_LIBS WANT_SUBDIRS LIBOBJS LTLIBOBJS'
 ac_subst_files=''
 
 # Initialize some variables set by options.
@@ -957,7 +957,7 @@ if test "$ac_init_help" = "long"; then
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures shibboleth 2.2.1 to adapt to many kinds of systems.
+\`configure' configures shibboleth 2.3 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1023,7 +1023,7 @@ fi
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of shibboleth 2.2.1:";;
+     short | recursive ) echo "Configuration of shibboleth 2.3:";;
    esac
   cat <<\_ACEOF
 
@@ -1078,8 +1078,10 @@ Optional Packages:
   --with-apxs=FILE        Specifies where to find the Apache 1.3 apxs script.
   --with-apxs2=FILE       Specifies where to find the Apache 2.0 apxs script.
   --with-apr=PATH         where apr-config is installed
+  --with-apu=PATH         where apu-config is installed
   --with-apxs22=FILE      Specifies where to find the Apache 2.2 apxs script.
   --with-apr1=PATH        where apr-1-config is installed
+  --with-apu1=PATH        where apu-1-config is installed
   --with-odbc=PATH        directory where odbc is installed
 
 Some influential environment variables:
@@ -1197,7 +1199,7 @@ fi
 test -n "$ac_init_help" && exit 0
 if $ac_init_version; then
   cat <<\_ACEOF
-shibboleth configure 2.2.1
+shibboleth configure 2.3
 generated by GNU Autoconf 2.59
 
 Copyright (C) 2003 Free Software Foundation, Inc.
@@ -1211,7 +1213,7 @@ cat >&5 <<_ACEOF
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by shibboleth $as_me 2.2.1, which was
+It was created by shibboleth $as_me 2.3, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   $ $0 $@
@@ -1856,7 +1858,7 @@ fi
 
 # Define the identity of the package.
  PACKAGE=shibboleth
- VERSION=2.2.1
+ VERSION=2.3
 
 
 cat >>confdefs.h <<_ACEOF
@@ -6100,7 +6102,7 @@ ia64-*-hpux*)
   ;;
 *-*-irix6*)
   # Find out which ABI we are using.
-  echo '#line 6103 "configure"' > conftest.$ac_ext
+  echo '#line 6105 "configure"' > conftest.$ac_ext
   if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -7208,7 +7210,7 @@ fi
 
 
 # Provide some information about the compiler.
-echo "$as_me:7211:" \
+echo "$as_me:7213:" \
      "checking for Fortran 77 compiler version" >&5
 ac_compiler=`set X $ac_compile; echo $2`
 { (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5
@@ -8246,11 +8248,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8249: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8251: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8253: \$? = $ac_status" >&5
+   echo "$as_me:8255: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -8479,11 +8481,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8482: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8484: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:8486: \$? = $ac_status" >&5
+   echo "$as_me:8488: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -8539,11 +8541,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:8542: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:8544: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:8546: \$? = $ac_status" >&5
+   echo "$as_me:8548: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -9873,7 +9875,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 9876 "configure"' > conftest.$ac_ext
+    echo '#line 9878 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -10744,7 +10746,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10747 "configure"
+#line 10749 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -10842,7 +10844,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 10845 "configure"
+#line 10847 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -13025,11 +13027,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13028: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13030: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:13032: \$? = $ac_status" >&5
+   echo "$as_me:13034: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -13085,11 +13087,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:13088: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:13090: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:13092: \$? = $ac_status" >&5
+   echo "$as_me:13094: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -13596,7 +13598,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 13599 "configure"' > conftest.$ac_ext
+    echo '#line 13601 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -14467,7 +14469,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 14470 "configure"
+#line 14472 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -14565,7 +14567,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 14568 "configure"
+#line 14570 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -15392,11 +15394,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15395: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15397: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:15399: \$? = $ac_status" >&5
+   echo "$as_me:15401: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -15452,11 +15454,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:15455: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:15457: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:15459: \$? = $ac_status" >&5
+   echo "$as_me:15461: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -16766,7 +16768,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 16769 "configure"' > conftest.$ac_ext
+    echo '#line 16771 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -17511,11 +17513,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17514: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17516: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17518: \$? = $ac_status" >&5
+   echo "$as_me:17520: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -17744,11 +17746,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17747: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17749: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>conftest.err)
    ac_status=$?
    cat conftest.err >&5
-   echo "$as_me:17751: \$? = $ac_status" >&5
+   echo "$as_me:17753: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s "$ac_outfile"; then
      # The compiler can only warn and ignore the option if not recognized
      # So say no if there are warnings
@@ -17804,11 +17806,11 @@ else
    -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \
    -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
    -e 's:$: $lt_compiler_flag:'`
-   (eval echo "\"\$as_me:17807: $lt_compile\"" >&5)
+   (eval echo "\"\$as_me:17809: $lt_compile\"" >&5)
    (eval "$lt_compile" 2>out/conftest.err)
    ac_status=$?
    cat out/conftest.err >&5
-   echo "$as_me:17811: \$? = $ac_status" >&5
+   echo "$as_me:17813: \$? = $ac_status" >&5
    if (exit $ac_status) && test -s out/conftest2.$ac_objext
    then
      # The compiler can only warn and ignore the option if not recognized
@@ -19138,7 +19140,7 @@ linux*)
   libsuff=
   case "$host_cpu" in
   x86_64*|s390x*|powerpc64*)
-    echo '#line 19141 "configure"' > conftest.$ac_ext
+    echo '#line 19143 "configure"' > conftest.$ac_ext
     if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
   (eval $ac_compile) 2>&5
   ac_status=$?
@@ -20009,7 +20011,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 20012 "configure"
+#line 20014 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
@@ -20107,7 +20109,7 @@ else
   lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
   lt_status=$lt_dlunknown
   cat > conftest.$ac_ext <<EOF
-#line 20110 "configure"
+#line 20112 "configure"
 #include "confdefs.h"
 
 #if HAVE_DLFCN_H
 
 
 
+
+# save and append master libs
+save_LIBS="$LIBS"
+LIBS="$XMLSEC_LIBS $LIBS"
+
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <xmltooling/io/HTTPResponse.h>
+int
+main ()
+{
+xmltooling::HTTPResponse::sanitizeURL("http://test")
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+        { ac_try='test -z "$ac_cxx_werror_flag"
+                        || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+        { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_XMLTOOLING 1
+_ACEOF
+
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { echo "$as_me:$LINENO: error: unable to link with XMLTooling, or version was too old" >&5
+echo "$as_me: error: unable to link with XMLTooling, or version was too old" >&2;}
+   { (exit 1); exit 1; }; }
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+
+# restore master libs
+LIBS="$save_LIBS"
+
 # Establish location of xmltooling catalog.
 XMLTOOLINGXMLDIR=""
 if test "x$with_xmltooling" = "x" ; then
@@ -25427,6 +25490,7 @@ fi
 #   --enable-apache-20
 #   --with-apxs2      (DSO build, the normal way, uses apxs to derive build flags)
 #      --with-apr        (DSO build, APR development package installed separately)
+#   --with-apu        (DSO build, APR-UTIL development package installed separately)
 
 # Check whether --enable-apache-20 or --disable-apache-20 was given.
 if test "${enable_apache_20+set}" = set; then
@@ -25646,9 +25710,77 @@ echo "$as_me: error: Unable to locate apr-config, may need --with-apr option." >
    { (exit 1); exit 1; }; }
     fi
 
+    # APU settings
+
+# Check whether --with-apu or --without-apu was given.
+if test "${with_apu+set}" = set; then
+  withval="$with_apu"
+
+        echo "$as_me:$LINENO: checking for user-specified apu-config name/location" >&5
+echo $ECHO_N "checking for user-specified apu-config name/location... $ECHO_C" >&6
+        if test "$withval" != "no" ; then
+            if test "$withval" != "yes"; then
+                APR_CONFIG=$withval
+                echo "$as_me:$LINENO: result: \"$withval\"" >&5
+echo "${ECHO_T}\"$withval\"" >&6
+            fi
+        fi
+
+else
+
+        # Extract the first word of "apu-config", so it can be a program name with args.
+set dummy apu-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_APU_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $APU_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_APU_CONFIG="$APU_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="`$APXS2 -q SBINDIR`:$PATH"
+for as_dir in $as_dummy
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_APU_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+APU_CONFIG=$ac_cv_path_APU_CONFIG
+
+if test -n "$APU_CONFIG"; then
+  echo "$as_me:$LINENO: result: $APU_CONFIG" >&5
+echo "${ECHO_T}$APU_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+fi;
+    if test -f "${APU_CONFIG}"; then
+        APU_CFLAGS="`${APU_CONFIG} --includes`"
+    else
+        { { echo "$as_me:$LINENO: error: Unable to locate apu-config, may need --with-apu option." >&5
+echo "$as_me: error: Unable to locate apu-config, may need --with-apu option." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
     # extract settings we need from APXS2 -q
     APXS2_CC="`$APXS2 -q CC`"
-    APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APR_CFLAGS"
+    APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APU_CFLAGS"
     APXS2_INCLUDE="`$APXS2 -q INCLUDEDIR`"
 fi
 
@@ -25660,6 +25792,7 @@ fi
 #   --enable-apache-22
 #   --with-apxs22     (DSO build, the normal way, uses apxs to derive build flags)
 #      --with-apr1       (DSO build, APR development package installed separately)
+#   --with-apu1       (DSO build, APR-UTIL development package installed separately)
 
 # Check whether --enable-apache-22 or --disable-apache-22 was given.
 if test "${enable_apache_22+set}" = set; then
@@ -25879,9 +26012,77 @@ echo "$as_me: error: Unable to locate apr-1-config, may need --with-apr1 option.
    { (exit 1); exit 1; }; }
     fi
 
+    # APU1 settings
+
+# Check whether --with-apu1 or --without-apu1 was given.
+if test "${with_apu1+set}" = set; then
+  withval="$with_apu1"
+
+        echo "$as_me:$LINENO: checking for user-specified apu-1-config name/location" >&5
+echo $ECHO_N "checking for user-specified apu-1-config name/location... $ECHO_C" >&6
+        if test "$withval" != "no" ; then
+            if test "$withval" != "yes"; then
+                APR1_CONFIG=$withval
+                echo "$as_me:$LINENO: result: \"$withval\"" >&5
+echo "${ECHO_T}\"$withval\"" >&6
+            fi
+        fi
+
+else
+
+        # Extract the first word of "apu-1-config", so it can be a program name with args.
+set dummy apu-1-config; ac_word=$2
+echo "$as_me:$LINENO: checking for $ac_word" >&5
+echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6
+if test "${ac_cv_path_APU1_CONFIG+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  case $APU1_CONFIG in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_APU1_CONFIG="$APU1_CONFIG" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_dummy="`$APXS22 -q SBINDIR`:$PATH"
+for as_dir in $as_dummy
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+  for ac_exec_ext in '' $ac_executable_extensions; do
+  if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_APU1_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+    echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+done
+
+  ;;
+esac
+fi
+APU1_CONFIG=$ac_cv_path_APU1_CONFIG
+
+if test -n "$APU1_CONFIG"; then
+  echo "$as_me:$LINENO: result: $APU1_CONFIG" >&5
+echo "${ECHO_T}$APU1_CONFIG" >&6
+else
+  echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+
+
+fi;
+    if test -f "${APU1_CONFIG}"; then
+        APU1_CFLAGS="`${APU1_CONFIG} --includes`"
+    else
+        { { echo "$as_me:$LINENO: error: Unable to locate apu-1-config, may need --with-apu1 option." >&5
+echo "$as_me: error: Unable to locate apu-1-config, may need --with-apu1 option." >&2;}
+   { (exit 1); exit 1; }; }
+    fi
+
     # extract settings we need from APXS22 -q
     APXS22_CC="`$APXS22 -q CC`"
-    APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS"
+    APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS $APU1_CFLAGS"
     APXS22_INCLUDE="`$APXS22 -q INCLUDEDIR`"
 fi
 
@@ -26891,7 +27092,7 @@ _ASBOX
 } >&5
 cat >&5 <<_CSEOF
 
-This file was extended by shibboleth $as_me 2.2.1, which was
+This file was extended by shibboleth $as_me 2.3, which was
 generated by GNU Autoconf 2.59.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -26954,7 +27155,7 @@ _ACEOF
 
 cat >>$CONFIG_STATUS <<_ACEOF
 ac_cs_version="\\
-shibboleth config.status 2.2.1
+shibboleth config.status 2.3
 configured by $0, generated by GNU Autoconf 2.59,
   with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\"
 
@@ -27318,10 +27519,12 @@ s,@APXS_CFLAGS@,$APXS_CFLAGS,;t t
 s,@APXS_INCLUDE@,$APXS_INCLUDE,;t t
 s,@APXS2@,$APXS2,;t t
 s,@APR_CONFIG@,$APR_CONFIG,;t t
+s,@APU_CONFIG@,$APU_CONFIG,;t t
 s,@APXS2_CFLAGS@,$APXS2_CFLAGS,;t t
 s,@APXS2_INCLUDE@,$APXS2_INCLUDE,;t t
 s,@APXS22@,$APXS22,;t t
 s,@APR1_CONFIG@,$APR1_CONFIG,;t t
+s,@APU1_CONFIG@,$APU1_CONFIG,;t t
 s,@APXS22_CFLAGS@,$APXS22_CFLAGS,;t t
 s,@APXS22_INCLUDE@,$APXS22_INCLUDE,;t t
 s,@BUILD_AP13_TRUE@,$BUILD_AP13_TRUE,;t t
index fd07125..7265638 100644 (file)
@@ -1,7 +1,7 @@
 AC_PREREQ([2.50])
-AC_INIT([shibboleth], [2.2.1], [shibboleth-users@internet2.edu], [shibboleth])
+AC_INIT([shibboleth], [2.3], [shibboleth-users@internet2.edu], [shibboleth])
 AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE([shibboleth],[2.2.1])
+AM_INIT_AUTOMAKE([shibboleth],[2.3])
 
 sinclude(doxygen.m4)
 sinclude(acx_pthread.m4)
@@ -258,6 +258,20 @@ LITE_LIBS="-lxmltooling-lite"
 XMLSEC_LIBS="-lxmltooling"
 AC_CHECK_HEADER([xmltooling/base.h],,
                 AC_MSG_ERROR([unable to find xmltooling header files]))
+                
+
+# save and append master libs
+save_LIBS="$LIBS"
+LIBS="$XMLSEC_LIBS $LIBS"
+
+AC_TRY_LINK(
+    [#include <xmltooling/io/HTTPResponse.h>],
+    [xmltooling::HTTPResponse::sanitizeURL("http://test")],
+    [AC_DEFINE(HAVE_XMLTOOLING,1,[Define if xmltooling library was found])],
+    [AC_MSG_ERROR([unable to link with XMLTooling, or version was too old])])
+
+# restore master libs
+LIBS="$save_LIBS"
 
 # Establish location of xmltooling catalog.
 XMLTOOLINGXMLDIR=""
@@ -618,6 +632,7 @@ AC_SUBST(APXS_INCLUDE)
 #   --enable-apache-20
 #   --with-apxs2      (DSO build, the normal way, uses apxs to derive build flags)
 #      --with-apr        (DSO build, APR development package installed separately)
+#   --with-apu        (DSO build, APR-UTIL development package installed separately)
 
 AC_ARG_ENABLE(apache-20,
        AC_HELP_STRING([--enable-apache-20], [enable the Apache 2.0 module]),
@@ -695,9 +710,30 @@ if test "$WANT_APACHE_20" = "yes" ; then
         AC_MSG_ERROR([Unable to locate apr-config, may need --with-apr option.])
     fi
 
+    # APU settings
+    AC_ARG_WITH(apu, 
+        AC_HELP_STRING([--with-apu=PATH], [where apu-config is installed]),
+        [
+        AC_MSG_CHECKING(for user-specified apu-config name/location)
+        if test "$withval" != "no" ; then
+            if test "$withval" != "yes"; then
+                APR_CONFIG=$withval
+                AC_MSG_RESULT("$withval")
+            fi
+        fi
+        ],
+        [
+        AC_PATH_PROG(APU_CONFIG, apu-config,,[`$APXS2 -q SBINDIR`]:[$PATH])
+        ])
+    if test -f "${APU_CONFIG}"; then
+        APU_CFLAGS="`${APU_CONFIG} --includes`"
+    else
+        AC_MSG_ERROR([Unable to locate apu-config, may need --with-apu option.])
+    fi
+
     # extract settings we need from APXS2 -q
     APXS2_CC="`$APXS2 -q CC`"
-    APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APR_CFLAGS"
+    APXS2_CFLAGS="`$APXS2 -q CPPFLAGS` `$APXS2 -q CFLAGS` $APU_CFLAGS"
     APXS2_INCLUDE="`$APXS2 -q INCLUDEDIR`"
 fi
 
@@ -709,6 +745,7 @@ AC_SUBST(APXS2_INCLUDE)
 #   --enable-apache-22
 #   --with-apxs22     (DSO build, the normal way, uses apxs to derive build flags)
 #      --with-apr1       (DSO build, APR development package installed separately)
+#   --with-apu1       (DSO build, APR-UTIL development package installed separately)
 
 AC_ARG_ENABLE(apache-22,
        AC_HELP_STRING([--enable-apache-22], [enable the Apache 2.2 module]),
@@ -786,9 +823,30 @@ if test "$WANT_APACHE_22" = "yes" ; then
         AC_MSG_ERROR([Unable to locate apr-1-config, may need --with-apr1 option.])
     fi
 
+    # APU1 settings
+    AC_ARG_WITH(apu1, 
+        AC_HELP_STRING([--with-apu1=PATH], [where apu-1-config is installed]),
+        [
+        AC_MSG_CHECKING(for user-specified apu-1-config name/location)
+        if test "$withval" != "no" ; then
+            if test "$withval" != "yes"; then
+                APR1_CONFIG=$withval
+                AC_MSG_RESULT("$withval")
+            fi
+        fi
+        ],
+        [
+        AC_PATH_PROG(APU1_CONFIG, apu-1-config,,[`$APXS22 -q SBINDIR`]:[$PATH])
+        ])
+    if test -f "${APU1_CONFIG}"; then
+        APU1_CFLAGS="`${APU1_CONFIG} --includes`"
+    else
+        AC_MSG_ERROR([Unable to locate apu-1-config, may need --with-apu1 option.])
+    fi
+
     # extract settings we need from APXS22 -q
     APXS22_CC="`$APXS22 -q CC`"
-    APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS"
+    APXS22_CFLAGS="`$APXS22 -q CPPFLAGS` `$APXS22 -q CFLAGS` $APR1_CFLAGS $APU1_CFLAGS"
     APXS22_INCLUDE="`$APXS22 -q INCLUDEDIR`"
 fi
 
old mode 100755 (executable)
new mode 100644 (file)
index ab75e34..ca27df3 100644 (file)
@@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 6443108..e21e018 100644 (file)
@@ -1,4 +1,4 @@
-Version 2.2.1
+Version 2.3
 
 Welcome to Internet2's Shibboleth
 
index 66ee2a7..51a97cc 100644 (file)
@@ -1,14 +1,14 @@
 Release Notes
 
 Shibboleth Native SP
-2.2.1
+2.3
 
 NOTE: The shibboleth2.xml configuration format in this release
 is fully compatible with the 2.1 release, but there are some small
 changes required to eliminate various warnings about deprecated options.
 
 List of issues addressed by this release:
-https://bugs.internet2.edu/jira/secure/IssueNavigator.jspa?reset=true&&pid=10011&fixfor=10232&status=5&status=6&sorter/field=issuekey&sorter/order=ASC
+https://bugs.internet2.edu/jira/browse/SSPCPP/fixforversion/10261
 
 Fully Supported
 
index f0bec65..1c4ba8c 100644 (file)
@@ -1,30 +1,30 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-if BUILD_FASTCGI\r
-\r
-fastcgidir = $(libdir)/@PACKAGE@\r
-\r
-fastcgi_PROGRAMS = shibauthorizer shibresponder\r
-\r
-shibauthorizer_SOURCES = shibauthorizer.cpp\r
-shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibauthorizer_LDADD = \\r
-  $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-shibresponder_SOURCES = shibresponder.cpp\r
-shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)\r
-shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)\r
-shibresponder_LDADD = \\r
-  $(top_builddir)/shibsp/libshibsp-lite.la\r
-\r
-endif\r
-\r
-EXTRA_DIST = \\r
-    shibauthorizer.cpp \\r
-    shibauthorizer.vcproj \\r
-    shibauthorizer.rc \\r
-    shibresponder.cpp \\r
-    shibresponder.vcproj \\r
-    shibresponder.rc \\r
-    resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+if BUILD_FASTCGI
+
+fastcgidir = $(libdir)/@PACKAGE@
+
+fastcgi_PROGRAMS = shibauthorizer shibresponder
+
+shibauthorizer_SOURCES = shibauthorizer.cpp
+shibauthorizer_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibauthorizer_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibauthorizer_LDADD = \
+  $(top_builddir)/shibsp/libshibsp-lite.la
+
+shibresponder_SOURCES = shibresponder.cpp
+shibresponder_CXXFLAGS = -I$(FASTCGI_INCLUDE)
+shibresponder_LDFLAGS = $(FASTCGI_LDFLAGS) $(FASTCGI_LIBS)
+shibresponder_LDADD = \
+  $(top_builddir)/shibsp/libshibsp-lite.la
+
+endif
+
+EXTRA_DIST = \
+    shibauthorizer.cpp \
+    shibauthorizer.vcproj \
+    shibauthorizer.rc \
+    shibresponder.cpp \
+    shibresponder.vcproj \
+    shibresponder.rc \
+    resource.h
index a9af072..7e93df4 100644 (file)
@@ -87,6 +87,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 55162af..f3772c1 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by isapi_shib.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{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
index 59f4417..b7babb5 100644 (file)
-/*\r
- *  Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer\r
-\r
-   Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
-    SHIB_RETURN_OK,\r
-    SHIB_RETURN_KO,\r
-    SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGIAuth : public AbstractSPRequest\r
-{\r
-    FCGX_Request* m_req;\r
-    int m_port;\r
-    string m_scheme,m_hostname;\r
-    multimap<string,string> m_response_headers;\r
-public:\r
-    map<string,string> m_request_headers;\r
-\r
-    ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
-            : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {\r
-        const char* server_name_str = hostname;\r
-        if (!server_name_str || !*server_name_str)\r
-            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
-        m_hostname = server_name_str;\r
-\r
-        m_port = port;\r
-        if (!m_port) {\r
-            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
-            m_port = strtol(server_port_str, &server_port_str, 10);\r
-            if (*server_port_str) {\r
-                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
-                throw runtime_error("Unable to determine server port.");\r
-            }\r
-        }\r
-\r
-        const char* server_scheme_str = scheme;\r
-        if (!server_scheme_str || !*server_scheme_str)\r
-            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
-        m_scheme = server_scheme_str;\r
-\r
-        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
-    }\r
-\r
-    ~ShibTargetFCGIAuth() { }\r
-\r
-    const char* getScheme() const {\r
-        return m_scheme.c_str();\r
-    }\r
-    const char* getHostname() const {\r
-        return m_hostname.c_str();\r
-    }\r
-    int getPort() const {\r
-        return m_port;\r
-    }\r
-    const char* getMethod() const {\r
-        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
-    }\r
-    string getContentType() const {\r
-        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    long getContentLength() const {\r
-        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
-        return s ? atol(s) : 0;\r
-    }\r
-    string getRemoteAddr() const {\r
-        string ret = AbstractSPRequest::getRemoteAddr();\r
-        if (!ret.empty())\r
-            return ret;\r
-        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    void log(SPLogLevel level, const string& msg) const {\r
-        AbstractSPRequest::log(level,msg);\r
-        if (level >= SPError)\r
-            cerr << "shib: " << msg;\r
-    }\r
-    void clearHeader(const char* rawname, const char* cginame) {\r
-        // No need, since we use environment variables.\r
-    }\r
-    void setHeader(const char* name, const char* value) {\r
-        if (value)\r
-            m_request_headers[name] = value;\r
-        else\r
-            m_request_headers.erase(name);\r
-    }\r
-    string getHeader(const char* name) const {\r
-        // Look in the local map first.\r
-        map<string,string>::const_iterator i = m_request_headers.find(name);\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        // Nothing set locally and this isn't a "secure" call, so check the request.\r
-        string hdr("HTTP_");\r
-        for (; *name; ++name) {\r
-            if (*name=='-')\r
-                hdr += '_';\r
-            else\r
-                hdr += toupper(*name);\r
-        }\r
-        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    string getSecureHeader(const char* name) const {\r
-        // Look in the local map only.\r
-        map<string,string>::const_iterator i = m_request_headers.find(name);\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        return "";\r
-    }\r
-    void setRemoteUser(const char* user) {\r
-        if (user)\r
-            m_request_headers["REMOTE_USER"] = user;\r
-        else\r
-            m_request_headers.erase("REMOTE_USER");\r
-    }\r
-    string getRemoteUser() const {\r
-        map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        else {\r
-            char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
-            if (remote_user)\r
-                return remote_user;\r
-        }\r
-        return "";\r
-    }\r
-    void setAuthType(const char* authtype) {\r
-        if (authtype)\r
-            m_request_headers["AUTH_TYPE"] = authtype;\r
-        else\r
-            m_request_headers.erase("AUTH_TYPE");\r
-    }\r
-    string getAuthType() const {\r
-        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");\r
-        if (i != m_request_headers.end())\r
-            return i->second;\r
-        else {\r
-            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);\r
-            if (auth_type)\r
-                return auth_type;\r
-        }\r
-        return "";\r
-    }\r
-    void setResponseHeader(const char* name, const char* value) {\r
-        // Set for later.\r
-        if (value)\r
-            m_response_headers.insert(make_pair(name,value));\r
-        else\r
-            m_response_headers.erase(name);\r
-    }\r
-    const char* getQueryString() const {\r
-        return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
-    }\r
-    const char* getRequestBody() const {\r
-        throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");\r
-    }\r
-\r
-    long sendResponse(istream& in, long status) {\r
-        string hdr = string("Connection: close\r\n");\r
-        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-\r
-        // We can't return 200 OK here or else the filter is bypassed\r
-        // so custom Shib errors will get turned into a generic page.\r
-        const char* codestr="Status: 500 Server Error";\r
-        switch (status) {\r
-            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;\r
-            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;\r
-            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;\r
-        }\r
-        cout << codestr << "\r\n" << hdr << "\r\n";\r
-        char buf[1024];\r
-        while (in) {\r
-            in.read(buf,1024);\r
-            cout.write(buf, in.gcount());\r
-        }\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long sendRedirect(const char* url) {\r
-        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
-          "Content-Type: text/html\r\n"\r
-          "Content-Length: 40\r\n"\r
-          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-          "Cache-Control: private,no-store,no-cache\r\n";\r
-        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-        hdr += "\r\n";\r
-\r
-        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long returnDecline() {\r
-        return SHIB_RETURN_KO;\r
-    }\r
-\r
-    long returnOK() {\r
-        return SHIB_RETURN_OK;\r
-    }\r
-\r
-    const vector<string>& getClientCertificates() const {\r
-        static vector<string> g_NoCerts;\r
-        return g_NoCerts;\r
-    }\r
-};\r
-\r
-static void print_ok(const map<string,string>& headers)\r
-{\r
-    cout << "Status: 200 OK" << "\r\n";\r
-    for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {\r
-        cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";\r
-    }\r
-    cout << "\r\n";\r
-}\r
-\r
-static void print_error(const char* msg)\r
-{\r
-    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
-    SPConfig* g_Config=&SPConfig::getConfig();\r
-    g_Config->setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::RequestMapping |\r
-        SPConfig::InProcess |\r
-        SPConfig::Logging |\r
-        SPConfig::Handlers\r
-        );\r
-    if (!g_Config->init()) {\r
-        cerr << "failed to initialize Shibboleth libraries" << endl;\r
-        exit(1);\r
-    }\r
-\r
-    try {\r
-        if (!g_Config->instantiate(NULL, true))\r
-            throw runtime_error("unknown error");\r
-    }\r
-    catch (exception& ex) {\r
-        g_Config->term();\r
-        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
-        exit(1);\r
-    }\r
-\r
-    string g_ServerScheme;\r
-    string g_ServerName;\r
-    int g_ServerPort=0;\r
-\r
-    // Load "authoritative" URL fields.\r
-    char* var = getenv("SHIBSP_SERVER_NAME");\r
-    if (var)\r
-        g_ServerName = var;\r
-    var = getenv("SHIBSP_SERVER_SCHEME");\r
-    if (var)\r
-        g_ServerScheme = var;\r
-    var = getenv("SHIBSP_SERVER_PORT");\r
-    if (var)\r
-        g_ServerPort = atoi(var);\r
-\r
-    streambuf* cout_streambuf = cout.rdbuf();\r
-    streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
-    FCGX_Request request;\r
-\r
-    FCGX_Init();\r
-    FCGX_InitRequest(&request, 0, 0);\r
-\r
-    cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
-    while (FCGX_Accept_r(&request) == 0)\r
-    {\r
-        // Note that the default bufsize (0) will cause the use of iostream\r
-        // methods that require positioning (such as peek(), seek(),\r
-        // unget() and putback()) to fail (in favour of more efficient IO).\r
-        fcgi_streambuf cout_fcgi_streambuf(request.out);\r
-        fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
-        cout.rdbuf(&cout_fcgi_streambuf);\r
-        cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
-        try {\r
-            xmltooling::NDC ndc("FastCGI shibauthorizer");\r
-            ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
-            pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            res = sta.getServiceProvider().doExport(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doExport handled request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doExport returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            res = sta.getServiceProvider().doAuthorization(sta);\r
-            if (res.first) {\r
-                sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        print_ok(sta.m_request_headers);\r
-                        continue;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        continue;\r
-\r
-                    default:\r
-                        cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");\r
-                        continue;\r
-                }\r
-            }\r
-\r
-            print_ok(sta.m_request_headers);\r
-\r
-        }\r
-        catch (exception& e) {\r
-            cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;\r
-            print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");\r
-        }\r
-\r
-        // If the output streambufs had non-zero bufsizes and\r
-        // were constructed outside of the accept loop (i.e.\r
-        // their destructor won't be called here), they would\r
-        // have to be flushed here.\r
-    }\r
-    cout << "Request loop ended." << endl;\r
-\r
-    cout.rdbuf(cout_streambuf);\r
-    cerr.rdbuf(cerr_streambuf);\r
-\r
-    if (g_Config)\r
-        g_Config->term();\r
-\r
-    return 0;\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/* shibauthorizer.cpp - Shibboleth FastCGI Authorizer
+
+   Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+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);
+
+typedef enum {
+    SHIB_RETURN_OK,
+    SHIB_RETURN_KO,
+    SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGIAuth : public AbstractSPRequest
+{
+    FCGX_Request* m_req;
+    int m_port;
+    string m_scheme,m_hostname;
+    multimap<string,string> m_response_headers;
+public:
+    map<string,string> m_request_headers;
+
+    ShibTargetFCGIAuth(FCGX_Request* req, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+            : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req) {
+        const char* server_name_str = hostname;
+        if (!server_name_str || !*server_name_str)
+            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+        m_hostname = server_name_str;
+
+        m_port = port;
+        if (!m_port) {
+            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+            m_port = strtol(server_port_str, &server_port_str, 10);
+            if (*server_port_str) {
+                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+                throw runtime_error("Unable to determine server port.");
+            }
+        }
+
+        const char* server_scheme_str = scheme;
+        if (!server_scheme_str || !*server_scheme_str)
+            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+        m_scheme = server_scheme_str;
+
+        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+    }
+
+    ~ShibTargetFCGIAuth() { }
+
+    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 FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+    }
+    string getContentType() const {
+        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+        return s ? s : "";
+    }
+    long getContentLength() const {
+        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+        return s ? atol(s) : 0;
+    }
+    string getRemoteAddr() const {
+        string ret = AbstractSPRequest::getRemoteAddr();
+        if (!ret.empty())
+            return ret;
+        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+        return s ? s : "";
+    }
+    void log(SPLogLevel level, const string& msg) const {
+        AbstractSPRequest::log(level,msg);
+        if (level >= SPError)
+            cerr << "shib: " << msg;
+    }
+    void clearHeader(const char* rawname, const char* cginame) {
+        // No need, since we use environment variables.
+    }
+    void setHeader(const char* name, const char* value) {
+        if (value)
+            m_request_headers[name] = value;
+        else
+            m_request_headers.erase(name);
+    }
+    string getHeader(const char* name) const {
+        // Look in the local map first.
+        map<string,string>::const_iterator i = m_request_headers.find(name);
+        if (i != m_request_headers.end())
+            return i->second;
+        // Nothing set locally and this isn't a "secure" call, so check the request.
+        string hdr("HTTP_");
+        for (; *name; ++name) {
+            if (*name=='-')
+                hdr += '_';
+            else
+                hdr += toupper(*name);
+        }
+        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+        return s ? s : "";
+    }
+    string getSecureHeader(const char* name) const {
+        // Look in the local map only.
+        map<string,string>::const_iterator i = m_request_headers.find(name);
+        if (i != m_request_headers.end())
+            return i->second;
+        return "";
+    }
+    void setRemoteUser(const char* user) {
+        if (user)
+            m_request_headers["REMOTE_USER"] = user;
+        else
+            m_request_headers.erase("REMOTE_USER");
+    }
+    string getRemoteUser() const {
+        map<string,string>::const_iterator i = m_request_headers.find("REMOTE_USER");
+        if (i != m_request_headers.end())
+            return i->second;
+        else {
+            char* remote_user = FCGX_GetParam("REMOTE_USER", m_req->envp);
+            if (remote_user)
+                return remote_user;
+        }
+        return "";
+    }
+    void setAuthType(const char* authtype) {
+        if (authtype)
+            m_request_headers["AUTH_TYPE"] = authtype;
+        else
+            m_request_headers.erase("AUTH_TYPE");
+    }
+    string getAuthType() const {
+        map<string,string>::const_iterator i = m_request_headers.find("AUTH_TYPE");
+        if (i != m_request_headers.end())
+            return i->second;
+        else {
+            char* auth_type = FCGX_GetParam("AUTH_TYPE", m_req->envp);
+            if (auth_type)
+                return auth_type;
+        }
+        return "";
+    }
+    void setResponseHeader(const char* name, const char* value) {
+        HTTPResponse::setResponseHeader(name, value);
+        // Set for later.
+        if (value)
+            m_response_headers.insert(make_pair(name,value));
+        else
+            m_response_headers.erase(name);
+    }
+    const char* getQueryString() const {
+        return FCGX_GetParam("QUERY_STRING", m_req->envp);
+    }
+    const char* getRequestBody() const {
+        throw runtime_error("getRequestBody not implemented by FastCGI authorizer.");
+    }
+
+    long sendResponse(istream& in, long status) {
+        string hdr = string("Connection: close\r\n");
+        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+
+        // We can't return 200 OK here or else the filter is bypassed
+        // so custom Shib errors will get turned into a generic page.
+        const char* codestr="Status: 500 Server Error";
+        switch (status) {
+            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;
+            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;
+            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;
+        }
+        cout << codestr << "\r\n" << hdr << "\r\n";
+        char buf[1024];
+        while (in) {
+            in.read(buf,1024);
+            cout.write(buf, in.gcount());
+        }
+        return SHIB_RETURN_DONE;
+    }
+
+    long sendRedirect(const char* url) {
+        HTTPResponse::sendRedirect(url);
+        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+          "Content-Type: text/html\r\n"
+          "Content-Length: 40\r\n"
+          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+          "Cache-Control: private,no-store,no-cache\r\n";
+        for (multimap<string,string>::const_iterator i=m_response_headers.begin(); i!=m_response_headers.end(); ++i)
+            hdr += i->first + ": " + i->second + "\r\n";
+        hdr += "\r\n";
+
+        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+        return SHIB_RETURN_DONE;
+    }
+
+    long returnDecline() {
+        return SHIB_RETURN_KO;
+    }
+
+    long returnOK() {
+        return SHIB_RETURN_OK;
+    }
+
+    const vector<string>& getClientCertificates() const {
+        static vector<string> g_NoCerts;
+        return g_NoCerts;
+    }
+};
+
+static void print_ok(const map<string,string>& headers)
+{
+    cout << "Status: 200 OK" << "\r\n";
+    for (map<string,string>::const_iterator iter = headers.begin(); iter != headers.end(); iter++) {
+        cout << "Variable-" << iter->first << ": " << iter->second << "\r\n";
+    }
+    cout << "\r\n";
+}
+
+static void print_error(const char* msg)
+{
+    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+    SPConfig* g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        cerr << "failed to initialize Shibboleth libraries" << endl;
+        exit(1);
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+        exit(1);
+    }
+
+    string g_ServerScheme;
+    string g_ServerName;
+    int g_ServerPort=0;
+
+    // Load "authoritative" URL fields.
+    char* var = getenv("SHIBSP_SERVER_NAME");
+    if (var)
+        g_ServerName = var;
+    var = getenv("SHIBSP_SERVER_SCHEME");
+    if (var)
+        g_ServerScheme = var;
+    var = getenv("SHIBSP_SERVER_PORT");
+    if (var)
+        g_ServerPort = atoi(var);
+
+    streambuf* cout_streambuf = cout.rdbuf();
+    streambuf* cerr_streambuf = cerr.rdbuf();
+
+    FCGX_Request request;
+
+    FCGX_Init();
+    FCGX_InitRequest(&request, 0, 0);
+
+    cout << "Shibboleth initialization complete. Starting request loop." << endl;
+    while (FCGX_Accept_r(&request) == 0)
+    {
+        // Note that the default bufsize (0) will cause the use of iostream
+        // methods that require positioning (such as peek(), seek(),
+        // unget() and putback()) to fail (in favour of more efficient IO).
+        fcgi_streambuf cout_fcgi_streambuf(request.out);
+        fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+        cout.rdbuf(&cout_fcgi_streambuf);
+        cerr.rdbuf(&cerr_fcgi_streambuf);
+
+        try {
+            xmltooling::NDC ndc("FastCGI shibauthorizer");
+            ShibTargetFCGIAuth sta(&request, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+            pair<bool,long> res = sta.getServiceProvider().doAuthentication(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doAuthentication handled the request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doAuthentication returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            res = sta.getServiceProvider().doExport(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doExport handled request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doExport returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            res = sta.getServiceProvider().doAuthorization(sta);
+            if (res.first) {
+                sta.log(SPRequest::SPDebug, "shib: doAuthorization handled request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_KO:
+                        print_ok(sta.m_request_headers);
+                        continue;
+
+                    case SHIB_RETURN_DONE:
+                        continue;
+
+                    default:
+                        cerr << "shib: doAuthorization returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth authorizer returned an unexpected result.</body></html>");
+                        continue;
+                }
+            }
+
+            print_ok(sta.m_request_headers);
+
+        }
+        catch (exception& e) {
+            cerr << "shib: FastCGI authorizer caught an exception: " << e.what() << endl;
+            print_error("<html><body>FastCGI Shibboleth authorizer caught an exception, check log for details.</body></html>");
+        }
+
+        // If the output streambufs had non-zero bufsizes and
+        // were constructed outside of the accept loop (i.e.
+        // their destructor won't be called here), they would
+        // have to be flushed here.
+    }
+    cout << "Request loop ended." << endl;
+
+    cout.rdbuf(cout_streambuf);
+    cerr.rdbuf(cerr_streambuf);
+
+    if (g_Config)
+        g_Config->term();
+
+    return 0;
+}
index c9b4c1d..37258c9 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth FastCGI Authorizer\0"\r
-            VALUE "FileVersion", "2, 2, 1, 0\0"\r
+            VALUE "FileVersion", "2, 3, 0, 0\0"\r
             VALUE "InternalName", "shibauthorizer\0"\r
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibauthorizer.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
-            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.3\0"\r
+            VALUE "ProductVersion", "2, 3, 0, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index 1537e33..c99d945 100644 (file)
-/*\r
- *  Copyright 2001-2007 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler\r
-\r
-   Andre Cruz\r
-*/\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _SCL_SECURE_NO_WARNINGS 1\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <stdexcept>\r
-#include <stdlib.h>\r
-#ifdef HAVE_UNISTD_H\r
-# include <unistd.h>\r
-# include <sys/mman.h>\r
-#endif\r
-#include <fcgio.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-static const XMLCh path[] =     UNICODE_LITERAL_4(p,a,t,h);\r
-static const XMLCh validate[] = UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-\r
-typedef enum {\r
-    SHIB_RETURN_OK,\r
-    SHIB_RETURN_KO,\r
-    SHIB_RETURN_DONE\r
-} shib_return_t;\r
-\r
-class ShibTargetFCGI : public AbstractSPRequest\r
-{\r
-    FCGX_Request* m_req;\r
-    const char* m_body;\r
-    multimap<string,string> m_headers;\r
-    int m_port;\r
-    string m_scheme,m_hostname;\r
-\r
-public:\r
-    ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)\r
-        : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {\r
-\r
-        const char* server_name_str = hostname;\r
-        if (!server_name_str || !*server_name_str)\r
-            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);\r
-        m_hostname = server_name_str;\r
-\r
-        m_port = port;\r
-        if (!m_port) {\r
-            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);\r
-            m_port = strtol(server_port_str, &server_port_str, 10);\r
-            if (*server_port_str) {\r
-                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;\r
-                throw runtime_error("Unable to determine server port.");\r
-            }\r
-        }\r
-\r
-        const char* server_scheme_str = scheme;\r
-        if (!server_scheme_str || !*server_scheme_str)\r
-            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";\r
-        m_scheme = server_scheme_str;\r
-\r
-        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));\r
-    }\r
-\r
-    ~ShibTargetFCGI() { }\r
-\r
-    const char* getScheme() const {\r
-        return m_scheme.c_str();\r
-    }\r
-    const char* getHostname() const {\r
-        return m_hostname.c_str();\r
-    }\r
-    int getPort() const {\r
-        return m_port;\r
-    }\r
-    const char* getMethod() const {\r
-        return FCGX_GetParam("REQUEST_METHOD", m_req->envp);\r
-    }\r
-    string getContentType() const {\r
-        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    long getContentLength() const {\r
-        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);\r
-        return s ? atol(s) : 0;\r
-    }\r
-    string getRemoteUser() const {\r
-        const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    string getRemoteAddr() const {\r
-        string ret = AbstractSPRequest::getRemoteAddr();\r
-        if (!ret.empty())\r
-            return ret;\r
-        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-    void log(SPLogLevel level, const string& msg) const {\r
-        AbstractSPRequest::log(level,msg);\r
-        if (level >= SPError)\r
-            cerr << "shib: " << msg;\r
-    }\r
-\r
-    string getHeader(const char* name) const {\r
-        string hdr("HTTP_");\r
-        for (; *name; ++name) {\r
-            if (*name=='-')\r
-                hdr += '_';\r
-            else\r
-                hdr += toupper(*name);\r
-        }\r
-        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);\r
-        return s ? s : "";\r
-    }\r
-\r
-    void setResponseHeader(const char* name, const char* value) {\r
-        // Set for later.\r
-        if (value)\r
-            m_headers.insert(make_pair(name,value));\r
-        else\r
-            m_headers.erase(name);\r
-    }\r
-\r
-    const char* getQueryString() const {\r
-        return FCGX_GetParam("QUERY_STRING", m_req->envp);\r
-    }\r
-\r
-    const char* getRequestBody() const {\r
-        return m_body;\r
-    }\r
-\r
-    long sendResponse(istream& in, long status) {\r
-        string hdr = string("Connection: close\r\n");\r
-        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-\r
-        const char* codestr="Status: 200 OK";\r
-        switch (status) {\r
-            case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="Status: 500 Server Error"; break;\r
-            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;\r
-            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;\r
-            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;\r
-        }\r
-        cout << codestr << "\r\n" << hdr << "\r\n";\r
-        char buf[1024];\r
-        while (in) {\r
-            in.read(buf,1024);\r
-            cout.write(buf, in.gcount());\r
-        }\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long sendRedirect(const char* url) {\r
-        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"\r
-          "Content-Type: text/html\r\n"\r
-          "Content-Length: 40\r\n"\r
-          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-          "Cache-Control: private,no-store,no-cache\r\n";\r
-        for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-            hdr += i->first + ": " + i->second + "\r\n";\r
-        hdr += "\r\n";\r
-\r
-        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";\r
-        return SHIB_RETURN_DONE;\r
-    }\r
-\r
-    long returnDecline() {\r
-        return SHIB_RETURN_KO;\r
-    }\r
-    long returnOK() {\r
-        return SHIB_RETURN_OK;\r
-    }\r
-\r
-    const vector<string>& getClientCertificates() const {\r
-        static vector<string> g_NoCerts;\r
-        return g_NoCerts;\r
-    }\r
-\r
-    // Not used in the extension.\r
-\r
-    virtual void clearHeader(const char* rawname, const char* cginame) {\r
-        throw runtime_error("clearHeader not implemented by FastCGI responder.");\r
-    }\r
-\r
-    virtual void setHeader(const char* name, const char* value) {\r
-        throw runtime_error("setHeader not implemented by FastCGI responder.");\r
-    }\r
-\r
-    virtual void setRemoteUser(const char* user) {\r
-        throw runtime_error("setRemoteUser not implemented by FastCGI responder.");\r
-    }\r
-};\r
-\r
-// Maximum number of bytes allowed to be read from stdin\r
-static const unsigned long STDIN_MAX = 1000000;\r
-\r
-static long gstdin(FCGX_Request* request, char** content)\r
-{\r
-    char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);\r
-    unsigned long clen = STDIN_MAX;\r
-\r
-    if (clenstr) {\r
-        clen = strtol(clenstr, &clenstr, 10);\r
-        if (*clenstr) {\r
-            cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;\r
-            clen = STDIN_MAX;\r
-        }\r
-\r
-        // *always* put a cap on the amount of data that will be read\r
-        if (clen > STDIN_MAX)\r
-            clen = STDIN_MAX;\r
-\r
-        *content = new char[clen];\r
-\r
-        cin.read(*content, clen);\r
-        clen = cin.gcount();\r
-    }\r
-    else {\r
-        // *never* read stdin when CONTENT_LENGTH is missing or unparsable\r
-        *content = 0;\r
-        clen = 0;\r
-    }\r
-\r
-    // Chew up any remaining stdin - this shouldn't be necessary\r
-    // but is because mod_fastcgi doesn't handle it correctly.\r
-\r
-    // ignore() doesn't set the eof bit in some versions of glibc++\r
-    // so use gcount() instead of eof()...\r
-    do cin.ignore(1024); while (cin.gcount() == 1024);\r
-\r
-    return clen;\r
-}\r
-\r
-static void print_ok() {\r
-    cout << "Status: 200 OK" << "\r\n\r\n";\r
-}\r
-\r
-static void print_error(const char* msg) {\r
-    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;\r
-}\r
-\r
-int main(void)\r
-{\r
-    SPConfig* g_Config=&SPConfig::getConfig();\r
-    g_Config->setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::RequestMapping |\r
-        SPConfig::InProcess |\r
-        SPConfig::Logging |\r
-        SPConfig::Handlers\r
-        );\r
-    if (!g_Config->init()) {\r
-        cerr << "failed to initialize Shibboleth libraries" << endl;\r
-        exit(1);\r
-    }\r
-\r
-    try {\r
-        if (!g_Config->instantiate(NULL, true))\r
-            throw runtime_error("unknown error");\r
-    }\r
-    catch (exception& ex) {\r
-        g_Config->term();\r
-        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;\r
-        exit(1);\r
-    }\r
-\r
-    string g_ServerScheme;\r
-    string g_ServerName;\r
-    int g_ServerPort=0;\r
-\r
-    // Load "authoritative" URL fields.\r
-    char* var = getenv("SHIBSP_SERVER_NAME");\r
-    if (var)\r
-        g_ServerName = var;\r
-    var = getenv("SHIBSP_SERVER_SCHEME");\r
-    if (var)\r
-        g_ServerScheme = var;\r
-    var = getenv("SHIBSP_SERVER_PORT");\r
-    if (var)\r
-        g_ServerPort = atoi(var);\r
-\r
-    streambuf* cin_streambuf  = cin.rdbuf();\r
-    streambuf* cout_streambuf = cout.rdbuf();\r
-    streambuf* cerr_streambuf = cerr.rdbuf();\r
-\r
-    FCGX_Request request;\r
-\r
-    FCGX_Init();\r
-    FCGX_InitRequest(&request, 0, 0);\r
-\r
-    cout << "Shibboleth initialization complete. Starting request loop." << endl;\r
-    while (FCGX_Accept_r(&request) == 0) {\r
-        // Note that the default bufsize (0) will cause the use of iostream\r
-        // methods that require positioning (such as peek(), seek(),\r
-        // unget() and putback()) to fail (in favour of more efficient IO).\r
-        fcgi_streambuf cin_fcgi_streambuf(request.in);\r
-        fcgi_streambuf cout_fcgi_streambuf(request.out);\r
-        fcgi_streambuf cerr_fcgi_streambuf(request.err);\r
-\r
-        cin.rdbuf(&cin_fcgi_streambuf);\r
-        cout.rdbuf(&cout_fcgi_streambuf);\r
-        cerr.rdbuf(&cerr_fcgi_streambuf);\r
-\r
-        // Although FastCGI supports writing before reading,\r
-        // many http clients (browsers) don't support it (so\r
-        // the connection deadlocks until a timeout expires!).\r
-        char* content;\r
-        gstdin(&request, &content);\r
-\r
-        try {\r
-            xmltooling::NDC ndc("FastCGI shibresponder");\r
-            ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);\r
-\r
-            pair<bool,long> res = stf.getServiceProvider().doHandler(stf);\r
-            if (res.first) {\r
-                stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");\r
-                switch(res.second) {\r
-                    case SHIB_RETURN_OK:\r
-                        print_ok();\r
-                        break;\r
-\r
-                    case SHIB_RETURN_KO:\r
-                        cerr << "shib: doHandler failed to handle the request" << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");\r
-                        break;\r
-\r
-                    case SHIB_RETURN_DONE:\r
-                        // response already handled\r
-                        break;\r
-\r
-                    default:\r
-                        cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;\r
-                        print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");\r
-                        break;\r
-                }\r
-            }\r
-            else {\r
-                cerr << "shib: doHandler failed to handle request." << endl;\r
-                print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");\r
-            }\r
-\r
-        }\r
-        catch (exception& e) {\r
-            cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;\r
-            print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");\r
-        }\r
-\r
-        delete[] content;\r
-\r
-        // If the output streambufs had non-zero bufsizes and\r
-        // were constructed outside of the accept loop (i.e.\r
-        // their destructor won't be called here), they would\r
-        // have to be flushed here.\r
-    }\r
-\r
-    cout << "Request loop ended." << endl;\r
-\r
-    cin.rdbuf(cin_streambuf);\r
-    cout.rdbuf(cout_streambuf);\r
-    cerr.rdbuf(cerr_streambuf);\r
-\r
-    if (g_Config)\r
-        g_Config->term();\r
-\r
-    return 0;\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/* shibresponder.cpp - Shibboleth FastCGI Responder/Handler
+
+   Andre Cruz
+*/
+
+#define SHIBSP_LITE
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+#define _SCL_SECURE_NO_WARNINGS 1
+
+#include <shibsp/AbstractSPRequest.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <xmltooling/unicode.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/XMLConstants.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <stdexcept>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+# include <sys/mman.h>
+#endif
+#include <fcgio.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace std;
+
+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);
+
+typedef enum {
+    SHIB_RETURN_OK,
+    SHIB_RETURN_KO,
+    SHIB_RETURN_DONE
+} shib_return_t;
+
+class ShibTargetFCGI : public AbstractSPRequest
+{
+    FCGX_Request* m_req;
+    const char* m_body;
+    multimap<string,string> m_headers;
+    int m_port;
+    string m_scheme,m_hostname;
+
+public:
+    ShibTargetFCGI(FCGX_Request* req, char* post_data, const char* scheme=NULL, const char* hostname=NULL, int port=0)
+        : AbstractSPRequest(SHIBSP_LOGCAT".FastCGI"), m_req(req), m_body(post_data) {
+
+        const char* server_name_str = hostname;
+        if (!server_name_str || !*server_name_str)
+            server_name_str = FCGX_GetParam("SERVER_NAME", req->envp);
+        m_hostname = server_name_str;
+
+        m_port = port;
+        if (!m_port) {
+            char* server_port_str = FCGX_GetParam("SERVER_PORT", req->envp);
+            m_port = strtol(server_port_str, &server_port_str, 10);
+            if (*server_port_str) {
+                cerr << "can't parse SERVER_PORT (" << FCGX_GetParam("SERVER_PORT", req->envp) << ")" << endl;
+                throw runtime_error("Unable to determine server port.");
+            }
+        }
+
+        const char* server_scheme_str = scheme;
+        if (!server_scheme_str || !*server_scheme_str)
+            server_scheme_str = (m_port == 443 || m_port == 8443) ? "https" : "http";
+        m_scheme = server_scheme_str;
+
+        setRequestURI(FCGX_GetParam("REQUEST_URI", m_req->envp));
+    }
+
+    ~ShibTargetFCGI() { }
+
+    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 FCGX_GetParam("REQUEST_METHOD", m_req->envp);
+    }
+    string getContentType() const {
+        const char* s = FCGX_GetParam("CONTENT_TYPE", m_req->envp);
+        return s ? s : "";
+    }
+    long getContentLength() const {
+        const char* s = FCGX_GetParam("CONTENT_LENGTH", m_req->envp);
+        return s ? atol(s) : 0;
+    }
+    string getRemoteUser() const {
+        const char* s = FCGX_GetParam("REMOTE_USER", m_req->envp);
+        return s ? s : "";
+    }
+    string getRemoteAddr() const {
+        string ret = AbstractSPRequest::getRemoteAddr();
+        if (!ret.empty())
+            return ret;
+        const char* s = FCGX_GetParam("REMOTE_ADDR", m_req->envp);
+        return s ? s : "";
+    }
+    void log(SPLogLevel level, const string& msg) const {
+        AbstractSPRequest::log(level,msg);
+        if (level >= SPError)
+            cerr << "shib: " << msg;
+    }
+
+    string getHeader(const char* name) const {
+        string hdr("HTTP_");
+        for (; *name; ++name) {
+            if (*name=='-')
+                hdr += '_';
+            else
+                hdr += toupper(*name);
+        }
+        char* s = FCGX_GetParam(hdr.c_str(), m_req->envp);
+        return s ? s : "";
+    }
+
+    void setResponseHeader(const char* name, const char* value) {
+        HTTPResponse::setResponseHeader(name, value);
+        // Set for later.
+        if (value)
+            m_headers.insert(make_pair(name,value));
+        else
+            m_headers.erase(name);
+    }
+
+    const char* getQueryString() const {
+        return FCGX_GetParam("QUERY_STRING", m_req->envp);
+    }
+
+    const char* getRequestBody() const {
+        return m_body;
+    }
+
+    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";
+
+        const char* codestr="Status: 200 OK";
+        switch (status) {
+            case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="Status: 500 Server Error"; break;
+            case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="Status: 401 Authorization Required"; break;
+            case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="Status: 403 Forbidden"; break;
+            case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="Status: 404 Not Found"; break;
+        }
+        cout << codestr << "\r\n" << hdr << "\r\n";
+        char buf[1024];
+        while (in) {
+            in.read(buf,1024);
+            cout.write(buf, in.gcount());
+        }
+        return SHIB_RETURN_DONE;
+    }
+
+    long sendRedirect(const char* url) {
+        HTTPResponse::sendRedirect(url);
+        string hdr=string("Status: 302 Please Wait\r\nLocation: ") + url + "\r\n"
+          "Content-Type: text/html\r\n"
+          "Content-Length: 40\r\n"
+          "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
+          "Cache-Control: private,no-store,no-cache\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";
+
+        cout << hdr << "<HTML><BODY>Redirecting...</BODY></HTML>";
+        return SHIB_RETURN_DONE;
+    }
+
+    long returnDecline() {
+        return SHIB_RETURN_KO;
+    }
+    long returnOK() {
+        return SHIB_RETURN_OK;
+    }
+
+    const vector<string>& getClientCertificates() const {
+        static vector<string> g_NoCerts;
+        return g_NoCerts;
+    }
+
+    // Not used in the extension.
+
+    virtual void clearHeader(const char* rawname, const char* cginame) {
+        throw runtime_error("clearHeader not implemented by FastCGI responder.");
+    }
+
+    virtual void setHeader(const char* name, const char* value) {
+        throw runtime_error("setHeader not implemented by FastCGI responder.");
+    }
+
+    virtual void setRemoteUser(const char* user) {
+        throw runtime_error("setRemoteUser not implemented by FastCGI responder.");
+    }
+};
+
+// Maximum number of bytes allowed to be read from stdin
+static const unsigned long STDIN_MAX = 1000000;
+
+static long gstdin(FCGX_Request* request, char** content)
+{
+    char* clenstr = FCGX_GetParam("CONTENT_LENGTH", request->envp);
+    unsigned long clen = STDIN_MAX;
+
+    if (clenstr) {
+        clen = strtol(clenstr, &clenstr, 10);
+        if (*clenstr) {
+            cerr << "can't parse CONTENT_LENGTH (" << FCGX_GetParam("CONTENT_LENGTH", request->envp) << ")" << endl;
+            clen = STDIN_MAX;
+        }
+
+        // *always* put a cap on the amount of data that will be read
+        if (clen > STDIN_MAX)
+            clen = STDIN_MAX;
+
+        *content = new char[clen];
+
+        cin.read(*content, clen);
+        clen = cin.gcount();
+    }
+    else {
+        // *never* read stdin when CONTENT_LENGTH is missing or unparsable
+        *content = 0;
+        clen = 0;
+    }
+
+    // Chew up any remaining stdin - this shouldn't be necessary
+    // but is because mod_fastcgi doesn't handle it correctly.
+
+    // ignore() doesn't set the eof bit in some versions of glibc++
+    // so use gcount() instead of eof()...
+    do cin.ignore(1024); while (cin.gcount() == 1024);
+
+    return clen;
+}
+
+static void print_ok() {
+    cout << "Status: 200 OK" << "\r\n\r\n";
+}
+
+static void print_error(const char* msg) {
+    cout << "Status: 500 Server Error" << "\r\n\r\n" << msg;
+}
+
+int main(void)
+{
+    SPConfig* g_Config=&SPConfig::getConfig();
+    g_Config->setFeatures(
+        SPConfig::Listener |
+        SPConfig::Caching |
+        SPConfig::RequestMapping |
+        SPConfig::InProcess |
+        SPConfig::Logging |
+        SPConfig::Handlers
+        );
+    if (!g_Config->init()) {
+        cerr << "failed to initialize Shibboleth libraries" << endl;
+        exit(1);
+    }
+
+    try {
+        if (!g_Config->instantiate(NULL, true))
+            throw runtime_error("unknown error");
+    }
+    catch (exception& ex) {
+        g_Config->term();
+        cerr << "exception while initializing Shibboleth configuration: " << ex.what() << endl;
+        exit(1);
+    }
+
+    string g_ServerScheme;
+    string g_ServerName;
+    int g_ServerPort=0;
+
+    // Load "authoritative" URL fields.
+    char* var = getenv("SHIBSP_SERVER_NAME");
+    if (var)
+        g_ServerName = var;
+    var = getenv("SHIBSP_SERVER_SCHEME");
+    if (var)
+        g_ServerScheme = var;
+    var = getenv("SHIBSP_SERVER_PORT");
+    if (var)
+        g_ServerPort = atoi(var);
+
+    streambuf* cin_streambuf  = cin.rdbuf();
+    streambuf* cout_streambuf = cout.rdbuf();
+    streambuf* cerr_streambuf = cerr.rdbuf();
+
+    FCGX_Request request;
+
+    FCGX_Init();
+    FCGX_InitRequest(&request, 0, 0);
+
+    cout << "Shibboleth initialization complete. Starting request loop." << endl;
+    while (FCGX_Accept_r(&request) == 0) {
+        // Note that the default bufsize (0) will cause the use of iostream
+        // methods that require positioning (such as peek(), seek(),
+        // unget() and putback()) to fail (in favour of more efficient IO).
+        fcgi_streambuf cin_fcgi_streambuf(request.in);
+        fcgi_streambuf cout_fcgi_streambuf(request.out);
+        fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+        cin.rdbuf(&cin_fcgi_streambuf);
+        cout.rdbuf(&cout_fcgi_streambuf);
+        cerr.rdbuf(&cerr_fcgi_streambuf);
+
+        // Although FastCGI supports writing before reading,
+        // many http clients (browsers) don't support it (so
+        // the connection deadlocks until a timeout expires!).
+        char* content;
+        gstdin(&request, &content);
+
+        try {
+            xmltooling::NDC ndc("FastCGI shibresponder");
+            ShibTargetFCGI stf(&request, content, g_ServerScheme.c_str(), g_ServerName.c_str(), g_ServerPort);
+
+            pair<bool,long> res = stf.getServiceProvider().doHandler(stf);
+            if (res.first) {
+                stf.log(SPRequest::SPDebug, "shib: doHandler handled the request");
+                switch(res.second) {
+                    case SHIB_RETURN_OK:
+                        print_ok();
+                        break;
+
+                    case SHIB_RETURN_KO:
+                        cerr << "shib: doHandler failed to handle the request" << endl;
+                        print_error("<html><body>FastCGI Shibboleth responder should only be used for Shibboleth protocol requests.</body></html>");
+                        break;
+
+                    case SHIB_RETURN_DONE:
+                        // response already handled
+                        break;
+
+                    default:
+                        cerr << "shib: doHandler returned an unexpected result: " << res.second << endl;
+                        print_error("<html><body>FastCGI Shibboleth responder returned an unexpected result.</body></html>");
+                        break;
+                }
+            }
+            else {
+                cerr << "shib: doHandler failed to handle request." << endl;
+                print_error("<html><body>FastCGI Shibboleth responder failed to process request.</body></html>");
+            }
+
+        }
+        catch (exception& e) {
+            cerr << "shib: FastCGI responder caught an exception: " << e.what() << endl;
+            print_error("<html><body>FastCGI Shibboleth responder caught an exception, check log for details.</body></html>");
+        }
+
+        delete[] content;
+
+        // If the output streambufs had non-zero bufsizes and
+        // were constructed outside of the accept loop (i.e.
+        // their destructor won't be called here), they would
+        // have to be flushed here.
+    }
+
+    cout << "Request loop ended." << endl;
+
+    cin.rdbuf(cin_streambuf);
+    cout.rdbuf(cout_streambuf);
+    cerr.rdbuf(cerr_streambuf);
+
+    if (g_Config)
+        g_Config->term();
+
+    return 0;
+}
index 4bccb0f..f95c347 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth FastCGI Responder\0"\r
-            VALUE "FileVersion", "2, 2, 1, 0\0"\r
+            VALUE "FileVersion", "2, 3, 0, 0\0"\r
             VALUE "InternalName", "shibresponder\0"\r
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibresponder.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
-            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.3\0"\r
+            VALUE "ProductVersion", "2, 3, 0, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index 148a079..73fdcce 100644 (file)
 #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 <sstream>
+#include <fstream>
+#include <stdexcept>
+#include <process.h>
 #include <xmltooling/unicode.h>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
 #include <xercesc/util/Base64.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
 
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
 #include <windows.h>
 #include <httpfilt.h>
 #include <httpext.h>
@@ -202,32 +203,6 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
         flag=props->getBool("catchAll");
         g_catchAll = flag.first && flag.second;
 
-<<<<<<< .mine
-        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 {
-                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) {
-                    ostringstream keystr;
-                    keystr << randkey << randkey2 << randkey3 << randkey4;
-                    g_spoofKey = keystr.str();
-                }
-                else {
-                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
-                    g_Config->term();
-                    g_Config=NULL;
-                    return FALSE;
-                }
-            }
-        }
-
-=======
         pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");
         if (unsetValue.first)
             g_unsetHeaderValue = unsetValue.second;
@@ -256,7 +231,6 @@ extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
             }
         }
 
->>>>>>> .r3097
         props = props->getPropertySet("ISAPI");
         if (props) {
             flag = props->getBool("normalizeRequest");
@@ -560,6 +534,7 @@ public:
     return getSecureHeader("remote-user");
   }
   void setResponseHeader(const char* name, const char* value) {
+    HTTPResponse::setResponseHeader(name, value);
     // Set for later.
     if (value)
         m_headers.insert(make_pair(name,value));
@@ -588,7 +563,7 @@ public:
     return SF_STATUS_REQ_FINISHED;
   }
   long sendRedirect(const char* url) {
-    // XXX: Don't support the httpRedirect option, yet.
+    HTTPResponse::sendRedirect(url);
     string hdr=string("Location: ") + url + "\r\n"
       "Content-Type: text/html\r\n"
       "Content-Length: 40\r\n"
@@ -869,6 +844,7 @@ public:
     return buf.empty() ? "" : buf;
   }
   void setResponseHeader(const char* name, const char* value) {
+    HTTPResponse::setResponseHeader(name, value);
     // Set for later.
     if (value)
         m_headers.insert(make_pair(name,value));
@@ -930,6 +906,7 @@ public:
     return HSE_STATUS_SUCCESS;
   }
   long sendRedirect(const char* url) {
+    HTTPResponse::sendRedirect(url);
     string hdr=string("Location: ") + url + "\r\n"
       "Content-Type: text/html\r\n"
       "Content-Length: 40\r\n"
diff --git a/isapi_shib/isapi_shib.cpp.mine b/isapi_shib/isapi_shib.cpp.mine
deleted file mode 100644 (file)
index 9d2278e..0000000
+++ /dev/null
@@ -1,993 +0,0 @@
-/*\r
- *  Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * isapi_shib.cpp\r
- *\r
- * Shibboleth ISAPI filter\r
- */\r
-\r
-#define SHIBSP_LITE\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-#define _CRT_RAND_S\r
-\r
-#include <shibsp/AbstractSPRequest.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <xmltooling/unicode.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/Base64.hpp>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <set>\r
-#include <sstream>\r
-#include <fstream>\r
-#include <stdexcept>\r
-#include <process.h>\r
-\r
-#include <windows.h>\r
-#include <httpfilt.h>\r
-#include <httpext.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-// globals\r
-namespace {\r
-    static const XMLCh path[] =             UNICODE_LITERAL_4(p,a,t,h);\r
-    static const XMLCh validate[] =         UNICODE_LITERAL_8(v,a,l,i,d,a,t,e);\r
-    static const XMLCh name[] =             UNICODE_LITERAL_4(n,a,m,e);\r
-    static const XMLCh port[] =             UNICODE_LITERAL_4(p,o,r,t);\r
-    static const XMLCh sslport[] =          UNICODE_LITERAL_7(s,s,l,p,o,r,t);\r
-    static const XMLCh scheme[] =           UNICODE_LITERAL_6(s,c,h,e,m,e);\r
-    static const XMLCh id[] =               UNICODE_LITERAL_2(i,d);\r
-    static const XMLCh Alias[] =            UNICODE_LITERAL_5(A,l,i,a,s);\r
-    static const XMLCh Site[] =             UNICODE_LITERAL_4(S,i,t,e);\r
-\r
-    struct site_t {\r
-        site_t(const DOMElement* e)\r
-        {\r
-            auto_ptr_char n(e->getAttributeNS(NULL,name));\r
-            auto_ptr_char s(e->getAttributeNS(NULL,scheme));\r
-            auto_ptr_char p(e->getAttributeNS(NULL,port));\r
-            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));\r
-            if (n.get()) m_name=n.get();\r
-            if (s.get()) m_scheme=s.get();\r
-            if (p.get()) m_port=p.get();\r
-            if (p2.get()) m_sslport=p2.get();\r
-            e = XMLHelper::getFirstChildElement(e, Alias);\r
-            while (e) {\r
-                if (e->hasChildNodes()) {\r
-                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());\r
-                    m_aliases.insert(alias.get());\r
-                }\r
-                e = XMLHelper::getNextSiblingElement(e, Alias);\r
-            }\r
-        }\r
-        string m_scheme,m_port,m_sslport,m_name;\r
-        set<string> m_aliases;\r
-    };\r
-\r
-    HINSTANCE g_hinstDLL;\r
-    SPConfig* g_Config = NULL;\r
-    map<string,site_t> g_Sites;\r
-    bool g_bNormalizeRequest = true;\r
-    string g_unsetHeaderValue,g_spoofKey;\r
-    bool g_checkSpoofing = true;\r
-    bool g_catchAll = false;\r
-    bool g_bSafeHeaderNames = false;\r
-    vector<string> g_NoCerts;\r
-}\r
-\r
-BOOL LogEvent(\r
-    LPCSTR  lpUNCServerName,\r
-    WORD  wType,\r
-    DWORD  dwEventID,\r
-    PSID  lpUserSid,\r
-    LPCSTR  message)\r
-{\r
-    LPCSTR  messages[] = {message, NULL};\r
-\r
-    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");\r
-    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
-    return (DeregisterEventSource(hElog) && res);\r
-}\r
-\r
-extern "C" __declspec(dllexport) BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID)\r
-{\r
-    if (fdwReason==DLL_PROCESS_ATTACH)\r
-        g_hinstDLL=hinstDLL;\r
-    return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO* pVer)\r
-{\r
-    if (!pVer)\r
-        return FALSE;\r
-\r
-    if (!g_Config) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
-                "Extension mode startup not possible, is the DLL loaded as a filter?");\r
-        return FALSE;\r
-    }\r
-\r
-    pVer->dwExtensionVersion=HSE_VERSION;\r
-    strncpy(pVer->lpszExtensionDesc,"Shibboleth ISAPI Extension",HSE_MAX_EXT_DLL_NAME_LEN-1);\r
-    return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI TerminateExtension(DWORD)\r
-{\r
-    return TRUE;    // cleanup should happen when filter unloads\r
-}\r
-\r
-extern "C" BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)\r
-{\r
-    if (!pVer)\r
-        return FALSE;\r
-    else if (g_Config) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
-                "Reentrant filter initialization, ignoring...");\r
-        return TRUE;\r
-    }\r
-\r
-    g_Config=&SPConfig::getConfig();\r
-    g_Config->setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::RequestMapping |\r
-        SPConfig::InProcess |\r
-        SPConfig::Logging |\r
-        SPConfig::Handlers\r
-        );\r
-    if (!g_Config->init()) {\r
-        g_Config=NULL;\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
-                "Filter startup failed during library initialization, check native log for help.");\r
-        return FALSE;\r
-    }\r
-\r
-    try {\r
-        if (!g_Config->instantiate(NULL, true))\r
-            throw runtime_error("unknown error");\r
-    }\r
-    catch (exception& ex) {\r
-        g_Config->term();\r
-        g_Config=NULL;\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
-                "Filter startup failed to load configuration, check native log for details.");\r
-        return FALSE;\r
-    }\r
-\r
-    // Access implementation-specifics and site mappings.\r
-    ServiceProvider* sp=g_Config->getServiceProvider();\r
-    Locker locker(sp);\r
-    const PropertySet* props=sp->getPropertySet("InProcess");\r
-    if (props) {\r
-        pair<bool,bool> flag=props->getBool("checkSpoofing");\r
-        g_checkSpoofing = !flag.first || flag.second;\r
-        flag=props->getBool("catchAll");\r
-        g_catchAll = flag.first && flag.second;\r
-\r
-        pair<bool,const char*> unsetValue=props->getString("unsetHeaderValue");\r
-        if (unsetValue.first)\r
-            g_unsetHeaderValue = unsetValue.second;\r
-        if (g_checkSpoofing) {\r
-            unsetValue = props->getString("spoofKey");\r
-            if (unsetValue.first)\r
-                g_spoofKey = unsetValue.second;\r
-            else {\r
-                unsigned int randkey=0,randkey2=0,randkey3=0,randkey4=0;\r
-                if (rand_s(&randkey) == 0 && rand_s(&randkey2) == 0 && rand_s(&randkey3) == 0 && rand_s(&randkey4) == 0) {\r
-                    ostringstream keystr;\r
-                    keystr << randkey << randkey2 << randkey3 << randkey4;\r
-                    g_spoofKey = keystr.str();\r
-                }\r
-                else {\r
-                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,\r
-                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");\r
-                    g_Config->term();\r
-                    g_Config=NULL;\r
-                    return FALSE;\r
-                }\r
-            }\r
-        }\r
-\r
-        props = props->getPropertySet("ISAPI");\r
-        if (props) {\r
-            flag = props->getBool("normalizeRequest");\r
-            g_bNormalizeRequest = !flag.first || flag.second;\r
-            flag = props->getBool("safeHeaderNames");\r
-            g_bSafeHeaderNames = flag.first && flag.second;\r
-            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);\r
-            while (child) {\r
-                auto_ptr_char id(child->getAttributeNS(NULL,id));\r
-                if (id.get())\r
-                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));\r
-                child=XMLHelper::getNextSiblingElement(child,Site);\r
-            }\r
-        }\r
-    }\r
-\r
-    pVer->dwFilterVersion=HTTP_FILTER_REVISION;\r
-    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);\r
-    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |\r
-                   SF_NOTIFY_SECURE_PORT |\r
-                   SF_NOTIFY_NONSECURE_PORT |\r
-                   SF_NOTIFY_PREPROC_HEADERS |\r
-                   SF_NOTIFY_LOG);\r
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");\r
-    return TRUE;\r
-}\r
-\r
-extern "C" BOOL WINAPI TerminateFilter(DWORD)\r
-{\r
-    if (g_Config)\r
-        g_Config->term();\r
-    g_Config = NULL;\r
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut down...");\r
-    return TRUE;\r
-}\r
-\r
-/* Next up, some suck-free versions of various APIs.\r
-\r
-   You DON'T require people to guess the buffer size and THEN tell them the right size.\r
-   Returning an LPCSTR is apparently way beyond their ken. Not to mention the fact that\r
-   constant strings aren't typed as such, making it just that much harder. These versions\r
-   are now updated to use a special growable buffer object, modeled after the standard\r
-   string class. The standard string won't work because they left out the option to\r
-   pre-allocate a non-constant buffer.\r
-*/\r
-\r
-class dynabuf\r
-{\r
-public:\r
-    dynabuf() { bufptr=NULL; buflen=0; }\r
-    dynabuf(size_t s) { bufptr=new char[buflen=s]; *bufptr=0; }\r
-    ~dynabuf() { delete[] bufptr; }\r
-    size_t length() const { return bufptr ? strlen(bufptr) : 0; }\r
-    size_t size() const { return buflen; }\r
-    bool empty() const { return length()==0; }\r
-    void reserve(size_t s, bool keep=false);\r
-    void erase() { if (bufptr) memset(bufptr,0,buflen); }\r
-    operator char*() { return bufptr; }\r
-    bool operator ==(const char* s) const;\r
-    bool operator !=(const char* s) const { return !(*this==s); }\r
-private:\r
-    char* bufptr;\r
-    size_t buflen;\r
-};\r
-\r
-void dynabuf::reserve(size_t s, bool keep)\r
-{\r
-    if (s<=buflen)\r
-        return;\r
-    char* p=new char[s];\r
-    if (keep)\r
-        while (buflen--)\r
-            p[buflen]=bufptr[buflen];\r
-    buflen=s;\r
-    delete[] bufptr;\r
-    bufptr=p;\r
-}\r
-\r
-bool dynabuf::operator==(const char* s) const\r
-{\r
-    if (buflen==NULL || s==NULL)\r
-        return (buflen==NULL && s==NULL);\r
-    else\r
-        return strcmp(bufptr,s)==0;\r
-}\r
-\r
-void GetServerVariable(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
-    s.reserve(size);\r
-    s.erase();\r
-    size=s.size();\r
-\r
-    while (!pfc->GetServerVariable(pfc,lpszVariable,s,&size)) {\r
-        // Grumble. Check the error.\r
-        DWORD e=GetLastError();\r
-        if (e==ERROR_INSUFFICIENT_BUFFER)\r
-            s.reserve(size);\r
-        else\r
-            break;\r
-    }\r
-    if (bRequired && s.empty())\r
-        throw ERROR_NO_DATA;\r
-}\r
-\r
-void GetServerVariable(LPEXTENSION_CONTROL_BLOCK lpECB, LPSTR lpszVariable, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
-    s.reserve(size);\r
-    s.erase();\r
-    size=s.size();\r
-\r
-    while (!lpECB->GetServerVariable(lpECB->ConnID,lpszVariable,s,&size)) {\r
-        // Grumble. Check the error.\r
-        DWORD e=GetLastError();\r
-        if (e==ERROR_INSUFFICIENT_BUFFER)\r
-            s.reserve(size);\r
-        else\r
-            break;\r
-    }\r
-    if (bRequired && s.empty())\r
-        throw ERROR_NO_DATA;\r
-}\r
-\r
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,\r
-               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)\r
-{\r
-    s.reserve(size);\r
-    s.erase();\r
-    size=s.size();\r
-\r
-    while (!pn->GetHeader(pfc,lpszName,s,&size)) {\r
-        // Grumble. Check the error.\r
-        DWORD e=GetLastError();\r
-        if (e==ERROR_INSUFFICIENT_BUFFER)\r
-            s.reserve(size);\r
-        else\r
-            break;\r
-    }\r
-    if (bRequired && s.empty())\r
-        throw ERROR_NO_DATA;\r
-}\r
-\r
-/****************************************************************************/\r
-// ISAPI Filter\r
-\r
-class ShibTargetIsapiF : public AbstractSPRequest\r
-{\r
-  PHTTP_FILTER_CONTEXT m_pfc;\r
-  PHTTP_FILTER_PREPROC_HEADERS m_pn;\r
-  multimap<string,string> m_headers;\r
-  int m_port;\r
-  string m_scheme,m_hostname;\r
-  mutable string m_remote_addr,m_content_type,m_method;\r
-  dynabuf m_allhttp;\r
-  bool m_firsttime;\r
-\r
-public:\r
-  ShibTargetIsapiF(PHTTP_FILTER_CONTEXT pfc, PHTTP_FILTER_PREPROC_HEADERS pn, const site_t& site)\r
-      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_pfc(pfc), m_pn(pn), m_allhttp(4096), m_firsttime(true) {\r
-\r
-    // URL path always come from IIS.\r
-    dynabuf var(256);\r
-    GetHeader(pn,pfc,"url",var,256,false);\r
-    setRequestURI(var);\r
-\r
-    // Port may come from IIS or from site def.\r
-    if (!g_bNormalizeRequest || (pfc->fIsSecurePort && site.m_sslport.empty()) || (!pfc->fIsSecurePort && site.m_port.empty())) {\r
-        GetServerVariable(pfc,"SERVER_PORT",var,10);\r
-        m_port = atoi(var);\r
-    }\r
-    else if (pfc->fIsSecurePort) {\r
-        m_port = atoi(site.m_sslport.c_str());\r
-    }\r
-    else {\r
-        m_port = atoi(site.m_port.c_str());\r
-    }\r
-\r
-    // Scheme may come from site def or be derived from IIS.\r
-    m_scheme=site.m_scheme;\r
-    if (m_scheme.empty() || !g_bNormalizeRequest)\r
-        m_scheme=pfc->fIsSecurePort ? "https" : "http";\r
-\r
-    GetServerVariable(pfc,"SERVER_NAME",var,32);\r
-\r
-    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
-    m_hostname = var;\r
-    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
-        m_hostname=site.m_name;\r
-\r
-    if (!g_spoofKey.empty()) {\r
-        GetHeader(pn, pfc, "ShibSpoofCheck:", var, 32, false);\r
-        if (!var.empty() && g_spoofKey == (char*)var)\r
-            m_firsttime = false;\r
-    }\r
-\r
-    if (!m_firsttime)\r
-        log(SPDebug, "ISAPI filter running more than once");\r
-  }\r
-  ~ShibTargetIsapiF() { }\r
-\r
-  const char* getScheme() const {\r
-    return m_scheme.c_str();\r
-  }\r
-  const char* getHostname() const {\r
-    return m_hostname.c_str();\r
-  }\r
-  int getPort() const {\r
-    return m_port;\r
-  }\r
-  const char* getQueryString() const {\r
-      const char* uri = getRequestURI();\r
-      uri = (uri ? strchr(uri, '?') : NULL);\r
-      return uri ? (uri + 1) : NULL;\r
-  }\r
-  const char* getMethod() const {\r
-    if (m_method.empty()) {\r
-        dynabuf var(5);\r
-        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);\r
-        if (!var.empty())\r
-            m_method = var;\r
-    }\r
-    return m_method.c_str();\r
-  }\r
-  string getContentType() const {\r
-    if (m_content_type.empty()) {\r
-        dynabuf var(32);\r
-        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);\r
-        if (!var.empty())\r
-            m_content_type = var;\r
-    }\r
-    return m_content_type;\r
-  }\r
-  string getRemoteAddr() const {\r
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
-    if (m_remote_addr.empty()) {\r
-        dynabuf var(16);\r
-        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);\r
-        if (!var.empty())\r
-            m_remote_addr = var;\r
-    }\r
-    return m_remote_addr;\r
-  }\r
-  void log(SPLogLevel level, const string& msg) {\r
-    AbstractSPRequest::log(level,msg);\r
-    if (level >= SPCrit)\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
-  }\r
-  string makeSafeHeader(const char* rawname) const {\r
-      string hdr;\r
-      for (; *rawname; ++rawname) {\r
-          if (isalnum(*rawname))\r
-              hdr += *rawname;\r
-      }\r
-      return (hdr + ':');\r
-  }\r
-  void clearHeader(const char* rawname, const char* cginame) {\r
-    if (g_checkSpoofing && m_firsttime) {\r
-        if (m_allhttp.empty())\r
-               GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);\r
-        string hdr = g_bSafeHeaderNames ? ("HTTP_" + makeSafeHeader(cginame + 5)) : (string(cginame) + ':');\r
-        if (strstr(m_allhttp, hdr.c_str()))\r
-            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, hdr.c_str()));\r
-    }\r
-    if (g_bSafeHeaderNames) {\r
-        string hdr = makeSafeHeader(rawname);\r
-        m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
-    }\r
-    else if (!strcmp(rawname,"REMOTE_USER")) {\r
-           m_pn->SetHeader(m_pfc, "remote-user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
-        m_pn->SetHeader(m_pfc, "remote_user:", const_cast<char*>(g_unsetHeaderValue.c_str()));\r
-       }\r
-       else {\r
-           string hdr = string(rawname) + ':';\r
-           m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(g_unsetHeaderValue.c_str()));\r
-       }\r
-  }\r
-  void setHeader(const char* name, const char* value) {\r
-    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
-    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));\r
-  }\r
-  string getSecureHeader(const char* name) const {\r
-    string hdr = g_bSafeHeaderNames ? makeSafeHeader(name) : (string(name) + ':');\r
-    dynabuf buf(256);\r
-    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
-    return string(buf.empty() ? "" : buf);\r
-  }\r
-  string getHeader(const char* name) const {\r
-    string hdr(name);\r
-    hdr += ':';\r
-    dynabuf buf(256);\r
-    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);\r
-    return string(buf.empty() ? "" : buf);\r
-  }\r
-  void setRemoteUser(const char* user) {\r
-    setHeader("remote-user", user);\r
-    if (!user || !*user)\r
-        m_pfc->pFilterContext = NULL;\r
-    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))\r
-        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);\r
-  }\r
-  string getRemoteUser() const {\r
-    return getSecureHeader("remote-user");\r
-  }\r
-  void setResponseHeader(const char* name, const char* value) {\r
-    // Set for later.\r
-    if (value)\r
-        m_headers.insert(make_pair(name,value));\r
-    else\r
-        m_headers.erase(name);\r
-  }\r
-  long sendResponse(istream& in, long status) {\r
-    string hdr = string("Connection: close\r\n");\r
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-        hdr += i->first + ": " + i->second + "\r\n";\r
-    hdr += "\r\n";\r
-    const char* codestr="200 OK";\r
-    switch (status) {\r
-        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;\r
-        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;\r
-        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;\r
-        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;\r
-    }\r
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, (void*)codestr, (DWORD)hdr.c_str(), 0);\r
-    char buf[1024];\r
-    while (in) {\r
-        in.read(buf,1024);\r
-        DWORD resplen = in.gcount();\r
-        m_pfc->WriteClient(m_pfc, buf, &resplen, 0);\r
-    }\r
-    return SF_STATUS_REQ_FINISHED;\r
-  }\r
-  long sendRedirect(const char* url) {\r
-    // XXX: Don't support the httpRedirect option, yet.\r
-    string hdr=string("Location: ") + url + "\r\n"\r
-      "Content-Type: text/html\r\n"\r
-      "Content-Length: 40\r\n"\r
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-      "Cache-Control: private,no-store,no-cache\r\n";\r
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-        hdr += i->first + ": " + i->second + "\r\n";\r
-    hdr += "\r\n";\r
-    m_pfc->ServerSupportFunction(m_pfc, SF_REQ_SEND_RESPONSE_HEADER, "302 Please Wait", (DWORD)hdr.c_str(), 0);\r
-    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
-    DWORD resplen=40;\r
-    m_pfc->WriteClient(m_pfc, (LPVOID)redmsg, &resplen, 0);\r
-    return SF_STATUS_REQ_FINISHED;\r
-  }\r
-  long returnDecline() {\r
-      return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-  }\r
-  long returnOK() {\r
-    return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-  }\r
-\r
-  const vector<string>& getClientCertificates() const {\r
-      return g_NoCerts;\r
-  }\r
-\r
-  // The filter never processes the POST, so stub these methods.\r
-  long getContentLength() const { throw IOException("The request's Content-Length is not available to an ISAPI filter."); }\r
-  const char* getRequestBody() const { throw IOException("The request body is not available to an ISAPI filter."); }\r
-};\r
-\r
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)\r
-{\r
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
-    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);\r
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"\r
-                            "<H1>Shibboleth Filter Error</H1>";\r
-    DWORD resplen=strlen(xmsg);\r
-    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);\r
-    resplen=strlen(msg);\r
-    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);\r
-    static const char* xmsg2="</BODY></HTML>";\r
-    resplen=strlen(xmsg2);\r
-    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);\r
-    return SF_STATUS_REQ_FINISHED;\r
-}\r
-\r
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)\r
-{\r
-    // Is this a log notification?\r
-    if (notificationType==SF_NOTIFY_LOG) {\r
-        if (pfc->pFilterContext)\r
-               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=reinterpret_cast<char*>(pfc->pFilterContext);\r
-        return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-    }\r
-\r
-    PHTTP_FILTER_PREPROC_HEADERS pn=(PHTTP_FILTER_PREPROC_HEADERS)pvNotification;\r
-    try\r
-    {\r
-        // Determine web site number. This can't really fail, I don't think.\r
-        dynabuf buf(128);\r
-        GetServerVariable(pfc,"INSTANCE_ID",buf,10);\r
-\r
-        // Match site instance to host name, skip if no match.\r
-        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
-        if (map_i==g_Sites.end())\r
-            return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-\r
-        ostringstream threadid;\r
-        threadid << "[" << getpid() << "] isapi_shib" << '\0';\r
-        xmltooling::NDC ndc(threadid.str().c_str());\r
-\r
-        ShibTargetIsapiF stf(pfc, pn, map_i->second);\r
-\r
-        // "false" because we don't override the Shib settings\r
-        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);\r
-        if (!g_spoofKey.empty())\r
-            pn->SetHeader(pfc, "ShibSpoofCheck:", const_cast<char*>(g_spoofKey.c_str()));\r
-        if (res.first) return res.second;\r
-\r
-        // "false" because we don't override the Shib settings\r
-        res = stf.getServiceProvider().doExport(stf);\r
-        if (res.first) return res.second;\r
-\r
-        res = stf.getServiceProvider().doAuthorization(stf);\r
-        if (res.first) return res.second;\r
-\r
-        return SF_STATUS_REQ_NEXT_NOTIFICATION;\r
-    }\r
-    catch(bad_alloc) {\r
-        return WriteClientError(pfc,"Out of Memory");\r
-    }\r
-    catch(long e) {\r
-        if (e==ERROR_NO_DATA)\r
-            return WriteClientError(pfc,"A required variable or header was empty.");\r
-        else\r
-            return WriteClientError(pfc,"Shibboleth Filter detected unexpected IIS error.");\r
-    }\r
-    catch (exception& e) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
-        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");\r
-    }\r
-    catch(...) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw an unknown exception.");\r
-        if (g_catchAll)\r
-            return WriteClientError(pfc,"Shibboleth Filter threw an unknown exception.");\r
-        throw;\r
-    }\r
-\r
-    return WriteClientError(pfc,"Shibboleth Filter reached unreachable code, save my walrus!");\r
-}\r
-\r
-\r
-/****************************************************************************/\r
-// ISAPI Extension\r
-\r
-DWORD WriteClientError(LPEXTENSION_CONTROL_BLOCK lpECB, const char* msg)\r
-{\r
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);\r
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";\r
-    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);\r
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";\r
-    DWORD resplen=strlen(xmsg);\r
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);\r
-    resplen=strlen(msg);\r
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);\r
-    static const char* xmsg2="</BODY></HTML>";\r
-    resplen=strlen(xmsg2);\r
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg2,&resplen,HSE_IO_SYNC);\r
-    return HSE_STATUS_SUCCESS;\r
-}\r
-\r
-\r
-class ShibTargetIsapiE : public AbstractSPRequest\r
-{\r
-  LPEXTENSION_CONTROL_BLOCK m_lpECB;\r
-  multimap<string,string> m_headers;\r
-  mutable vector<string> m_certs;\r
-  mutable string m_body;\r
-  mutable bool m_gotBody;\r
-  int m_port;\r
-  string m_scheme,m_hostname,m_uri;\r
-  mutable string m_remote_addr,m_remote_user;\r
-\r
-public:\r
-  ShibTargetIsapiE(LPEXTENSION_CONTROL_BLOCK lpECB, const site_t& site)\r
-      : AbstractSPRequest(SHIBSP_LOGCAT".ISAPI"), m_lpECB(lpECB), m_gotBody(false) {\r
-    dynabuf ssl(5);\r
-    GetServerVariable(lpECB,"HTTPS",ssl,5);\r
-    bool SSL=(ssl=="on" || ssl=="ON");\r
-\r
-    // Scheme may come from site def or be derived from IIS.\r
-    m_scheme=site.m_scheme;\r
-    if (m_scheme.empty() || !g_bNormalizeRequest)\r
-        m_scheme = SSL ? "https" : "http";\r
-\r
-    // URL path always come from IIS.\r
-    dynabuf url(256);\r
-    GetServerVariable(lpECB,"URL",url,255);\r
-\r
-    // Port may come from IIS or from site def.\r
-    dynabuf port(11);\r
-    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))\r
-        GetServerVariable(lpECB,"SERVER_PORT",port,10);\r
-    else if (SSL) {\r
-        strncpy(port,site.m_sslport.c_str(),10);\r
-        static_cast<char*>(port)[10]=0;\r
-    }\r
-    else {\r
-        strncpy(port,site.m_port.c_str(),10);\r
-        static_cast<char*>(port)[10]=0;\r
-    }\r
-    m_port = atoi(port);\r
-\r
-    dynabuf var(32);\r
-    GetServerVariable(lpECB, "SERVER_NAME", var, 32);\r
-\r
-    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.\r
-    m_hostname=var;\r
-    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())\r
-        m_hostname=site.m_name;\r
-\r
-    /*\r
-     * IIS screws us over on PATH_INFO (the hits keep on coming). We need to figure out if\r
-     * the server is set up for proper PATH_INFO handling, or "IIS sucks rabid weasels mode",\r
-     * which is the default. No perfect way to tell, but we can take a good guess by checking\r
-     * whether the URL is a substring of the PATH_INFO:\r
-     *\r
-     * e.g. for /Shibboleth.sso/SAML/POST\r
-     *\r
-     *  Bad mode (default):\r
-     *      URL:        /Shibboleth.sso\r
-     *      PathInfo:   /Shibboleth.sso/SAML/POST\r
-     *\r
-     *  Good mode:\r
-     *      URL:        /Shibboleth.sso\r
-     *      PathInfo:   /SAML/POST\r
-     */\r
-\r
-    string uri;\r
-\r
-    // Clearly we're only in bad mode if path info exists at all.\r
-    if (lpECB->lpszPathInfo && *(lpECB->lpszPathInfo)) {\r
-        if (strstr(lpECB->lpszPathInfo,url))\r
-            // Pretty good chance we're in bad mode, unless the PathInfo repeats the path itself.\r
-            uri = lpECB->lpszPathInfo;\r
-        else {\r
-            uri = url;\r
-            uri += lpECB->lpszPathInfo;\r
-        }\r
-    }\r
-    else {\r
-        uri = url;\r
-    }\r
-\r
-    // For consistency with Apache, let's add the query string.\r
-    if (lpECB->lpszQueryString && *(lpECB->lpszQueryString)) {\r
-        uri += '?';\r
-        uri += lpECB->lpszQueryString;\r
-    }\r
-\r
-    setRequestURI(uri.c_str());\r
-  }\r
-  ~ShibTargetIsapiE() { }\r
-\r
-  const char* getScheme() const {\r
-    return m_scheme.c_str();\r
-  }\r
-  const char* getHostname() const {\r
-    return m_hostname.c_str();\r
-  }\r
-  int getPort() const {\r
-    return m_port;\r
-  }\r
-  const char* getMethod() const {\r
-    return m_lpECB->lpszMethod;\r
-  }\r
-  string getContentType() const {\r
-    return m_lpECB->lpszContentType ? m_lpECB->lpszContentType : "";\r
-  }\r
-  long getContentLength() const {\r
-      return m_lpECB->cbTotalBytes;\r
-  }\r
-  string getRemoteUser() const {\r
-    if (m_remote_user.empty()) {\r
-        dynabuf var(16);\r
-        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);\r
-        if (!var.empty())\r
-            m_remote_user = var;\r
-    }\r
-    return m_remote_user;\r
-  }\r
-  string getRemoteAddr() const {\r
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();\r
-    if (m_remote_addr.empty()) {\r
-        dynabuf var(16);\r
-        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);\r
-        if (!var.empty())\r
-            m_remote_addr = var;\r
-    }\r
-    return m_remote_addr;\r
-  }\r
-  void log(SPLogLevel level, const string& msg) const {\r
-      AbstractSPRequest::log(level,msg);\r
-      if (level >= SPCrit)\r
-          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());\r
-  }\r
-  string getHeader(const char* name) const {\r
-    string hdr("HTTP_");\r
-    for (; *name; ++name) {\r
-        if (*name=='-')\r
-            hdr += '_';\r
-        else\r
-            hdr += toupper(*name);\r
-    }\r
-    dynabuf buf(128);\r
-    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);\r
-    return buf.empty() ? "" : buf;\r
-  }\r
-  void setResponseHeader(const char* name, const char* value) {\r
-    // Set for later.\r
-    if (value)\r
-        m_headers.insert(make_pair(name,value));\r
-    else\r
-        m_headers.erase(name);\r
-  }\r
-  const char* getQueryString() const {\r
-    return m_lpECB->lpszQueryString;\r
-  }\r
-  const char* getRequestBody() const {\r
-    if (m_gotBody)\r
-        return m_body.c_str();\r
-    if (m_lpECB->cbTotalBytes > 1024*1024) // 1MB?\r
-        throw opensaml::SecurityPolicyException("Size of request body exceeded 1M size limit.");\r
-    else if (m_lpECB->cbTotalBytes > m_lpECB->cbAvailable) {\r
-      m_gotBody=true;\r
-      DWORD datalen=m_lpECB->cbTotalBytes;\r
-      if (m_lpECB->cbAvailable > 0) {\r
-        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
-        datalen-=m_lpECB->cbAvailable;\r
-      }\r
-      char buf[8192];\r
-      while (datalen) {\r
-        DWORD buflen=8192;\r
-        BOOL ret = m_lpECB->ReadClient(m_lpECB->ConnID, buf, &buflen);\r
-        if (!ret)\r
-            throw IOException("Error reading request body from browser.");\r
-        else if (!buflen)\r
-            throw IOException("Socket closed while reading request body from browser.");\r
-        m_body.append(buf, buflen);\r
-        datalen-=buflen;\r
-      }\r
-    }\r
-    else if (m_lpECB->cbAvailable) {\r
-        m_gotBody=true;\r
-        m_body.assign(reinterpret_cast<char*>(m_lpECB->lpbData),m_lpECB->cbAvailable);\r
-    }\r
-    return m_body.c_str();\r
-  }\r
-  long sendResponse(istream& in, long status) {\r
-    string hdr = string("Connection: close\r\n");\r
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-        hdr += i->first + ": " + i->second + "\r\n";\r
-    hdr += "\r\n";\r
-    const char* codestr="200 OK";\r
-    switch (status) {\r
-        case XMLTOOLING_HTTP_STATUS_UNAUTHORIZED:   codestr="401 Authorization Required"; break;\r
-        case XMLTOOLING_HTTP_STATUS_FORBIDDEN:      codestr="403 Forbidden"; break;\r
-        case XMLTOOLING_HTTP_STATUS_NOTFOUND:       codestr="404 Not Found"; break;\r
-        case XMLTOOLING_HTTP_STATUS_ERROR:          codestr="500 Server Error"; break;\r
-    }\r
-    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 0, (LPDWORD)hdr.c_str());\r
-    char buf[1024];\r
-    while (in) {\r
-        in.read(buf,1024);\r
-        DWORD resplen = in.gcount();\r
-        m_lpECB->WriteClient(m_lpECB->ConnID, buf, &resplen, HSE_IO_SYNC);\r
-    }\r
-    return HSE_STATUS_SUCCESS;\r
-  }\r
-  long sendRedirect(const char* url) {\r
-    string hdr=string("Location: ") + url + "\r\n"\r
-      "Content-Type: text/html\r\n"\r
-      "Content-Length: 40\r\n"\r
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"\r
-      "Cache-Control: private,no-store,no-cache\r\n";\r
-    for (multimap<string,string>::const_iterator i=m_headers.begin(); i!=m_headers.end(); ++i)\r
-        hdr += i->first + ": " + i->second + "\r\n";\r
-    hdr += "\r\n";\r
-    m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, "302 Moved", 0, (LPDWORD)hdr.c_str());\r
-    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";\r
-    DWORD resplen=40;\r
-    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);\r
-    return HSE_STATUS_SUCCESS;\r
-  }\r
-  // Decline happens in the POST processor if this isn't the shire url\r
-  // Note that it can also happen with HTAccess, but we don't support that, yet.\r
-  long returnDecline() {\r
-    return WriteClientError(\r
-        m_lpECB,\r
-        "ISAPI extension can only be invoked to process Shibboleth protocol requests."\r
-               "Make sure the mapped file extension doesn't match actual content."\r
-        );\r
-  }\r
-  long returnOK() {\r
-      return HSE_STATUS_SUCCESS;\r
-  }\r
-\r
-  const vector<string>& getClientCertificates() const {\r
-      if (m_certs.empty()) {\r
-        char CertificateBuf[8192];\r
-        CERT_CONTEXT_EX ccex;\r
-        ccex.cbAllocated = sizeof(CertificateBuf);\r
-        ccex.CertContext.pbCertEncoded = (BYTE*)CertificateBuf;\r
-        DWORD dwSize = sizeof(ccex);\r
-\r
-        if (m_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_GET_CERT_INFO_EX, (LPVOID)&ccex, (LPDWORD)dwSize, NULL)) {\r
-            if (ccex.CertContext.cbCertEncoded) {\r
-                xsecsize_t outlen;\r
-                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);\r
-                m_certs.push_back(reinterpret_cast<char*>(serialized));\r
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE\r
-                XMLString::release(&serialized);\r
-#else\r
-                XMLString::release((char**)&serialized);\r
-#endif\r
-            }\r
-        }\r
-      }\r
-      return m_certs;\r
-  }\r
-\r
-  // Not used in the extension.\r
-  void clearHeader(const char* rawname, const char* cginame) { throw runtime_error("clearHeader not implemented"); }\r
-  void setHeader(const char* name, const char* value) { throw runtime_error("setHeader not implemented"); }\r
-  void setRemoteUser(const char* user) { throw runtime_error("setRemoteUser not implemented"); }\r
-};\r
-\r
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)\r
-{\r
-    try {\r
-        ostringstream threadid;\r
-        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';\r
-        xmltooling::NDC ndc(threadid.str().c_str());\r
-\r
-        // Determine web site number. This can't really fail, I don't think.\r
-        dynabuf buf(128);\r
-        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);\r
-\r
-        // Match site instance to host name, skip if no match.\r
-        map<string,site_t>::const_iterator map_i=g_Sites.find(static_cast<char*>(buf));\r
-        if (map_i==g_Sites.end())\r
-            return WriteClientError(lpECB, "Shibboleth Extension not configured for web site (check <ISAPI> mappings in configuration).");\r
-\r
-        ShibTargetIsapiE ste(lpECB, map_i->second);\r
-        pair<bool,long> res = ste.getServiceProvider().doHandler(ste);\r
-        if (res.first) return res.second;\r
-\r
-        return WriteClientError(lpECB, "Shibboleth Extension failed to process request");\r
-\r
-    }\r
-    catch(bad_alloc) {\r
-        return WriteClientError(lpECB,"Out of Memory");\r
-    }\r
-    catch(long e) {\r
-        if (e==ERROR_NO_DATA)\r
-            return WriteClientError(lpECB,"A required variable or header was empty.");\r
-        else\r
-            return WriteClientError(lpECB,"Server detected unexpected IIS error.");\r
-    }\r
-    catch (exception& e) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());\r
-        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");\r
-    }\r
-    catch(...) {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw an unknown exception.");\r
-        if (g_catchAll)\r
-            return WriteClientError(lpECB,"Shibboleth Extension threw an unknown exception.");\r
-        throw;\r
-    }\r
-\r
-    // If we get here we've got an error.\r
-    return HSE_STATUS_ERROR;\r
-}\r
diff --git a/isapi_shib/isapi_shib.cpp.r3059 b/isapi_shib/isapi_shib.cpp.r3059
deleted file mode 100644 (file)
index 73fb7a0..0000000
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- *  Copyright 2001-2009 Internet2
- *
- * Licensed 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
-
-#include <shibsp/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-// 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 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)
-        {
-            auto_ptr_char n(e->getAttributeNS(NULL,name));
-            auto_ptr_char s(e->getAttributeNS(NULL,scheme));
-            auto_ptr_char p(e->getAttributeNS(NULL,port));
-            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
-            if (n.get()) m_name=n.get();
-            if (s.get()) m_scheme=s.get();
-            if (p.get()) m_port=p.get();
-            if (p2.get()) m_sslport=p2.get();
-            e = XMLHelper::getFirstChildElement(e, Alias);
-            while (e) {
-                if (e->hasChildNodes()) {
-                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());
-                    m_aliases.insert(alias.get());
-                }
-                e = XMLHelper::getNextSiblingElement(e, Alias);
-            }
-        }
-        string m_scheme,m_port,m_sslport,m_name;
-        set<string> m_aliases;
-    };
-
-    struct context_t {
-       char* m_user;
-       bool m_checked;
-    };
-
-    HINSTANCE g_hinstDLL;
-    SPConfig* g_Config = NULL;
-    map<string,site_t> g_Sites;
-    bool g_bNormalizeRequest = true;
-    string g_unsetHeaderValue;
-    bool g_checkSpoofing = true;
-    bool g_catchAll = false;
-    vector<string> g_NoCerts;
-}
-
-BOOL LogEvent(
-    LPCSTR  lpUNCServerName,
-    WORD  wType,
-    DWORD  dwEventID,
-    PSID  lpUserSid,
-    LPCSTR  message)
-{
-    LPCSTR  messages[] = {message, NULL};
-
-    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
-    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
-    return (DeregisterEventSource(hElog) && res);
-}
-
-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) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "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)
-{
-    if (!pVer)
-        return FALSE;
-    else if (g_Config) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Reentrant filter initialization, ignoring...");
-        return TRUE;
-    }
-
-    g_Config=&SPConfig::getConfig();
-    g_Config->setFeatures(
-        SPConfig::Listener |
-        SPConfig::Caching |
-        SPConfig::RequestMapping |
-        SPConfig::InProcess |
-        SPConfig::Logging |
-        SPConfig::Handlers
-        );
-    if (!g_Config->init()) {
-        g_Config=NULL;
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Filter startup failed during library initialization, check native log for help.");
-        return FALSE;
-    }
-
-    try {
-        if (!g_Config->instantiate(NULL, true))
-            throw runtime_error("unknown error");
-    }
-    catch (exception& ex) {
-        g_Config->term();
-        g_Config=NULL;
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Filter startup failed to load configuration, check native log for details.");
-        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,const char*> unsetValue=props->getString("unsetHeaderValue");
-        if (unsetValue.first)
-            g_unsetHeaderValue = unsetValue.second;
-        pair<bool,bool> flag=props->getBool("checkSpoofing");
-        g_checkSpoofing = !flag.first || flag.second;
-        flag=props->getBool("catchAll");
-        g_catchAll = flag.first && flag.second;
-
-        props = props->getPropertySet("ISAPI");
-        if (props) {
-            flag = props->getBool("normalizeRequest");
-            g_bNormalizeRequest = !flag.first || flag.second;
-            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
-            while (child) {
-                auto_ptr_char id(child->getAttributeNS(NULL,id));
-                if (id.get())
-                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
-                child=XMLHelper::getNextSiblingElement(child,Site);
-            }
-        }
-    }
-
-    pVer->dwFilterVersion=HTTP_FILTER_REVISION;
-    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
-    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
-                   SF_NOTIFY_SECURE_PORT |
-                   SF_NOTIFY_NONSECURE_PORT |
-                   SF_NOTIFY_PREPROC_HEADERS |
-                   SF_NOTIFY_LOG);
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
-    return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
-    if (g_Config)
-        g_Config->term();
-    g_Config = NULL;
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut 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=NULL; 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==NULL || s==NULL)
-        return (buflen==NULL && s==NULL);
-    else
-        return strcmp(bufptr,s)==0;
-}
-
-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())
-        throw ERROR_NO_DATA;
-}
-
-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())
-        throw ERROR_NO_DATA;
-}
-
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
-               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!pn->GetHeader(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())
-        throw ERROR_NO_DATA;
-}
-
-/****************************************************************************/
-// 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;
-
-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) {
-
-    // URL path always come from IIS.
-    dynabuf var(256);
-    GetHeader(pn,pfc,"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(pfc,"SERVER_PORT",var,10);
-        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(pfc,"SERVER_NAME",var,32);
-
-    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
-    m_hostname = var;
-    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
-        m_hostname=site.m_name;
-
-    if (!pfc->pFilterContext) {
-        pfc->pFilterContext = pfc->AllocMem(pfc, sizeof(context_t), NULL);
-        if (static_cast<context_t*>(pfc->pFilterContext)) {
-            static_cast<context_t*>(pfc->pFilterContext)->m_user = NULL;
-            static_cast<context_t*>(pfc->pFilterContext)->m_checked = false;
-        }
-    }
-  }
-  ~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, '?') : NULL);
-      return uri ? (uri + 1) : NULL;
-  }
-  const char* getMethod() const {
-    if (m_method.empty()) {
-        dynabuf var(5);
-        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
-        if (!var.empty())
-            m_method = var;
-    }
-    return m_method.c_str();
-  }
-  string getContentType() const {
-    if (m_content_type.empty()) {
-        dynabuf var(32);
-        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
-        if (!var.empty())
-            m_content_type = var;
-    }
-    return m_content_type;
-  }
-  string getRemoteAddr() const {
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  void log(SPLogLevel level, const string& msg) {
-    AbstractSPRequest::log(level,msg);
-    if (level >= SPError)
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
-  }
-  void clearHeader(const char* rawname, const char* cginame) {
-       if (g_checkSpoofing && m_pfc->pFilterContext && !static_cast<context_t*>(m_pfc->pFilterContext)->m_checked) {
-        if (m_allhttp.empty())
-               GetServerVariable(m_pfc,"ALL_HTTP",m_allhttp,4096);
-        if (strstr(m_allhttp, cginame))
-            throw opensaml::SecurityPolicyException("Attempt to spoof header ($1) was detected.", params(1, rawname));
-    }
-    string hdr(!strcmp(rawname,"REMOTE_USER") ? "remote-user" : rawname);
-    hdr += ':';
-    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(name);
-    hdr += ':';
-    m_pn->SetHeader(m_pfc, const_cast<char*>(hdr.c_str()), const_cast<char*>(value));
-  }
-  string getHeader(const char* name) const {
-    string hdr(name);
-    hdr += ':';
-    dynabuf buf(256);
-    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf);
-  }
-  void setRemoteUser(const char* user) {
-    setHeader("remote-user", user);
-    if (m_pfc->pFilterContext) {
-        if (!user || !*user)
-            static_cast<context_t*>(m_pfc->pFilterContext)->m_user = NULL;
-        else if (static_cast<context_t*>(m_pfc->pFilterContext)->m_user = (char*)m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
-            strcpy(static_cast<context_t*>(m_pfc->pFilterContext)->m_user, user);
-    }
-  }
-  string getRemoteUser() const {
-    return getHeader("remote-user");
-  }
-  void setResponseHeader(const char* name, const char* value) {
-    // Set for later.
-    if (value)
-        m_headers.insert(make_pair(name,value));
-    else
-        m_headers.erase(name);
-  }
-  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_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, (DWORD)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) {
-    // XXX: Don't support the httpRedirect option, yet.
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "Content-Length: 40\r\n"
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\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, "302 Please Wait", (DWORD)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."); }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
-                            "<H1>Shibboleth Filter Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
-    resplen=strlen(msg);
-    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
-    static const char* xmsg2="</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
-    return SF_STATUS_REQ_FINISHED;
-}
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
-    // Is this a log notification?
-    if (notificationType==SF_NOTIFY_LOG) {
-        if (pfc->pFilterContext && static_cast<context_t*>(pfc->pFilterContext)->m_user)
-               ((PHTTP_FILTER_LOG)pvNotification)->pszClientUserName=static_cast<context_t*>(pfc->pFilterContext)->m_user;
-        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);
-
-        // 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;
-
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
-
-        ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
-        // "false" because we don't override the Shib settings
-        pair<bool,long> res = stf.getServiceProvider().doAuthentication(stf);
-        if (pfc->pFilterContext)
-            static_cast<context_t*>(pfc->pFilterContext)->m_checked = true;
-        if (res.first) return res.second;
-
-        // "false" because we don't override the Shib settings
-        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(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 (exception& e) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
-        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
-    }
-    catch(...) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw 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)
-{
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
-    resplen=strlen(msg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
-    static const char* xmsg2="</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)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) {
-    dynabuf ssl(5);
-    GetServerVariable(lpECB,"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(lpECB,"URL",url,255);
-
-    // Port may come from IIS or from site def.
-    dynabuf port(11);
-    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
-        GetServerVariable(lpECB,"SERVER_PORT",port,10);
-    else if (SSL) {
-        strncpy(port,site.m_sslport.c_str(),10);
-        static_cast<char*>(port)[10]=0;
-    }
-    else {
-        strncpy(port,site.m_port.c_str(),10);
-        static_cast<char*>(port)[10]=0;
-    }
-    m_port = atoi(port);
-
-    dynabuf var(32);
-    GetServerVariable(lpECB, "SERVER_NAME", var, 32);
-
-    // 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 {
-            uri = url;
-            uri += lpECB->lpszPathInfo;
-        }
-    }
-    else {
-        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 {
-    if (m_remote_user.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
-        if (!var.empty())
-            m_remote_user = var;
-    }
-    return m_remote_user;
-  }
-  string getRemoteAddr() const {
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  void log(SPLogLevel level, const string& msg) const {
-      AbstractSPRequest::log(level,msg);
-      if (level >= SPError)
-          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
-  }
-  string getHeader(const char* name) const {
-    string hdr("HTTP_");
-    for (; *name; ++name) {
-        if (*name=='-')
-            hdr += '_';
-        else
-            hdr += toupper(*name);
-    }
-    dynabuf buf(128);
-    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
-    return buf.empty() ? "" : buf;
-  }
-  void setResponseHeader(const char* name, const char* value) {
-    // Set for later.
-    if (value)
-        m_headers.insert(make_pair(name,value));
-    else
-        m_headers.erase(name);
-  }
-  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)
-            throw IOException("Error reading request body from browser.");
-        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";
-    const char* codestr="200 OK";
-    switch (status) {
-        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_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 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) {
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "Content-Length: 40\r\n"
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\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, "302 Moved", 0, (LPDWORD)hdr.c_str());
-    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
-    DWORD resplen=40;
-    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
-    return HSE_STATUS_SUCCESS;
-  }
-  // Decline happens in the POST processor if this isn't the shire url
-  // 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, NULL)) {
-            if (ccex.CertContext.cbCertEncoded) {
-                xsecsize_t outlen;
-                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
-                m_certs.push_back(reinterpret_cast<char*>(serialized));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
-                XMLString::release(&serialized);
-#else
-                XMLString::release((char**)&serialized);
-#endif
-            }
-        }
-      }
-      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"); }
-};
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
-    try {
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
-
-        // Determine web site number. This can't really fail, I don't think.
-        dynabuf buf(128);
-        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
-
-        // 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 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(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 (exception& e) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
-        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
-    }
-    catch(...) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw 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.cpp.r3097 b/isapi_shib/isapi_shib.cpp.r3097
deleted file mode 100644 (file)
index 2a1130d..0000000
+++ /dev/null
@@ -1,1008 +0,0 @@
-/*
- *  Copyright 2001-2009 Internet2
- *
- * Licensed 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/AbstractSPRequest.h>
-#include <shibsp/SPConfig.h>
-#include <shibsp/ServiceProvider.h>
-#include <xmltooling/unicode.h>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/XMLConstants.h>
-#include <xmltooling/util/XMLHelper.h>
-#include <xercesc/util/Base64.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
-#include <set>
-#include <sstream>
-#include <fstream>
-#include <stdexcept>
-#include <process.h>
-
-#include <windows.h>
-#include <httpfilt.h>
-#include <httpext.h>
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-// 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 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)
-        {
-            auto_ptr_char n(e->getAttributeNS(NULL,name));
-            auto_ptr_char s(e->getAttributeNS(NULL,scheme));
-            auto_ptr_char p(e->getAttributeNS(NULL,port));
-            auto_ptr_char p2(e->getAttributeNS(NULL,sslport));
-            if (n.get()) m_name=n.get();
-            if (s.get()) m_scheme=s.get();
-            if (p.get()) m_port=p.get();
-            if (p2.get()) m_sslport=p2.get();
-            e = XMLHelper::getFirstChildElement(e, Alias);
-            while (e) {
-                if (e->hasChildNodes()) {
-                    auto_ptr_char alias(e->getFirstChild()->getNodeValue());
-                    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 = NULL;
-    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;
-}
-
-BOOL LogEvent(
-    LPCSTR  lpUNCServerName,
-    WORD  wType,
-    DWORD  dwEventID,
-    PSID  lpUserSid,
-    LPCSTR  message)
-{
-    LPCSTR  messages[] = {message, NULL};
-
-    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth ISAPI Filter");
-    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
-    return (DeregisterEventSource(hElog) && res);
-}
-
-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) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "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)
-{
-    if (!pVer)
-        return FALSE;
-    else if (g_Config) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Reentrant filter initialization, ignoring...");
-        return TRUE;
-    }
-
-    g_Config=&SPConfig::getConfig();
-    g_Config->setFeatures(
-        SPConfig::Listener |
-        SPConfig::Caching |
-        SPConfig::RequestMapping |
-        SPConfig::InProcess |
-        SPConfig::Logging |
-        SPConfig::Handlers
-        );
-    if (!g_Config->init()) {
-        g_Config=NULL;
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Filter startup failed during library initialization, check native log for help.");
-        return FALSE;
-    }
-
-    try {
-        if (!g_Config->instantiate(NULL, true))
-            throw runtime_error("unknown error");
-    }
-    catch (exception& ex) {
-        g_Config->term();
-        g_Config=NULL;
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, ex.what());
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                "Filter startup failed to load configuration, check native log for details.");
-        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);
-                    ostringstream keystr;
-                    keystr << randkey << randkey2 << randkey3 << randkey4;
-                    g_spoofKey = keystr.str();
-                }
-                else {
-                    _set_invalid_parameter_handler(old);
-                    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL,
-                            "Filter failed to generate a random anti-spoofing key (if this is Windows 2000 set one manually).");
-                    locker.assign();    // pops lock on SP config
-                    g_Config->term();
-                    g_Config=NULL;
-                    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;
-            const DOMElement* child = XMLHelper::getFirstChildElement(props->getElement(),Site);
-            while (child) {
-                auto_ptr_char id(child->getAttributeNS(NULL,id));
-                if (id.get())
-                    g_Sites.insert(pair<string,site_t>(id.get(),site_t(child)));
-                child=XMLHelper::getNextSiblingElement(child,Site);
-            }
-        }
-    }
-
-    pVer->dwFilterVersion=HTTP_FILTER_REVISION;
-    strncpy(pVer->lpszFilterDesc,"Shibboleth ISAPI Filter",SF_MAX_FILTER_DESC_LEN);
-    pVer->dwFlags=(SF_NOTIFY_ORDER_HIGH |
-                   SF_NOTIFY_SECURE_PORT |
-                   SF_NOTIFY_NONSECURE_PORT |
-                   SF_NOTIFY_PREPROC_HEADERS |
-                   SF_NOTIFY_LOG);
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter initialized...");
-    return TRUE;
-}
-
-extern "C" BOOL WINAPI TerminateFilter(DWORD)
-{
-    if (g_Config)
-        g_Config->term();
-    g_Config = NULL;
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "Filter shut 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=NULL; 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==NULL || s==NULL)
-        return (buflen==NULL && s==NULL);
-    else
-        return strcmp(bufptr,s)==0;
-}
-
-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())
-        throw ERROR_NO_DATA;
-}
-
-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())
-        throw ERROR_NO_DATA;
-}
-
-void GetHeader(PHTTP_FILTER_PREPROC_HEADERS pn, PHTTP_FILTER_CONTEXT pfc,
-               LPSTR lpszName, dynabuf& s, DWORD size=80, bool bRequired=true)
-{
-    s.reserve(size);
-    s.erase();
-    size=s.size();
-
-    while (!pn->GetHeader(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())
-        throw ERROR_NO_DATA;
-}
-
-/****************************************************************************/
-// 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) {
-
-    // URL path always come from IIS.
-    dynabuf var(256);
-    GetHeader(pn,pfc,"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(pfc,"SERVER_PORT",var,10);
-        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(pfc,"SERVER_NAME",var,32);
-
-    // Make sure SERVER_NAME is "authorized" for use on this site. If not, set to canonical name.
-    m_hostname = var;
-    if (site.m_name!=m_hostname && site.m_aliases.find(m_hostname)==site.m_aliases.end())
-        m_hostname=site.m_name;
-
-    if (!g_spoofKey.empty()) {
-        GetHeader(pn, pfc, "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, '?') : NULL);
-      return uri ? (uri + 1) : NULL;
-  }
-  const char* getMethod() const {
-    if (m_method.empty()) {
-        dynabuf var(5);
-        GetServerVariable(m_pfc,"HTTP_METHOD",var,5,false);
-        if (!var.empty())
-            m_method = var;
-    }
-    return m_method.c_str();
-  }
-  string getContentType() const {
-    if (m_content_type.empty()) {
-        dynabuf var(32);
-        GetServerVariable(m_pfc,"HTTP_CONTENT_TYPE",var,32,false);
-        if (!var.empty())
-            m_content_type = var;
-    }
-    return m_content_type;
-  }
-  string getRemoteAddr() const {
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_pfc,"REMOTE_ADDR",var,16,false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  void log(SPLogLevel level, const string& msg) {
-    AbstractSPRequest::log(level,msg);
-    if (level >= SPCrit)
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
-  }
-  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) {
-    if (g_checkSpoofing && m_firsttime) {
-        if (m_allhttp.empty())
-               GetServerVariable(m_pfc, "ALL_HTTP", m_allhttp, 4096);
-        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_user:", 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(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf.empty() ? "" : buf);
-  }
-  string getHeader(const char* name) const {
-    string hdr(name);
-    hdr += ':';
-    dynabuf buf(256);
-    GetHeader(m_pn, m_pfc, const_cast<char*>(hdr.c_str()), buf, 256, false);
-    return string(buf.empty() ? "" : buf);
-  }
-  void setRemoteUser(const char* user) {
-    setHeader("remote-user", user);
-    if (!user || !*user)
-        m_pfc->pFilterContext = NULL;
-    else if (m_pfc->pFilterContext = m_pfc->AllocMem(m_pfc, sizeof(char) * (strlen(user) + 1), NULL))
-        strcpy(reinterpret_cast<char*>(m_pfc->pFilterContext), user);
-  }
-  string getRemoteUser() const {
-    return getSecureHeader("remote-user");
-  }
-  void setResponseHeader(const char* name, const char* value) {
-    // Set for later.
-    if (value)
-        m_headers.insert(make_pair(name,value));
-    else
-        m_headers.erase(name);
-  }
-  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_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, (DWORD)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) {
-    // XXX: Don't support the httpRedirect option, yet.
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "Content-Length: 40\r\n"
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\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, "302 Please Wait", (DWORD)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."); }
-};
-
-DWORD WriteClientError(PHTTP_FILTER_CONTEXT pfc, const char* msg)
-{
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    pfc->ServerSupportFunction(pfc,SF_REQ_SEND_RESPONSE_HEADER,"200 OK",(DWORD)ctype,0);
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Filter Error</TITLE></HEAD><BODY>"
-                            "<H1>Shibboleth Filter Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    pfc->WriteClient(pfc,(LPVOID)xmsg,&resplen,0);
-    resplen=strlen(msg);
-    pfc->WriteClient(pfc,(LPVOID)msg,&resplen,0);
-    static const char* xmsg2="</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    pfc->WriteClient(pfc,(LPVOID)xmsg2,&resplen,0);
-    return SF_STATUS_REQ_FINISHED;
-}
-
-extern "C" DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc, DWORD notificationType, LPVOID pvNotification)
-{
-    // 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);
-
-        // 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;
-
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
-
-        ShibTargetIsapiF stf(pfc, pn, map_i->second);
-
-        // "false" because we don't override the Shib settings
-        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;
-
-        // "false" because we don't override the Shib settings
-        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(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 (exception& e) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
-        return WriteClientError(pfc,"Shibboleth Filter caught an exception, check Event Log for details.");
-    }
-    catch(...) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Filter threw 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)
-{
-    LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg);
-    static const char* ctype="Connection: close\r\nContent-Type: text/html\r\n\r\n";
-    lpECB->ServerSupportFunction(lpECB->ConnID,HSE_REQ_SEND_RESPONSE_HEADER,"200 OK",0,(LPDWORD)ctype);
-    static const char* xmsg="<HTML><HEAD><TITLE>Shibboleth Error</TITLE></HEAD><BODY><H1>Shibboleth Error</H1>";
-    DWORD resplen=strlen(xmsg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)xmsg,&resplen,HSE_IO_SYNC);
-    resplen=strlen(msg);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)msg,&resplen,HSE_IO_SYNC);
-    static const char* xmsg2="</BODY></HTML>";
-    resplen=strlen(xmsg2);
-    lpECB->WriteClient(lpECB->ConnID,(LPVOID)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) {
-    dynabuf ssl(5);
-    GetServerVariable(lpECB,"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(lpECB,"URL",url,255);
-
-    // Port may come from IIS or from site def.
-    dynabuf port(11);
-    if (!g_bNormalizeRequest || (SSL && site.m_sslport.empty()) || (!SSL && site.m_port.empty()))
-        GetServerVariable(lpECB,"SERVER_PORT",port,10);
-    else if (SSL) {
-        strncpy(port,site.m_sslport.c_str(),10);
-        static_cast<char*>(port)[10]=0;
-    }
-    else {
-        strncpy(port,site.m_port.c_str(),10);
-        static_cast<char*>(port)[10]=0;
-    }
-    m_port = atoi(port);
-
-    dynabuf var(32);
-    GetServerVariable(lpECB, "SERVER_NAME", var, 32);
-
-    // 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 {
-            uri = url;
-            uri += lpECB->lpszPathInfo;
-        }
-    }
-    else {
-        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 {
-    if (m_remote_user.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_lpECB, "REMOTE_USER", var, 32, false);
-        if (!var.empty())
-            m_remote_user = var;
-    }
-    return m_remote_user;
-  }
-  string getRemoteAddr() const {
-    m_remote_addr = AbstractSPRequest::getRemoteAddr();
-    if (m_remote_addr.empty()) {
-        dynabuf var(16);
-        GetServerVariable(m_lpECB, "REMOTE_ADDR", var, 16, false);
-        if (!var.empty())
-            m_remote_addr = var;
-    }
-    return m_remote_addr;
-  }
-  void log(SPLogLevel level, const string& msg) const {
-      AbstractSPRequest::log(level,msg);
-      if (level >= SPCrit)
-          LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, msg.c_str());
-  }
-  string getHeader(const char* name) const {
-    string hdr("HTTP_");
-    for (; *name; ++name) {
-        if (*name=='-')
-            hdr += '_';
-        else
-            hdr += toupper(*name);
-    }
-    dynabuf buf(128);
-    GetServerVariable(m_lpECB, const_cast<char*>(hdr.c_str()), buf, 128, false);
-    return buf.empty() ? "" : buf;
-  }
-  void setResponseHeader(const char* name, const char* value) {
-    // Set for later.
-    if (value)
-        m_headers.insert(make_pair(name,value));
-    else
-        m_headers.erase(name);
-  }
-  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)
-            throw IOException("Error reading request body from browser.");
-        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";
-    const char* codestr="200 OK";
-    switch (status) {
-        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_lpECB->ServerSupportFunction(m_lpECB->ConnID, HSE_REQ_SEND_RESPONSE_HEADER, (void*)codestr, 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) {
-    string hdr=string("Location: ") + url + "\r\n"
-      "Content-Type: text/html\r\n"
-      "Content-Length: 40\r\n"
-      "Expires: 01-Jan-1997 12:00:00 GMT\r\n"
-      "Cache-Control: private,no-store,no-cache\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, "302 Moved", 0, (LPDWORD)hdr.c_str());
-    static const char* redmsg="<HTML><BODY>Redirecting...</BODY></HTML>";
-    DWORD resplen=40;
-    m_lpECB->WriteClient(m_lpECB->ConnID, (LPVOID)redmsg, &resplen, HSE_IO_SYNC);
-    return HSE_STATUS_SUCCESS;
-  }
-  // Decline happens in the POST processor if this isn't the shire url
-  // 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, NULL)) {
-            if (ccex.CertContext.cbCertEncoded) {
-                xsecsize_t outlen;
-                XMLByte* serialized = Base64::encode(reinterpret_cast<XMLByte*>(CertificateBuf), ccex.CertContext.cbCertEncoded, &outlen);
-                m_certs.push_back(reinterpret_cast<char*>(serialized));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
-                XMLString::release(&serialized);
-#else
-                XMLString::release((char**)&serialized);
-#endif
-            }
-        }
-      }
-      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"); }
-};
-
-extern "C" DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB)
-{
-    try {
-        ostringstream threadid;
-        threadid << "[" << getpid() << "] isapi_shib_extension" << '\0';
-        xmltooling::NDC ndc(threadid.str().c_str());
-
-        // Determine web site number. This can't really fail, I don't think.
-        dynabuf buf(128);
-        GetServerVariable(lpECB,"INSTANCE_ID",buf,10);
-
-        // 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 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(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 (exception& e) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, e.what());
-        return WriteClientError(lpECB,"Shibboleth Extension caught an exception, check Event Log for details.");
-    }
-    catch(...) {
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "Shibboleth Extension threw 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;
-}
index 4a6f709..116438f 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth ISAPI Filter / Extension\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "isapi_shib\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "isapi_shib.dll\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index 23f82e3..0223495 100644 (file)
--- a/ltmain.sh
+++ b/ltmain.sh
@@ -1,7 +1,7 @@
 # ltmain.sh - Provide generalized library-building support services.
 # NOTE: Changing this file will not affect anything until you rerun configure.
 #
-# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005
 # Free Software Foundation, Inc.
 # Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996
 #
@@ -17,7 +17,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 #
 # As a special exception to the GNU General Public License, if you
 # distribute this file as part of a program that contains a
@@ -33,9 +33,6 @@ basename="s,^.*/,,g"
 # function.
 progpath="$0"
 
-# RH: define SED for historic ltconfig's generated by Libtool 1.3
-[ -z "$SED" ] && SED=sed
-
 # The name of this program:
 progname=`echo "$progpath" | $SED $basename`
 modename="$progname"
@@ -46,9 +43,20 @@ EXIT_FAILURE=1
 
 PROGRAM=ltmain.sh
 PACKAGE=libtool
-VERSION=1.5.6
-TIMESTAMP=" (1.1220.2.95 2004/04/11 05:50:42)"
-
+VERSION=1.5.22
+TIMESTAMP=" (1.1220.2.365 2005/12/18 22:14:06)"
+
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '${1+"$@"}'='"$@"'
+  setopt NO_GLOB_SUBST
+else
+  case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac
+fi
 
 # Check that we have a working $echo.
 if test "X$1" = X--no-reexec; then
@@ -86,14 +94,15 @@ rm="rm -f"
 Xsed="${SED}"' -e 1s/^X//'
 sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g'
 # test EBCDIC or ASCII
-case `echo A|tr A '\301'` in
- A) # EBCDIC based system
-  SP2NL="tr '\100' '\n'"
-  NL2SP="tr '\r\n' '\100\100'"
+case `echo X|tr X '\101'` in
+ A) # ASCII based system
+    # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr
+  SP2NL='tr \040 \012'
+  NL2SP='tr \015\012 \040\040'
   ;;
- *) # Assume ASCII based system
-  SP2NL="tr '\040' '\012'"
-  NL2SP="tr '\015\012' '\040\040'"
+ *) # EBCDIC based system
+  SP2NL='tr \100 \n'
+  NL2SP='tr \r\n \100\100'
   ;;
 esac
 
@@ -102,16 +111,19 @@ esac
 # These must not be set unconditionally because not all systems understand
 # e.g. LANG=C (notably SCO).
 # We save the old values to restore during execute mode.
-if test "${LC_ALL+set}" = set; then
-  save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL
-fi
-if test "${LANG+set}" = set; then
-  save_LANG="$LANG"; LANG=C; export LANG
-fi
+for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+do
+  eval "if test \"\${$lt_var+set}\" = set; then
+         save_$lt_var=\$$lt_var
+         $lt_var=C
+         export $lt_var
+       fi"
+done
 
 # Make sure IFS has a sensible default
-: ${IFS="      
-"}
+lt_nl='
+'
+IFS="  $lt_nl"
 
 if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then
   $echo "$modename: not configured to build any kind of library" 1>&2
@@ -128,20 +140,62 @@ run=
 show="$echo"
 show_help=
 execute_dlfiles=
+duplicate_deps=no
+preserve_args=
 lo2o="s/\\.lo\$/.${objext}/"
 o2lo="s/\\.${objext}\$/.lo/"
+extracted_archives=
+extracted_serial=0
 
 #####################################
 # Shell function definitions:
 # This seems to be the best place for them
 
+# func_mktempdir [string]
+# Make a temporary directory that won't clash with other running
+# libtool processes, and avoids race conditions if possible.  If
+# given, STRING is the basename for that directory.
+func_mktempdir ()
+{
+    my_template="${TMPDIR-/tmp}/${1-$progname}"
+
+    if test "$run" = ":"; then
+      # Return a directory name, but don't create it in dry-run mode
+      my_tmpdir="${my_template}-$$"
+    else
+
+      # If mktemp works, use that first and foremost
+      my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null`
+
+      if test ! -d "$my_tmpdir"; then
+       # Failing that, at least try and use $RANDOM to avoid a race
+       my_tmpdir="${my_template}-${RANDOM-0}$$"
+
+       save_mktempdir_umask=`umask`
+       umask 0077
+       $mkdir "$my_tmpdir"
+       umask $save_mktempdir_umask
+      fi
+
+      # If we're not in dry-run mode, bomb out on failure
+      test -d "$my_tmpdir" || {
+        $echo "cannot create temporary directory \`$my_tmpdir'" 1>&2
+       exit $EXIT_FAILURE
+      }
+    fi
+
+    $echo "X$my_tmpdir" | $Xsed
+}
+
+
 # func_win32_libid arg
 # return the library type of file 'arg'
 #
 # Need a lot of goo to handle *both* DLLs and import libs
 # Has to be a shell function in order to 'eat' the argument
 # that is supplied when $file_magic_command is called.
-func_win32_libid () {
+func_win32_libid ()
+{
   win32_libid_type="unknown"
   win32_fileres=`file -L $1 2>/dev/null`
   case $win32_fileres in
@@ -152,12 +206,11 @@ func_win32_libid () {
     if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | \
       $EGREP -e 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then
       win32_nmres=`eval $NM -f posix -A $1 | \
-       sed -n -e '1,100{/ I /{x;/import/!{s/^/import/;h;p;};x;};}'`
-      if test "X$win32_nmres" = "Ximport" ; then
-        win32_libid_type="x86 archive import"
-      else
-        win32_libid_type="x86 archive static"
-      fi
+       $SED -n -e '1,100{/ I /{s,.*,import,;p;q;};}'`
+      case $win32_nmres in
+      import*)  win32_libid_type="x86 archive import";;
+      *)        win32_libid_type="x86 archive static";;
+      esac
     fi
     ;;
   *DLL*)
@@ -181,7 +234,8 @@ func_win32_libid () {
 # Only attempt this if the compiler in the base compile
 # command doesn't match the default compiler.
 # arg is usually of the form 'gcc ...'
-func_infer_tag () {
+func_infer_tag ()
+{
     if test -n "$available_tags" && test -z "$tagname"; then
       CC_quoted=
       for arg in $CC; do
@@ -238,12 +292,126 @@ func_infer_tag () {
       esac
     fi
 }
+
+
+# func_extract_an_archive dir oldlib
+func_extract_an_archive ()
+{
+    f_ex_an_ar_dir="$1"; shift
+    f_ex_an_ar_oldlib="$1"
+
+    $show "(cd $f_ex_an_ar_dir && $AR x $f_ex_an_ar_oldlib)"
+    $run eval "(cd \$f_ex_an_ar_dir && $AR x \$f_ex_an_ar_oldlib)" || exit $?
+    if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then
+     :
+    else
+      $echo "$modename: ERROR: object name conflicts: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" 1>&2
+      exit $EXIT_FAILURE
+    fi
+}
+
+# func_extract_archives gentop oldlib ...
+func_extract_archives ()
+{
+    my_gentop="$1"; shift
+    my_oldlibs=${1+"$@"}
+    my_oldobjs=""
+    my_xlib=""
+    my_xabs=""
+    my_xdir=""
+    my_status=""
+
+    $show "${rm}r $my_gentop"
+    $run ${rm}r "$my_gentop"
+    $show "$mkdir $my_gentop"
+    $run $mkdir "$my_gentop"
+    my_status=$?
+    if test "$my_status" -ne 0 && test ! -d "$my_gentop"; then
+      exit $my_status
+    fi
+
+    for my_xlib in $my_oldlibs; do
+      # Extract the objects.
+      case $my_xlib in
+       [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;;
+       *) my_xabs=`pwd`"/$my_xlib" ;;
+      esac
+      my_xlib=`$echo "X$my_xlib" | $Xsed -e 's%^.*/%%'`
+      my_xlib_u=$my_xlib
+      while :; do
+        case " $extracted_archives " in
+       *" $my_xlib_u "*)
+         extracted_serial=`expr $extracted_serial + 1`
+         my_xlib_u=lt$extracted_serial-$my_xlib ;;
+       *) break ;;
+       esac
+      done
+      extracted_archives="$extracted_archives $my_xlib_u"
+      my_xdir="$my_gentop/$my_xlib_u"
+
+      $show "${rm}r $my_xdir"
+      $run ${rm}r "$my_xdir"
+      $show "$mkdir $my_xdir"
+      $run $mkdir "$my_xdir"
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$my_xdir"; then
+       exit $exit_status
+      fi
+      case $host in
+      *-darwin*)
+       $show "Extracting $my_xabs"
+       # Do not bother doing anything if just a dry run
+       if test -z "$run"; then
+         darwin_orig_dir=`pwd`
+         cd $my_xdir || exit $?
+         darwin_archive=$my_xabs
+         darwin_curdir=`pwd`
+         darwin_base_archive=`$echo "X$darwin_archive" | $Xsed -e 's%^.*/%%'`
+         darwin_arches=`lipo -info "$darwin_archive" 2>/dev/null | $EGREP Architectures 2>/dev/null`
+         if test -n "$darwin_arches"; then 
+           darwin_arches=`echo "$darwin_arches" | $SED -e 's/.*are://'`
+           darwin_arch=
+           $show "$darwin_base_archive has multiple architectures $darwin_arches"
+           for darwin_arch in  $darwin_arches ; do
+             mkdir -p "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             lipo -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}"
+             cd "unfat-$$/${darwin_base_archive}-${darwin_arch}"
+             func_extract_an_archive "`pwd`" "${darwin_base_archive}"
+             cd "$darwin_curdir"
+             $rm "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}"
+           done # $darwin_arches
+      ## Okay now we have a bunch of thin objects, gotta fatten them up :)
+           darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print| xargs basename | sort -u | $NL2SP`
+           darwin_file=
+           darwin_files=
+           for darwin_file in $darwin_filelist; do
+             darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP`
+             lipo -create -output "$darwin_file" $darwin_files
+           done # $darwin_filelist
+           ${rm}r unfat-$$
+           cd "$darwin_orig_dir"
+         else
+           cd "$darwin_orig_dir"
+           func_extract_an_archive "$my_xdir" "$my_xabs"
+         fi # $darwin_arches
+       fi # $run
+       ;;
+      *)
+        func_extract_an_archive "$my_xdir" "$my_xabs"
+        ;;
+      esac
+      my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
+    done
+    func_extract_archives_result="$my_oldobjs"
+}
 # End of Shell function definitions
 #####################################
 
 # Darwin sucks
 eval std_shrext=\"$shrext_cmds\"
 
+disable_libs=no
+
 # Parse our command line options once, thoroughly.
 while test "$#" -gt 0
 do
@@ -308,10 +476,10 @@ do
   --version)
     $echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"
     $echo
-    $echo "Copyright (C) 2003  Free Software Foundation, Inc."
+    $echo "Copyright (C) 2005  Free Software Foundation, Inc."
     $echo "This is free software; see the source for copying conditions.  There is NO"
     $echo "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --config)
@@ -320,7 +488,7 @@ do
     for tagname in $taglist; do
       ${SED} -n -e "/^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$/,/^# ### END LIBTOOL TAG CONFIG: $tagname$/p" < "$progpath"
     done
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --debug)
@@ -345,7 +513,7 @@ do
     else
       $echo "disable static libraries"
     fi
-    exit $EXIT_SUCCESS
+    exit $?
     ;;
 
   --finish) mode="finish" ;;
@@ -360,7 +528,11 @@ do
     preserve_args="$preserve_args $arg"
     ;;
 
-  --tag) prevopt="--tag" prev=tag ;;
+  --tag)
+    prevopt="--tag"
+    prev=tag
+    preserve_args="$preserve_args --tag"
+    ;;
   --tag=*)
     set tag "$optarg" ${1+"$@"}
     shift
@@ -392,6 +564,18 @@ if test -n "$prevopt"; then
   exit $EXIT_FAILURE
 fi
 
+case $disable_libs in
+no) 
+  ;;
+shared)
+  build_libtool_libs=no
+  build_old_libs=yes
+  ;;
+static)
+  build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac`
+  ;;
+esac
+
 # If this variable is set in any of the actions, the command in it
 # will be execed at the end.  This prevents here-documents from being
 # left over by shells.
@@ -402,7 +586,7 @@ if test -z "$show_help"; then
   # Infer the operation mode.
   if test -z "$mode"; then
     $echo "*** Warning: inferring the mode of operation is deprecated." 1>&2
-    $echo "*** Future versions of Libtool will require -mode=MODE be specified." 1>&2
+    $echo "*** Future versions of Libtool will require --mode=MODE be specified." 1>&2
     case $nonopt in
     *cc | cc* | *++ | gcc* | *-gcc* | g++* | xlc*)
       mode=link
@@ -468,7 +652,7 @@ if test -z "$show_help"; then
 
     for arg
     do
-      case "$arg_mode" in
+      case $arg_mode in
       arg  )
        # do not "continue".  Instead, add this to base_compile
        lastarg="$arg"
@@ -550,7 +734,10 @@ if test -z "$show_help"; then
       case $lastarg in
       # Double-quote args containing other shell metacharacters.
       # Many Bourne shells cannot handle close brackets correctly
-      # in scan sets, so we specify it separately.
+      # in scan sets, and some SunOS ksh mistreat backslash-escaping
+      # in scan sets (worked around with variable expansion),
+      # and furthermore cannot handle '|' '&' '(' ')' in scan sets 
+      # at all, so we specify them separately.
       *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        lastarg="\"$lastarg\""
        ;;
@@ -591,6 +778,7 @@ if test -z "$show_help"; then
     *.f90) xform=f90 ;;
     *.for) xform=for ;;
     *.java) xform=java ;;
+    *.obj) xform=obj ;;
     esac
 
     libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"`
@@ -624,6 +812,14 @@ if test -z "$show_help"; then
       esac
     done
 
+    qlibobj=`$echo "X$libobj" | $Xsed -e "$sed_quote_subst"`
+    case $qlibobj in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+       qlibobj="\"$qlibobj\"" ;;
+    esac
+    test "X$libobj" != "X$qlibobj" \
+       && $echo "X$libobj" | grep '[]~#^*{};<>?"'"'"'  &()|`$[]' \
+       && $echo "$modename: libobj name \`$libobj' may not contain shell special characters."
     objname=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
     xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'`
     if test "X$xdir" = "X$obj"; then
@@ -696,12 +892,17 @@ compiler."
        $run $rm $removelist
        exit $EXIT_FAILURE
       fi
-      $echo $srcfile > "$lockfile"
+      $echo "$srcfile" > "$lockfile"
     fi
 
     if test -n "$fix_srcfile_path"; then
       eval srcfile=\"$fix_srcfile_path\"
     fi
+    qsrcfile=`$echo "X$srcfile" | $Xsed -e "$sed_quote_subst"`
+    case $qsrcfile in
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
+      qsrcfile="\"$qsrcfile\"" ;;
+    esac
 
     $run $rm "$libobj" "${libobj}T"
 
@@ -723,18 +924,18 @@ EOF
       fbsd_hideous_sh_bug=$base_compile
 
       if test "$pic_mode" != no; then
-       command="$base_compile $srcfile $pic_flag"
+       command="$base_compile $qsrcfile $pic_flag"
       else
        # Don't build PIC code
-       command="$base_compile $srcfile"
+       command="$base_compile $qsrcfile"
       fi
 
       if test ! -d "${xdir}$objdir"; then
        $show "$mkdir ${xdir}$objdir"
        $run $mkdir ${xdir}$objdir
-       status=$?
-       if test "$status" -ne 0 && test ! -d "${xdir}$objdir"; then
-         exit $status
+       exit_status=$?
+       if test "$exit_status" -ne 0 && test ! -d "${xdir}$objdir"; then
+         exit $exit_status
        fi
       fi
 
@@ -806,9 +1007,9 @@ EOF
     if test "$build_old_libs" = yes; then
       if test "$pic_mode" != yes; then
        # Don't build PIC code
-       command="$base_compile $srcfile"
+       command="$base_compile $qsrcfile"
       else
-       command="$base_compile $srcfile $pic_flag"
+       command="$base_compile $qsrcfile $pic_flag"
       fi
       if test "$compiler_c_o" = yes; then
        command="$command -o $obj"
@@ -937,6 +1138,7 @@ EOF
     no_install=no
     objs=
     non_pic_objects=
+    notinst_path= # paths that contain not-installed libtool libraries
     precious_files_regex=
     prefer_static_libs=no
     preload=no
@@ -957,22 +1159,32 @@ EOF
     for arg
     do
       case $arg in
-      -all-static | -static)
-       if test "X$arg" = "X-all-static"; then
+      -all-static | -static | -static-libtool-libs)
+    case $arg in
+    -all-static)
          if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then
            $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2
          fi
          if test -n "$link_static_flag"; then
            dlopen_self=$dlopen_self_static
          fi
-       else
+         prefer_static_libs=yes
+         ;;
+    -static)
          if test -z "$pic_flag" && test -n "$link_static_flag"; then
            dlopen_self=$dlopen_self_static
          fi
-       fi
+         prefer_static_libs=built
+         ;;
+    -static-libtool-libs)
+      if test -z "$pic_flag" && test -n "$link_static_flag"; then
+        dlopen_self=$dlopen_self_static
+      fi
+      prefer_static_libs=yes
+      ;;
+    esac
        build_libtool_libs=no
        build_old_libs=yes
-       prefer_static_libs=yes
        break
        ;;
       esac
@@ -1147,6 +1359,11 @@ EOF
                  if test -z "$pic_object" || test "$pic_object" = none ; then
                    arg="$non_pic_object"
                  fi
+               else
+                 # If the PIC object exists, use it instead.
+                 # $xdir was prepended to $pic_object above.
+                 non_pic_object="$pic_object"
+                 non_pic_objects="$non_pic_objects $non_pic_object"
                fi
              else
                # Only an error if not doing a dry-run.
@@ -1230,6 +1447,13 @@ EOF
          prev=
          continue
          ;;
+       darwin_framework|darwin_framework_skip)
+         test "$prev" = "darwin_framework" && compiler_flags="$compiler_flags $arg"
+         compile_command="$compile_command $arg"
+         finalize_command="$finalize_command $arg"
+         prev=
+         continue
+         ;;
        *)
          eval "$prev=\"\$arg\""
          prev=
@@ -1288,6 +1512,18 @@ EOF
        continue
        ;;
 
+      -framework|-arch|-isysroot)
+       case " $CC " in
+         *" ${arg} ${1} "* | *" ${arg} ${1} "*) 
+               prev=darwin_framework_skip ;;
+         *) compiler_flags="$compiler_flags $arg"
+            prev=darwin_framework ;;
+       esac
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
+       continue
+       ;;
+
       -inst-prefix-dir)
        prev=inst_prefix
        continue
@@ -1314,7 +1550,8 @@ EOF
          absdir=`cd "$dir" && pwd`
          if test -z "$absdir"; then
            $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2
-           exit $EXIT_FAILURE
+           absdir="$dir"
+           notinst_path="$notinst_path $dir"
          fi
          dir="$absdir"
          ;;
@@ -1328,10 +1565,15 @@ EOF
        esac
        case $host in
        *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$dir" | $Xsed -e 's*/lib$*/bin*'`
          case :$dllsearchpath: in
          *":$dir:"*) ;;
          *) dllsearchpath="$dllsearchpath:$dir";;
          esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
          ;;
        esac
        continue
@@ -1340,15 +1582,15 @@ EOF
       -l*)
        if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then
          case $host in
-         *-*-cygwin* | *-*-pw32* | *-*-beos*)
+         *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos*)
            # These systems don't actually have a C or math library (as such)
            continue
            ;;
-         *-*-mingw* | *-*-os2*)
+         *-*-os2*)
            # These systems don't actually have a C library (as such)
            test "X$arg" = "X-lc" && continue
            ;;
-         *-*-openbsd* | *-*-freebsd*)
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
            # Do not include libc due to us having libc/libc_r.
            test "X$arg" = "X-lc" && continue
            ;;
@@ -1356,10 +1598,19 @@ EOF
            # Rhapsody C and math libraries are in the System framework
            deplibs="$deplibs -framework System"
            continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
+           test "X$arg" = "X-lc" && continue
+           ;;
          esac
        elif test "X$arg" = "X-lc_r"; then
         case $host in
-        *-*-openbsd* | *-*-freebsd*)
+        *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
           # Do not include libc_r directly, use -pthread flag.
           continue
           ;;
@@ -1369,8 +1620,20 @@ EOF
        continue
        ;;
 
+      # Tru64 UNIX uses -model [arg] to determine the layout of C++
+      # classes, name mangling, and exception handling.
+      -model)
+       compile_command="$compile_command $arg"
+       compiler_flags="$compiler_flags $arg"
+       finalize_command="$finalize_command $arg"
+       prev=xcompiler
+       continue
+       ;;
+
      -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe)
-       deplibs="$deplibs $arg"
+       compiler_flags="$compiler_flags $arg"
+       compile_command="$compile_command $arg"
+       finalize_command="$finalize_command $arg"
        continue
        ;;
 
@@ -1379,13 +1642,19 @@ EOF
        continue
        ;;
 
-      # gcc -m* arguments should be passed to the linker via $compiler_flags
-      # in order to pass architecture information to the linker
-      # (e.g. 32 vs 64-bit).  This may also be accomplished via -Wl,-mfoo
-      # but this is not reliable with gcc because gcc may use -mfoo to
-      # select a different linker, different libraries, etc, while
-      # -Wl,-mfoo simply passes -mfoo to the linker.
-      -m*)
+      # -64, -mips[0-9] enable 64-bit mode on the SGI compiler
+      # -r[0-9][0-9]* specifies the processor on the SGI compiler
+      # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler
+      # +DA*, +DD* enable 64-bit mode on the HP compiler
+      # -q* pass through compiler args for the IBM compiler
+      # -m* pass through architecture-specific compiler args for GCC
+      # -m*, -t[45]*, -txscale* pass through architecture-specific
+      # compiler args for GCC
+      # -pg pass through profiling flag for GCC
+      # @file GCC response files
+      -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*|-pg| \
+      -t[45]*|-txscale*|@*)
+
        # Unknown arguments in both finalize_command and compile_command need
        # to be aesthetically quoted because they are evaled later.
        arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
@@ -1396,9 +1665,7 @@ EOF
        esac
         compile_command="$compile_command $arg"
         finalize_command="$finalize_command $arg"
-        if test "$with_gcc" = "yes" ; then
-          compiler_flags="$compiler_flags $arg"
-        fi
+        compiler_flags="$compiler_flags $arg"
         continue
         ;;
 
@@ -1475,7 +1742,7 @@ EOF
        continue
        ;;
 
-      -static)
+      -static | -static-libtool-libs)
        # The effects of -static are defined in a previous loop.
        # We used to do the same as -all-static on platforms that
        # didn't have a PIC flag, but the assumption that the effects
@@ -1636,6 +1903,11 @@ EOF
            if test -z "$pic_object" || test "$pic_object" = none ; then
              arg="$non_pic_object"
            fi
+         else
+           # If the PIC object exists, use it instead.
+           # $xdir was prepended to $pic_object above.
+           non_pic_object="$pic_object"
+           non_pic_objects="$non_pic_objects $non_pic_object"
          fi
        else
          # Only an error if not doing a dry-run.
@@ -1741,9 +2013,9 @@ EOF
     if test ! -d "$output_objdir"; then
       $show "$mkdir $output_objdir"
       $run $mkdir $output_objdir
-      status=$?
-      if test "$status" -ne 0 && test ! -d "$output_objdir"; then
-       exit $status
+      exit_status=$?
+      if test "$exit_status" -ne 0 && test ! -d "$output_objdir"; then
+       exit $exit_status
       fi
     fi
 
@@ -1806,7 +2078,6 @@ EOF
     newlib_search_path=
     need_relink=no # whether we're linking any uninstalled libtool libraries
     notinst_deplibs= # not-installed libtool libraries
-    notinst_path= # paths that contain not-installed libtool libraries
     case $linkmode in
     lib)
        passes="conv link"
@@ -1858,7 +2129,7 @@ EOF
            compile_deplibs="$deplib $compile_deplibs"
            finalize_deplibs="$deplib $finalize_deplibs"
          else
-           deplibs="$deplib $deplibs"
+           compiler_flags="$compiler_flags $deplib"
          fi
          continue
          ;;
@@ -1867,10 +2138,6 @@ EOF
            $echo "$modename: warning: \`-l' is ignored for archives/objects" 1>&2
            continue
          fi
-         if test "$pass" = conv; then
-           deplibs="$deplib $deplibs"
-           continue
-         fi
          name=`$echo "X$deplib" | $Xsed -e 's/^-l//'`
          for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do
            for search_ext in .la $std_shrext .so .a; do
@@ -1981,7 +2248,22 @@ EOF
          fi
          case $linkmode in
          lib)
-           if test "$deplibs_check_method" != pass_all; then
+           valid_a_lib=no
+           case $deplibs_check_method in
+             match_pattern*)
+               set dummy $deplibs_check_method
+               match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
+               if eval $echo \"$deplib\" 2>/dev/null \
+                   | $SED 10q \
+                   | $EGREP "$match_pattern_regex" > /dev/null; then
+                 valid_a_lib=yes
+               fi
+               ;;
+             pass_all)
+               valid_a_lib=yes
+               ;;
+            esac
+           if test "$valid_a_lib" != yes; then
              $echo
              $echo "*** Warning: Trying to link with static lib archive $deplib."
              $echo "*** I have the capability to make that library automatically link in when"
@@ -2031,7 +2313,7 @@ EOF
        esac # case $deplib
        if test "$found" = yes || test -f "$lib"; then :
        else
-         $echo "$modename: cannot find the library \`$lib'" 1>&2
+         $echo "$modename: cannot find the library \`$lib' or unhandled argument \`$deplib'" 1>&2
          exit $EXIT_FAILURE
        fi
 
@@ -2055,6 +2337,8 @@ EOF
        # it will not redefine variables installed, or shouldnotlink
        installed=yes
        shouldnotlink=no
+       avoidtemprpath=
+
 
        # Read the .la file
        case $lib in
@@ -2153,11 +2437,19 @@ EOF
            dir="$libdir"
            absdir="$libdir"
          fi
+         test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes
        else
-         dir="$ladir/$objdir"
-         absdir="$abs_ladir/$objdir"
-         # Remove this search path later
-         notinst_path="$notinst_path $abs_ladir"
+         if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then
+           dir="$ladir"
+           absdir="$abs_ladir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         else
+           dir="$ladir/$objdir"
+           absdir="$abs_ladir/$objdir"
+           # Remove this search path later
+           notinst_path="$notinst_path $abs_ladir"
+         fi
        fi # $installed = yes
        name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'`
 
@@ -2228,14 +2520,16 @@ EOF
 
        if test "$linkmode,$pass" = "prog,link"; then
          if test -n "$library_names" &&
-            { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+         { { test "$prefer_static_libs" = no ||
+             test "$prefer_static_libs,$installed" = "built,yes"; } ||
+           test -z "$old_library"; }; then
            # We need to hardcode the library path
-           if test -n "$shlibpath_var"; then
+           if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then
              # Make sure the rpath contains only unique directories.
              case "$temp_rpath " in
              *" $dir "*) ;;
              *" $absdir "*) ;;
-             *) temp_rpath="$temp_rpath $dir" ;;
+             *) temp_rpath="$temp_rpath $absdir" ;;
              esac
            fi
 
@@ -2272,8 +2566,12 @@ EOF
        fi
 
        link_static=no # Whether the deplib will be linked statically
+       use_static_libs=$prefer_static_libs
+       if test "$use_static_libs" = built && test "$installed" = yes ; then
+         use_static_libs=no
+       fi
        if test -n "$library_names" &&
-          { test "$prefer_static_libs" = no || test -z "$old_library"; }; then
+          { test "$use_static_libs" = no || test -z "$old_library"; }; then
          if test "$installed" = no; then
            notinst_deplibs="$notinst_deplibs $lib"
            need_relink=yes
@@ -2386,11 +2684,15 @@ EOF
              if test "$hardcode_direct" = no; then
                add="$dir/$linklib"
                case $host in
-                 *-*-sco3.2v5* ) add_dir="-L$dir" ;;
+                 *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;;
+                 *-*-sysv4*uw2*) add_dir="-L$dir" ;;
+                 *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \
+                   *-*-unixware7*) add_dir="-L$dir" ;;
                  *-*-darwin* )
                    # if the lib is a module then we can not link against
                    # it, someone is ignoring the new warnings I added
-                   if /usr/bin/file -L $add 2> /dev/null | $EGREP "bundle" >/dev/null ; then
+                   if /usr/bin/file -L $add 2> /dev/null |
+                      $EGREP ": [^:]* bundle" >/dev/null ; then
                      $echo "** Warning, lib $linklib is a module, not a shared library"
                      if test -z "$old_library" ; then
                        $echo
@@ -2421,7 +2723,7 @@ EOF
                add_dir="-L$dir"
                # Try looking first in the location we're being installed to.
                if test -n "$inst_prefix_dir"; then
-                 case "$libdir" in
+                 case $libdir in
                    [\\/]*)
                      add_dir="$add_dir -L$inst_prefix_dir$libdir"
                      ;;
@@ -2494,7 +2796,7 @@ EOF
              add_dir="-L$libdir"
              # Try looking first in the location we're being installed to.
              if test -n "$inst_prefix_dir"; then
-               case "$libdir" in
+               case $libdir in
                  [\\/]*)
                    add_dir="$add_dir -L$inst_prefix_dir$libdir"
                    ;;
@@ -2555,8 +2857,6 @@ EOF
              fi
            fi
          else
-           convenience="$convenience $dir/$old_library"
-           old_convenience="$old_convenience $dir/$old_library"
            deplibs="$dir/$old_library $deplibs"
            link_static=yes
          fi
@@ -2674,12 +2974,12 @@ EOF
              *) continue ;;
              esac
              case " $deplibs " in
-             *" $depdepl "*) ;;
-             *) deplibs="$depdepl $deplibs" ;;
+             *" $path "*) ;;
+             *) deplibs="$path $deplibs" ;;
              esac
              case " $deplibs " in
-             *" $path "*) ;;
-             *) deplibs="$deplibs $path" ;;
+             *" $depdepl "*) ;;
+             *) deplibs="$depdepl $deplibs" ;;
              esac
            done
          fi # link_all_deplibs != no
@@ -2918,7 +3218,7 @@ EOF
          # which has an extra 1 added just for fun
          #
          case $version_type in
-         darwin|linux|osf|windows)
+         darwin|linux|osf|windows|none)
            current=`expr $number_major + $number_minor`
            age="$number_minor"
            revision="$number_revision"
@@ -2944,27 +3244,27 @@ EOF
 
        # Check that each of the things are valid numbers.
        case $current in
-       [0-9]*) ;;
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
        *)
-         $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2
+         $echo "$modename: CURRENT \`$current' must be a nonnegative integer" 1>&2
          $echo "$modename: \`$vinfo' is not valid version information" 1>&2
          exit $EXIT_FAILURE
          ;;
        esac
 
        case $revision in
-       [0-9]*) ;;
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
        *)
-         $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2
+         $echo "$modename: REVISION \`$revision' must be a nonnegative integer" 1>&2
          $echo "$modename: \`$vinfo' is not valid version information" 1>&2
          exit $EXIT_FAILURE
          ;;
        esac
 
        case $age in
-       [0-9]*) ;;
+       0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;;
        *)
-         $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2
+         $echo "$modename: AGE \`$age' must be a nonnegative integer" 1>&2
          $echo "$modename: \`$vinfo' is not valid version information" 1>&2
          exit $EXIT_FAILURE
          ;;
@@ -2990,7 +3290,7 @@ EOF
          versuffix="$major.$age.$revision"
          # Darwin ld doesn't like 0 for these options...
          minor_current=`expr $current + 1`
-         verstring="-compatibility_version $minor_current -current_version $minor_current.$revision"
+         verstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision"
          ;;
 
        freebsd-aout)
@@ -3142,11 +3442,11 @@ EOF
       fi
 
       # Eliminate all temporary directories.
-      for path in $notinst_path; do
-       lib_search_path=`$echo "$lib_search_path " | ${SED} -e 's% $path % %g'`
-       deplibs=`$echo "$deplibs " | ${SED} -e 's% -L$path % %g'`
-       dependency_libs=`$echo "$dependency_libs " | ${SED} -e 's% -L$path % %g'`
-      done
+#      for path in $notinst_path; do
+#      lib_search_path=`$echo "$lib_search_path " | ${SED} -e "s% $path % %g"`
+#      deplibs=`$echo "$deplibs " | ${SED} -e "s% -L$path % %g"`
+#      dependency_libs=`$echo "$dependency_libs " | ${SED} -e "s% -L$path % %g"`
+#      done
 
       if test -n "$xrpath"; then
        # If the user specified any rpath flags, then add them.
@@ -3196,9 +3496,14 @@ EOF
          *-*-netbsd*)
            # Don't link with libc until the a.out ld.so is fixed.
            ;;
-         *-*-openbsd* | *-*-freebsd*)
+         *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*)
            # Do not include libc due to us having libc/libc_r.
-           test "X$arg" = "X-lc" && continue
+           ;;
+         *-*-sco3.2v5* | *-*-sco5v6*)
+           # Causes problems with __ctype
+           ;;
+         *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*)
+           # Compiler inserts libc in the correct place for threads to work
            ;;
          *)
            # Add libc to deplibs on all other systems if necessary.
@@ -3242,13 +3547,12 @@ EOF
          int main() { return 0; }
 EOF
          $rm conftest
-         $LTCC -o conftest conftest.c $deplibs
-         if test "$?" -eq 0 ; then
+      if $LTCC $LTCFLAGS -o conftest conftest.c $deplibs; then
            ldd_output=`ldd conftest`
            for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
+             name=`expr $i : '-l\(.*\)'`
              # If $name is empty we are operating on a -L argument.
-              if test "$name" != "" && test "$name" -ne "0"; then
+              if test "$name" != "" && test "$name" != "0"; then
                if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
                  case " $predeps $postdeps " in
                  *" $i "*)
@@ -3283,13 +3587,11 @@ EOF
            # Error occurred in the first compile.  Let's try to salvage
            # the situation: Compile a separate program for each library.
            for i in $deplibs; do
-             name="`expr $i : '-l\(.*\)'`"
+             name=`expr $i : '-l\(.*\)'`
              # If $name is empty we are operating on a -L argument.
               if test "$name" != "" && test "$name" != "0"; then
                $rm conftest
-               $LTCC -o conftest conftest.c $i
-               # Did it work?
-               if test "$?" -eq 0 ; then
+               if $LTCC $LTCFLAGS -o conftest conftest.c $i; then
                  ldd_output=`ldd conftest`
                  if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
                    case " $predeps $postdeps " in
@@ -3321,7 +3623,7 @@ EOF
                  droppeddeps=yes
                  $echo
                  $echo "*** Warning!  Library $i is needed by this library but I was not able to"
-                 $echo "***  make it link in!  You will probably need to install it or some"
+                 $echo "*** make it link in!  You will probably need to install it or some"
                  $echo "*** library that it depends on before this library will be fully"
                  $echo "*** functional.  Installing it before continuing would be even better."
                fi
@@ -3335,7 +3637,7 @@ EOF
          set dummy $deplibs_check_method
          file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
          for a_deplib in $deplibs; do
-           name="`expr $a_deplib : '-l\(.*\)'`"
+           name=`expr $a_deplib : '-l\(.*\)'`
            # If $name is empty we are operating on a -L argument.
             if test "$name" != "" && test  "$name" != "0"; then
              if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
@@ -3404,7 +3706,7 @@ EOF
          set dummy $deplibs_check_method
          match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"`
          for a_deplib in $deplibs; do
-           name="`expr $a_deplib : '-l\(.*\)'`"
+           name=`expr $a_deplib : '-l\(.*\)'`
            # If $name is empty we are operating on a -L argument.
            if test -n "$name" && test "$name" != "0"; then
              if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then
@@ -3534,6 +3836,35 @@ EOF
        deplibs=$newdeplibs
       fi
 
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      deplibs="$new_libs"
+
+
       # All the library-specific variables (install_libdir is set above).
       library_names=
       old_library=
@@ -3617,6 +3948,7 @@ EOF
        fi
 
        lib="$output_objdir/$realname"
+       linknames=
        for link
        do
          linknames="$linknames $link"
@@ -3645,6 +3977,9 @@ EOF
                # The command line is too long to execute in one step.
                $show "using reloadable object file for export list..."
                skipped_export=:
+               # Break out early, otherwise skipped_export may be
+               # set to false by a later but shorter cmd.
+               break
              fi
            done
            IFS="$save_ifs"
@@ -3678,67 +4013,13 @@ EOF
            eval libobjs=\"\$libobjs $whole_archive_flag_spec\"
          else
            gentop="$output_objdir/${outputname}x"
-           $show "${rm}r $gentop"
-           $run ${rm}r "$gentop"
-           $show "$mkdir $gentop"
-           $run $mkdir "$gentop"
-           status=$?
-           if test "$status" -ne 0 && test ! -d "$gentop"; then
-             exit $status
-           fi
            generated="$generated $gentop"
 
-           for xlib in $convenience; do
-             # Extract the objects.
-             case $xlib in
-             [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-             *) xabs=`pwd`"/$xlib" ;;
-             esac
-             xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-             xdir="$gentop/$xlib"
-
-             $show "${rm}r $xdir"
-             $run ${rm}r "$xdir"
-             $show "$mkdir $xdir"
-             $run $mkdir "$xdir"
-             status=$?
-             if test "$status" -ne 0 && test ! -d "$xdir"; then
-               exit $status
-             fi
-             # We will extract separately just the conflicting names and we will no
-             # longer touch any unique names. It is faster to leave these extract
-             # automatically by $AR in one run.
-             $show "(cd $xdir && $AR x $xabs)"
-             $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-             if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-               :
-             else
-               $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-               $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-               $AR t "$xabs" | sort | uniq -cd | while read -r count name
-               do
-                 i=1
-                 while test "$i" -le "$count"
-                 do
-                  # Put our $i before any first dot (extension)
-                  # Never overwrite any file
-                  name_to="$name"
-                  while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-                  do
-                    name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-                  done
-                  $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-                  $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-                  i=`expr $i + 1`
-                 done
-               done
-             fi
-
-             libobjs="$libobjs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-           done
+           func_extract_archives $gentop $convenience
+           libobjs="$libobjs $func_extract_archives_result"
          fi
        fi
-
+       
        if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then
          eval flag=\"$thread_safe_flag_spec\"
          linker_flags="$linker_flags $flag"
@@ -3768,7 +4049,8 @@ EOF
          fi
        fi
 
-       if test "X$skipped_export" != "X:" && len=`expr "X$test_cmds" : ".*"` &&
+       if test "X$skipped_export" != "X:" &&
+          len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
           test "$len" -le "$max_cmd_len" || test "$max_cmd_len" -le -1; then
          :
        else
@@ -3787,6 +4069,7 @@ EOF
            save_libobjs=$libobjs
          fi
          save_output=$output
+         output_la=`$echo "X$output" | $Xsed -e "$basename"`
 
          # Clear the reloadable object creation command queue and
          # initialize k to one.
@@ -3796,13 +4079,13 @@ EOF
          delfiles=
          last_robj=
          k=1
-         output=$output_objdir/$save_output-${k}.$objext
+         output=$output_objdir/$output_la-${k}.$objext
          # Loop over the list of objects to be linked.
          for obj in $save_libobjs
          do
            eval test_cmds=\"$reload_cmds $objlist $last_robj\"
            if test "X$objlist" = X ||
-              { len=`expr "X$test_cmds" : ".*"` &&
+              { len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
                 test "$len" -le "$max_cmd_len"; }; then
              objlist="$objlist $obj"
            else
@@ -3816,9 +4099,9 @@ EOF
                # the last one created.
                eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj\"
              fi
-             last_robj=$output_objdir/$save_output-${k}.$objext
+             last_robj=$output_objdir/$output_la-${k}.$objext
              k=`expr $k + 1`
-             output=$output_objdir/$save_output-${k}.$objext
+             output=$output_objdir/$output_la-${k}.$objext
              objlist=$obj
              len=1
            fi
@@ -3838,13 +4121,13 @@ EOF
            eval concat_cmds=\"\$concat_cmds~$export_symbols_cmds\"
           fi
 
-         # Set up a command to remove the reloadale object files
+         # Set up a command to remove the reloadable object files
          # after they are used.
          i=0
          while test "$i" -lt "$k"
          do
            i=`expr $i + 1`
-           delfiles="$delfiles $output_objdir/$save_output-${i}.$objext"
+           delfiles="$delfiles $output_objdir/$output_la-${i}.$objext"
          done
 
          $echo "creating a temporary reloadable object file: $output"
@@ -3892,13 +4175,30 @@ EOF
          IFS="$save_ifs"
          eval cmd=\"$cmd\"
          $show "$cmd"
-         $run eval "$cmd" || exit $?
+         $run eval "$cmd" || {
+           lt_exit=$?
+
+           # Restore the uninstalled library and exit
+           if test "$mode" = relink; then
+             $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+           fi
+
+           exit $lt_exit
+         }
        done
        IFS="$save_ifs"
 
        # Restore the uninstalled library and exit
        if test "$mode" = relink; then
          $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $?
+
+         if test -n "$convenience"; then
+           if test -z "$whole_archive_flag_spec"; then
+             $show "${rm}r $gentop"
+             $run ${rm}r "$gentop"
+           fi
+         fi
+
          exit $EXIT_SUCCESS
        fi
 
@@ -3968,72 +4268,20 @@ EOF
       reload_conv_objs=
       gentop=
       # reload_cmds runs $LD directly, so let us get rid of
-      # -Wl from whole_archive_flag_spec
+      # -Wl from whole_archive_flag_spec and hope we can get by with
+      # turning comma into space..
       wl=
 
       if test -n "$convenience"; then
        if test -n "$whole_archive_flag_spec"; then
-         eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\"
+         eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\"
+      reload_conv_objs=$reload_objs\ `$echo "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'`
        else
          gentop="$output_objdir/${obj}x"
-         $show "${rm}r $gentop"
-         $run ${rm}r "$gentop"
-         $show "$mkdir $gentop"
-         $run $mkdir "$gentop"
-         status=$?
-         if test "$status" -ne 0 && test ! -d "$gentop"; then
-           exit $status
-         fi
          generated="$generated $gentop"
 
-         for xlib in $convenience; do
-           # Extract the objects.
-           case $xlib in
-           [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-           *) xabs=`pwd`"/$xlib" ;;
-           esac
-           xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-           xdir="$gentop/$xlib"
-
-           $show "${rm}r $xdir"
-           $run ${rm}r "$xdir"
-           $show "$mkdir $xdir"
-           $run $mkdir "$xdir"
-           status=$?
-           if test "$status" -ne 0 && test ! -d "$xdir"; then
-             exit $status
-           fi
-           # We will extract separately just the conflicting names and we will no
-           # longer touch any unique names. It is faster to leave these extract
-           # automatically by $AR in one run.
-           $show "(cd $xdir && $AR x $xabs)"
-           $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-           if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-             :
-           else
-             $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-             $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-             $AR t "$xabs" | sort | uniq -cd | while read -r count name
-             do
-               i=1
-               while test "$i" -le "$count"
-               do
-                # Put our $i before any first dot (extension)
-                # Never overwrite any file
-                name_to="$name"
-                while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-                do
-                  name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-                done
-                $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-                $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-                i=`expr $i + 1`
-               done
-             done
-           fi
-
-           reload_conv_objs="$reload_objs "`find $xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP`
-         done
+         func_extract_archives $gentop $convenience
+         reload_conv_objs="$reload_objs $func_extract_archives_result"
        fi
       fi
 
@@ -4134,6 +4382,35 @@ EOF
         ;;
       esac
 
+
+      # move library search paths that coincide with paths to not yet
+      # installed libraries to the beginning of the library search list
+      new_libs=
+      for path in $notinst_path; do
+       case " $new_libs " in
+       *" -L$path/$objdir "*) ;;
+       *)
+         case " $compile_deplibs " in
+         *" -L$path/$objdir "*)
+           new_libs="$new_libs -L$path/$objdir" ;;
+         esac
+         ;;
+       esac
+      done
+      for deplib in $compile_deplibs; do
+       case $deplib in
+       -L*)
+         case " $new_libs " in
+         *" $deplib "*) ;;
+         *) new_libs="$new_libs $deplib" ;;
+         esac
+         ;;
+       *) new_libs="$new_libs $deplib" ;;
+       esac
+      done
+      compile_deplibs="$new_libs"
+
+
       compile_command="$compile_command $compile_deplibs"
       finalize_command="$finalize_command $finalize_deplibs"
 
@@ -4178,10 +4455,15 @@ EOF
        fi
        case $host in
        *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*)
+         testbindir=`$echo "X$libdir" | $Xsed -e 's*/lib$*/bin*'`
          case :$dllsearchpath: in
          *":$libdir:"*) ;;
          *) dllsearchpath="$dllsearchpath:$libdir";;
          esac
+         case :$dllsearchpath: in
+         *":$testbindir:"*) ;;
+         *) dllsearchpath="$dllsearchpath:$testbindir";;
+         esac
          ;;
        esac
       done
@@ -4295,13 +4577,25 @@ extern \"C\" {
 
            # Prepare the list of exported symbols
            if test -z "$export_symbols"; then
-             export_symbols="$output_objdir/$output.exp"
+             export_symbols="$output_objdir/$outputname.exp"
              $run $rm $export_symbols
-             $run eval "${SED} -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+             $run eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
            else
-             $run eval "${SED} -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"'
-             $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T'
+             $run eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"'
+             $run eval 'grep -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T'
              $run eval 'mv "$nlist"T "$nlist"'
+              case $host in
+              *cygwin* | *mingw* )
+               $run eval "echo EXPORTS "'> "$output_objdir/$outputname.def"'
+               $run eval 'cat "$nlist" >> "$output_objdir/$outputname.def"'
+                ;;
+              esac
            fi
          fi
 
@@ -4352,7 +4646,26 @@ extern \"C\" {
 #endif
 
 /* The mapping between symbol names and symbols. */
+"
+
+           case $host in
+           *cygwin* | *mingw* )
+         $echo >> "$output_objdir/$dlsyms" "\
+/* DATA imports from DLLs on WIN32 can't be const, because
+   runtime relocations are performed -- see ld's documentation
+   on pseudo-relocs */
+struct {
+"
+             ;;
+           * )
+         $echo >> "$output_objdir/$dlsyms" "\
 const struct {
+"
+             ;;
+           esac
+
+
+         $echo >> "$output_objdir/$dlsyms" "\
   const char *name;
   lt_ptr address;
 }
@@ -4399,16 +4712,29 @@ static const void *lt_preloaded_setup() {
          esac
 
          # Now compile the dynamic symbol file.
-         $show "(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
-         $run eval '(cd $output_objdir && $LTCC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
+         $show "(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")"
+         $run eval '(cd $output_objdir && $LTCC  $LTCFLAGS -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $?
 
          # Clean up the generated files.
          $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T"
          $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T"
 
          # Transform the symbol file into the correct name.
-         compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
-         finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"`
+          case $host in
+          *cygwin* | *mingw* )
+            if test -f "$output_objdir/${outputname}.def" ; then
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}.def $output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            else
+              compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+              finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+             fi
+            ;;
+          * )
+            compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%" | $NL2SP`
+            ;;
+          esac
          ;;
        *)
          $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2
@@ -4421,19 +4747,19 @@ static const void *lt_preloaded_setup() {
        # really was required.
 
        # Nullify the symbol file.
-       compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"`
-       finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"`
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
+       finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "s% @SYMFILE@%%" | $NL2SP`
       fi
 
       if test "$need_relink" = no || test "$build_libtool_libs" != yes; then
        # Replace the output file specification.
-       compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'`
+       compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$output"'%g' | $NL2SP`
        link_command="$compile_command$compile_rpath"
 
        # We have no uninstalled library dependencies, so finalize right now.
        $show "$link_command"
        $run eval "$link_command"
-       status=$?
+       exit_status=$?
 
        # Delete the generated files.
        if test -n "$dlsyms"; then
@@ -4441,7 +4767,7 @@ static const void *lt_preloaded_setup() {
          $run $rm "$output_objdir/${outputname}S.${objext}"
        fi
 
-       exit $status
+       exit $exit_status
       fi
 
       if test -n "$shlibpath_var"; then
@@ -4514,7 +4840,7 @@ static const void *lt_preloaded_setup() {
        if test "$fast_install" != no; then
          link_command="$finalize_var$compile_command$finalize_rpath"
          if test "$fast_install" = yes; then
-           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'`
+           relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $SP2NL | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g' | $NL2SP`
          else
            # fast_install is set to needless
            relink_command=
@@ -4551,7 +4877,7 @@ static const void *lt_preloaded_setup() {
          fi
        done
        relink_command="(cd `pwd`; $relink_command)"
-       relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+       relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
       fi
 
       # Quote $echo for shipping.
@@ -4581,10 +4907,12 @@ static const void *lt_preloaded_setup() {
        esac
        case $host in
          *cygwin* | *mingw* )
-           cwrappersource=`$echo ${objdir}/lt-${output}.c`
-           cwrapper=`$echo ${output}.exe`
-           $rm $cwrappersource $cwrapper
-           trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
+            output_name=`basename $output`
+            output_path=`dirname $output`
+            cwrappersource="$output_path/$objdir/lt-$output_name.c"
+            cwrapper="$output_path/$output_name.exe"
+            $rm $cwrappersource $cwrapper
+            trap "$rm $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15
 
            cat > $cwrappersource <<EOF
 
@@ -4609,6 +4937,9 @@ EOF
 #include <malloc.h>
 #include <stdarg.h>
 #include <assert.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/stat.h>
 
 #if defined(PATH_MAX)
 # define LT_PATHMAX PATH_MAX
@@ -4619,15 +4950,19 @@ EOF
 #endif
 
 #ifndef DIR_SEPARATOR
-#define DIR_SEPARATOR '/'
+# define DIR_SEPARATOR '/'
+# define PATH_SEPARATOR ':'
 #endif
 
 #if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \
   defined (__OS2__)
-#define HAVE_DOS_BASED_FILE_SYSTEM
-#ifndef DIR_SEPARATOR_2
-#define DIR_SEPARATOR_2 '\\'
-#endif
+# define HAVE_DOS_BASED_FILE_SYSTEM
+# ifndef DIR_SEPARATOR_2
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+# ifndef PATH_SEPARATOR_2
+#  define PATH_SEPARATOR_2 ';'
+# endif
 #endif
 
 #ifndef DIR_SEPARATOR_2
@@ -4637,17 +4972,32 @@ EOF
         (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2))
 #endif /* DIR_SEPARATOR_2 */
 
+#ifndef PATH_SEPARATOR_2
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR)
+#else /* PATH_SEPARATOR_2 */
+# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2)
+#endif /* PATH_SEPARATOR_2 */
+
 #define XMALLOC(type, num)      ((type *) xmalloc ((num) * sizeof(type)))
 #define XFREE(stale) do { \
   if (stale) { free ((void *) stale); stale = 0; } \
 } while (0)
 
+/* -DDEBUG is fairly common in CFLAGS.  */
+#undef DEBUG
+#if defined DEBUGWRAPPER
+# define DEBUG(format, ...) fprintf(stderr, format, __VA_ARGS__)
+#else
+# define DEBUG(format, ...)
+#endif
+
 const char *program_name = NULL;
 
 void * xmalloc (size_t num);
 char * xstrdup (const char *string);
-char * basename (const char *name);
-char * fnqualify(const char *path);
+const char * base_name (const char *name);
+char * find_executable(const char *wrapper);
+int    check_executable(const char *path);
 char * strendzap(char *str, const char *pat);
 void lt_fatal (const char *message, ...);
 
@@ -4657,29 +5007,51 @@ main (int argc, char *argv[])
   char **newargz;
   int i;
 
-  program_name = (char *) xstrdup ((char *) basename (argv[0]));
+  program_name = (char *) xstrdup (base_name (argv[0]));
+  DEBUG("(main) argv[0]      : %s\n",argv[0]);
+  DEBUG("(main) program_name : %s\n",program_name);
   newargz = XMALLOC(char *, argc+2);
 EOF
 
-           cat >> $cwrappersource <<EOF
-  newargz[0] = "$SHELL";
+            cat >> $cwrappersource <<EOF
+  newargz[0] = (char *) xstrdup("$SHELL");
 EOF
 
-           cat >> $cwrappersource <<"EOF"
-  newargz[1] = fnqualify(argv[0]);
+            cat >> $cwrappersource <<"EOF"
+  newargz[1] = find_executable(argv[0]);
+  if (newargz[1] == NULL)
+    lt_fatal("Couldn't find %s", argv[0]);
+  DEBUG("(main) found exe at : %s\n",newargz[1]);
   /* we know the script has the same name, without the .exe */
   /* so make sure newargz[1] doesn't end in .exe */
   strendzap(newargz[1],".exe");
   for (i = 1; i < argc; i++)
     newargz[i+1] = xstrdup(argv[i]);
   newargz[argc+1] = NULL;
+
+  for (i=0; i<argc+1; i++)
+  {
+    DEBUG("(main) newargz[%d]   : %s\n",i,newargz[i]);
+    ;
+  }
+
 EOF
 
-           cat >> $cwrappersource <<EOF
+            case $host_os in
+              mingw*)
+                cat >> $cwrappersource <<EOF
+  execv("$SHELL",(char const **)newargz);
+EOF
+              ;;
+              *)
+                cat >> $cwrappersource <<EOF
   execv("$SHELL",newargz);
 EOF
+              ;;
+            esac
 
-           cat >> $cwrappersource <<"EOF"
+            cat >> $cwrappersource <<"EOF"
+  return 127;
 }
 
 void *
@@ -4699,48 +5071,148 @@ xstrdup (const char *string)
 ;
 }
 
-char *
-basename (const char *name)
+const char *
+base_name (const char *name)
 {
   const char *base;
 
 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
   /* Skip over the disk name in MSDOS pathnames. */
-  if (isalpha (name[0]) && name[1] == ':')
+  if (isalpha ((unsigned char)name[0]) && name[1] == ':')
     name += 2;
 #endif
 
   for (base = name; *name; name++)
     if (IS_DIR_SEPARATOR (*name))
       base = name + 1;
-  return (char *) base;
+  return base;
+}
+
+int
+check_executable(const char * path)
+{
+  struct stat st;
+
+  DEBUG("(check_executable)  : %s\n", path ? (*path ? path : "EMPTY!") : "NULL!");
+  if ((!path) || (!*path))
+    return 0;
+
+  if ((stat (path, &st) >= 0) &&
+      (
+        /* MinGW & native WIN32 do not support S_IXOTH or S_IXGRP */
+#if defined (S_IXOTH)
+       ((st.st_mode & S_IXOTH) == S_IXOTH) ||
+#endif
+#if defined (S_IXGRP)
+       ((st.st_mode & S_IXGRP) == S_IXGRP) ||
+#endif
+       ((st.st_mode & S_IXUSR) == S_IXUSR))
+      )
+    return 1;
+  else
+    return 0;
 }
 
+/* Searches for the full path of the wrapper.  Returns
+   newly allocated full path name if found, NULL otherwise */
 char *
-fnqualify(const char *path)
+find_executable (const char* wrapper)
 {
-  size_t size;
-  char *p;
+  int has_slash = 0;
+  const char* p;
+  const char* p_next;
+  /* static buffer for getcwd */
   char tmp[LT_PATHMAX + 1];
+  int tmp_len;
+  char* concat_name;
+
+  DEBUG("(find_executable)  : %s\n", wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!");
 
-  assert(path != NULL);
+  if ((wrapper == NULL) || (*wrapper == '\0'))
+    return NULL;
 
-  /* Is it qualified already? */
+  /* Absolute path? */
+#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+  if (isalpha ((unsigned char)wrapper[0]) && wrapper[1] == ':')
+  {
+    concat_name = xstrdup (wrapper);
+    if (check_executable(concat_name))
+      return concat_name;
+    XFREE(concat_name);
+  }
+  else
+  {
+#endif
+    if (IS_DIR_SEPARATOR (wrapper[0]))
+    {
+      concat_name = xstrdup (wrapper);
+      if (check_executable(concat_name))
+        return concat_name;
+      XFREE(concat_name);
+    }
 #if defined (HAVE_DOS_BASED_FILE_SYSTEM)
-  if (isalpha (path[0]) && path[1] == ':')
-    return xstrdup (path);
+  }
 #endif
-  if (IS_DIR_SEPARATOR (path[0]))
-    return xstrdup (path);
 
-  /* prepend the current directory */
-  /* doesn't handle '~' */
+  for (p = wrapper; *p; p++)
+    if (*p == '/')
+    {
+      has_slash = 1;
+      break;
+    }
+  if (!has_slash)
+  {
+    /* no slashes; search PATH */
+    const char* path = getenv ("PATH");
+    if (path != NULL)
+    {
+      for (p = path; *p; p = p_next)
+      {
+        const char* q;
+        size_t p_len;
+        for (q = p; *q; q++)
+          if (IS_PATH_SEPARATOR(*q))
+            break;
+        p_len = q - p;
+        p_next = (*q == '\0' ? q : q + 1);
+        if (p_len == 0)
+        {
+          /* empty path: current directory */
+          if (getcwd (tmp, LT_PATHMAX) == NULL)
+            lt_fatal ("getcwd failed");
+          tmp_len = strlen(tmp);
+          concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, tmp, tmp_len);
+          concat_name[tmp_len] = '/';
+          strcpy (concat_name + tmp_len + 1, wrapper);
+        }
+        else
+        {
+          concat_name = XMALLOC(char, p_len + 1 + strlen(wrapper) + 1);
+          memcpy (concat_name, p, p_len);
+          concat_name[p_len] = '/';
+          strcpy (concat_name + p_len + 1, wrapper);
+        }
+        if (check_executable(concat_name))
+          return concat_name;
+        XFREE(concat_name);
+      }
+    }
+    /* not found in PATH; assume curdir */
+  }
+  /* Relative path | not found in path: prepend cwd */
   if (getcwd (tmp, LT_PATHMAX) == NULL)
     lt_fatal ("getcwd failed");
-  size = strlen(tmp) + 1 + strlen(path) + 1; /* +2 for '/' and '\0' */
-  p = XMALLOC(char, size);
-  sprintf(p, "%s%c%s", tmp, DIR_SEPARATOR, path);
-  return p;
+  tmp_len = strlen(tmp);
+  concat_name = XMALLOC(char, tmp_len + 1 + strlen(wrapper) + 1);
+  memcpy (concat_name, tmp, tmp_len);
+  concat_name[tmp_len] = '/';
+  strcpy (concat_name + tmp_len + 1, wrapper);
+
+  if (check_executable(concat_name))
+    return concat_name;
+  XFREE(concat_name);
+  return NULL;
 }
 
 char *
@@ -4784,16 +5256,16 @@ lt_fatal (const char *message, ...)
   va_end (ap);
 }
 EOF
-         # we should really use a build-platform specific compiler
-         # here, but OTOH, the wrappers (shell script and this C one)
-         # are only useful if you want to execute the "real" binary.
-         # Since the "real" binary is built for $host, then this
-         # wrapper might as well be built for $host, too.
-         $run $LTCC -s -o $cwrapper $cwrappersource
-         ;;
-       esac
-       $rm $output
-       trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
+          # we should really use a build-platform specific compiler
+          # here, but OTOH, the wrappers (shell script and this C one)
+          # are only useful if you want to execute the "real" binary.
+          # Since the "real" binary is built for $host, then this
+          # wrapper might as well be built for $host, too.
+          $run $LTCC $LTCFLAGS -s -o $cwrapper $cwrappersource
+          ;;
+        esac
+        $rm $output
+        trap "$rm $output; exit $EXIT_FAILURE" 1 2 15
 
        $echo > $output "\
 #! $SHELL
@@ -4812,9 +5284,21 @@ EOF
 Xsed='${SED} -e 1s/^X//'
 sed_quote_subst='$sed_quote_subst'
 
+# Be Bourne compatible (taken from Autoconf:_AS_BOURNE_COMPATIBLE).
+if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then
+  emulate sh
+  NULLCMD=:
+  # Zsh 3.x and 4.x performs word splitting on \${1+\"\$@\"}, which
+  # is contrary to our usage.  Disable this feature.
+  alias -g '\${1+\"\$@\"}'='\"\$@\"'
+  setopt NO_GLOB_SUBST
+else
+  case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac
+fi
+
 # The HP-UX ksh and POSIX shell print the target directory to stdout
 # if CDPATH is set.
-if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
 
 relink_command=\"$relink_command\"
 
@@ -4943,23 +5427,23 @@ else
        # Backslashes separate directories on plain windows
        *-*-mingw | *-*-os2*)
          $echo >> $output "\
-      exec \$progdir\\\\\$program \${1+\"\$@\"}
+      exec \"\$progdir\\\\\$program\" \${1+\"\$@\"}
 "
          ;;
 
        *)
          $echo >> $output "\
-      exec \$progdir/\$program \${1+\"\$@\"}
+      exec \"\$progdir/\$program\" \${1+\"\$@\"}
 "
          ;;
        esac
        $echo >> $output "\
-      \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\"
+      \$echo \"\$0: cannot exec \$program \$*\"
       exit $EXIT_FAILURE
     fi
   else
     # The program doesn't exist.
-    \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2
+    \$echo \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2
     \$echo \"This script is just a wrapper for \$program.\" 1>&2
     $echo \"See the $PACKAGE documentation for more information.\" 1>&2
     exit $EXIT_FAILURE
@@ -4991,71 +5475,73 @@ fi\
 
       if test -n "$addlibs"; then
        gentop="$output_objdir/${outputname}x"
-       $show "${rm}r $gentop"
-       $run ${rm}r "$gentop"
-       $show "$mkdir $gentop"
-       $run $mkdir "$gentop"
-       status=$?
-       if test "$status" -ne 0 && test ! -d "$gentop"; then
-         exit $status
-       fi
        generated="$generated $gentop"
 
-       # Add in members from convenience archives.
-       for xlib in $addlibs; do
-         # Extract the objects.
-         case $xlib in
-         [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;;
-         *) xabs=`pwd`"/$xlib" ;;
-         esac
-         xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'`
-         xdir="$gentop/$xlib"
-
-         $show "${rm}r $xdir"
-         $run ${rm}r "$xdir"
-         $show "$mkdir $xdir"
-         $run $mkdir "$xdir"
-         status=$?
-         if test "$status" -ne 0 && test ! -d "$xdir"; then
-           exit $status
-         fi
-         # We will extract separately just the conflicting names and we will no
-         # longer touch any unique names. It is faster to leave these extract
-         # automatically by $AR in one run.
-         $show "(cd $xdir && $AR x $xabs)"
-         $run eval "(cd \$xdir && $AR x \$xabs)" || exit $?
-         if ($AR t "$xabs" | sort | sort -uc >/dev/null 2>&1); then
-           :
-         else
-           $echo "$modename: warning: object name conflicts; renaming object files" 1>&2
-           $echo "$modename: warning: to ensure that they will not overwrite" 1>&2
-           $AR t "$xabs" | sort | uniq -cd | while read -r count name
-           do
-             i=1
-             while test "$i" -le "$count"
-             do
-              # Put our $i before any first dot (extension)
-              # Never overwrite any file
-              name_to="$name"
-              while test "X$name_to" = "X$name" || test -f "$xdir/$name_to"
-              do
-                name_to=`$echo "X$name_to" | $Xsed -e "s/\([^.]*\)/\1-$i/"`
-              done
-              $show "(cd $xdir && $AR xN $i $xabs '$name' && $mv '$name' '$name_to')"
-              $run eval "(cd \$xdir && $AR xN $i \$xabs '$name' && $mv '$name' '$name_to')" || exit $?
-              i=`expr $i + 1`
-             done
-           done
-         fi
-
-         oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP`
-       done
+       func_extract_archives $gentop $addlibs
+       oldobjs="$oldobjs $func_extract_archives_result"
       fi
 
       # Do each command in the archive commands.
       if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then
        cmds=$old_archive_from_new_cmds
       else
+       # POSIX demands no paths to be encoded in archives.  We have
+       # to avoid creating archives with duplicate basenames if we
+       # might have to extract them afterwards, e.g., when creating a
+       # static archive out of a convenience library, or when linking
+       # the entirety of a libtool archive into another (currently
+       # not supported by libtool).
+       if (for obj in $oldobjs
+           do
+             $echo "X$obj" | $Xsed -e 's%^.*/%%'
+           done | sort | sort -uc >/dev/null 2>&1); then
+         :
+       else
+         $echo "copying selected object files to avoid basename conflicts..."
+
+         if test -z "$gentop"; then
+           gentop="$output_objdir/${outputname}x"
+           generated="$generated $gentop"
+
+           $show "${rm}r $gentop"
+           $run ${rm}r "$gentop"
+           $show "$mkdir $gentop"
+           $run $mkdir "$gentop"
+           exit_status=$?
+           if test "$exit_status" -ne 0 && test ! -d "$gentop"; then
+             exit $exit_status
+           fi
+         fi
+
+         save_oldobjs=$oldobjs
+         oldobjs=
+         counter=1
+         for obj in $save_oldobjs
+         do
+           objbase=`$echo "X$obj" | $Xsed -e 's%^.*/%%'`
+           case " $oldobjs " in
+           " ") oldobjs=$obj ;;
+           *[\ /]"$objbase "*)
+             while :; do
+               # Make sure we don't pick an alternate name that also
+               # overlaps.
+               newobj=lt$counter-$objbase
+               counter=`expr $counter + 1`
+               case " $oldobjs " in
+               *[\ /]"$newobj "*) ;;
+               *) if test ! -f "$gentop/$newobj"; then break; fi ;;
+               esac
+             done
+             $show "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj"
+             $run ln "$obj" "$gentop/$newobj" ||
+             $run cp "$obj" "$gentop/$newobj"
+             oldobjs="$oldobjs $gentop/$newobj"
+             ;;
+           *) oldobjs="$oldobjs $obj" ;;
+           esac
+         done
+       fi
+
        eval cmds=\"$old_archive_cmds\"
 
        if len=`expr "X$cmds" : ".*"` &&
@@ -5069,20 +5555,7 @@ fi\
          objlist=
          concat_cmds=
          save_oldobjs=$oldobjs
-         # GNU ar 2.10+ was changed to match POSIX; thus no paths are
-         # encoded into archives.  This makes 'ar r' malfunction in
-         # this piecewise linking case whenever conflicting object
-         # names appear in distinct ar calls; check, warn and compensate.
-           if (for obj in $save_oldobjs
-           do
-             $echo "X$obj" | $Xsed -e 's%^.*/%%'
-           done | sort | sort -uc >/dev/null 2>&1); then
-           :
-         else
-           $echo "$modename: warning: object name conflicts; overriding AR_FLAGS to 'cq'" 1>&2
-           $echo "$modename: warning: to ensure that POSIX-compatible ar will work" 1>&2
-           AR_FLAGS=cq
-         fi
+
          # Is there a better way of finding the last object in the list?
          for obj in $save_oldobjs
          do
@@ -5093,7 +5566,7 @@ fi\
            oldobjs="$objlist $obj"
            objlist="$objlist $obj"
            eval test_cmds=\"$old_archive_cmds\"
-           if len=`expr "X$test_cmds" : ".*"` &&
+           if len=`expr "X$test_cmds" : ".*" 2>/dev/null` &&
               test "$len" -le "$max_cmd_len"; then
              :
            else
@@ -5151,7 +5624,7 @@ fi\
       done
       # Quote the link command for shipping.
       relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)"
-      relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"`
+      relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e "$sed_quote_subst" | $NL2SP`
       if test "$hardcode_automatic" = yes ; then
        relink_command=
       fi
@@ -5290,11 +5763,11 @@ relink_command=\"$relink_command\""
     # install_prog (especially on Windows NT).
     if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh ||
        # Allow the use of GNU shtool's install command.
-       $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then
+       $echo "X$nonopt" | grep shtool > /dev/null; then
       # Aesthetically quote it.
       arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        arg="\"$arg\""
        ;;
       esac
@@ -5303,14 +5776,14 @@ relink_command=\"$relink_command\""
       shift
     else
       install_prog=
-      arg="$nonopt"
+      arg=$nonopt
     fi
 
     # The real first argument should be the name of the installation program.
     # Aesthetically quote it.
     arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
     case $arg in
-    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*)
+    *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \      ]*|*]*|"")
       arg="\"$arg\""
       ;;
     esac
@@ -5328,28 +5801,31 @@ relink_command=\"$relink_command\""
     do
       if test -n "$dest"; then
        files="$files $dest"
-       dest="$arg"
+       dest=$arg
        continue
       fi
 
       case $arg in
       -d) isdir=yes ;;
-      -f) prev="-f" ;;
-      -g) prev="-g" ;;
-      -m) prev="-m" ;;
-      -o) prev="-o" ;;
+      -f) 
+       case " $install_prog " in
+       *[\\\ /]cp\ *) ;;
+       *) prev=$arg ;;
+       esac
+       ;;
+      -g | -m | -o) prev=$arg ;;
       -s)
        stripme=" -s"
        continue
        ;;
-      -*) ;;
-
+      -*)
+       ;;
       *)
        # If the previous option needed an argument, then skip it.
        if test -n "$prev"; then
          prev=
        else
-         dest="$arg"
+         dest=$arg
          continue
        fi
        ;;
@@ -5358,7 +5834,7 @@ relink_command=\"$relink_command\""
       # Aesthetically quote the argument.
       arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`
       case $arg in
-      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*)
+      *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \    ]*|*]*|"")
        arg="\"$arg\""
        ;;
       esac
@@ -5493,9 +5969,9 @@ relink_command=\"$relink_command\""
 
          if test -n "$inst_prefix_dir"; then
            # Stick the inst_prefix_dir data into the link command.
-           relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"`
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%" | $NL2SP`
          else
-           relink_command=`$echo "$relink_command" | $SED "s%@inst_prefix_dir@%%"`
+           relink_command=`$echo "$relink_command" | $SP2NL | $SED "s%@inst_prefix_dir@%%" | $NL2SP`
          fi
 
          $echo "$modename: warning: relinking \`$file'" 1>&2
@@ -5527,11 +6003,14 @@ relink_command=\"$relink_command\""
 
          if test "$#" -gt 0; then
            # Delete the old symlinks, and create new ones.
+           # Try `ln -sf' first, because the `ln' binary might depend on
+           # the symlink we replace!  Solaris /bin/ln does not understand -f,
+           # so we also need to try rm && ln -s.
            for linkname
            do
              if test "$linkname" != "$realname"; then
-               $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
-               $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)"
+                $show "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
+                $run eval "(cd $destdir && { $LN_S -f $realname $linkname || { $rm $linkname && $LN_S $realname $linkname; }; })"
              fi
            done
          fi
@@ -5544,7 +6023,16 @@ relink_command=\"$relink_command\""
            IFS="$save_ifs"
            eval cmd=\"$cmd\"
            $show "$cmd"
-           $run eval "$cmd" || exit $?
+           $run eval "$cmd" || {
+             lt_exit=$?
+
+             # Restore the uninstalled library and exit
+             if test "$mode" = relink; then
+               $run eval '(cd $output_objdir && $rm ${realname}T && $mv ${realname}U $realname)'
+             fi
+
+             exit $lt_exit
+           }
          done
          IFS="$save_ifs"
        fi
@@ -5638,17 +6126,15 @@ relink_command=\"$relink_command\""
          notinst_deplibs=
          relink_command=
 
-         # To insure that "foo" is sourced, and not "foo.exe",
-         # finese the cygwin/MSYS system by explicitly sourcing "foo."
-         # which disallows the automatic-append-.exe behavior.
-         case $build in
-         *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
-         *) wrapperdot=${wrapper} ;;
-         esac
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
          # If there is no directory component, then add one.
-         case $file in
-         */* | *\\*) . ${wrapperdot} ;;
-         *) . ./${wrapperdot} ;;
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
          esac
 
          # Check the variables that should have been set.
@@ -5676,38 +6162,25 @@ relink_command=\"$relink_command\""
          done
 
          relink_command=
-         # To insure that "foo" is sourced, and not "foo.exe",
-         # finese the cygwin/MSYS system by explicitly sourcing "foo."
-         # which disallows the automatic-append-.exe behavior.
-         case $build in
-         *cygwin* | *mingw*) wrapperdot=${wrapper}. ;;
-         *) wrapperdot=${wrapper} ;;
-         esac
+         # Note that it is not necessary on cygwin/mingw to append a dot to
+         # foo even if both foo and FILE.exe exist: automatic-append-.exe
+         # behavior happens only for exec(3), not for open(2)!  Also, sourcing
+         # `FILE.' does not work on cygwin managed mounts.
+         #
          # If there is no directory component, then add one.
-         case $file in
-         */* | *\\*) . ${wrapperdot} ;;
-         *) . ./${wrapperdot} ;;
+         case $wrapper in
+         */* | *\\*) . ${wrapper} ;;
+         *) . ./${wrapper} ;;
          esac
 
          outputname=
          if test "$fast_install" = no && test -n "$relink_command"; then
            if test "$finalize" = yes && test -z "$run"; then
-             tmpdir="/tmp"
-             test -n "$TMPDIR" && tmpdir="$TMPDIR"
-             tmpdir="$tmpdir/libtool-$$"
-             save_umask=`umask`
-             umask 0077
-             if $mkdir "$tmpdir"; then
-               umask $save_umask
-             else
-               umask $save_umask
-               $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2
-               continue
-             fi
+             tmpdir=`func_mktempdir`
              file=`$echo "X$file$stripped_ext" | $Xsed -e 's%^.*/%%'`
              outputname="$tmpdir/$file"
              # Replace the output file specification.
-             relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'`
+             relink_command=`$echo "X$relink_command" | $SP2NL | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g' | $NL2SP`
 
              $show "$relink_command"
              if $run eval "$relink_command"; then :
@@ -5727,7 +6200,7 @@ relink_command=\"$relink_command\""
        fi
 
        # remove .exe since cygwin /usr/bin/install will append another
-       # one anyways
+       # one anyway 
        case $install_prog,$host in
        */usr/bin/install*,*cygwin*)
          case $file:$destfile in
@@ -5827,7 +6300,7 @@ relink_command=\"$relink_command\""
     # Exit here if they wanted silent mode.
     test "$show" = : && exit $EXIT_SUCCESS
 
-    $echo "----------------------------------------------------------------------"
+    $echo "X----------------------------------------------------------------------" | $Xsed
     $echo "Libraries have been installed in:"
     for libdir in $libdirs; do
       $echo "   $libdir"
@@ -5860,7 +6333,7 @@ relink_command=\"$relink_command\""
     $echo
     $echo "See any operating system documentation about shared libraries for"
     $echo "more information, such as the ld(1) and ld.so(8) manual pages."
-    $echo "----------------------------------------------------------------------"
+    $echo "X----------------------------------------------------------------------" | $Xsed
     exit $EXIT_SUCCESS
     ;;
 
@@ -5983,12 +6456,15 @@ relink_command=\"$relink_command\""
       fi
 
       # Restore saved environment variables
-      if test "${save_LC_ALL+set}" = set; then
-       LC_ALL="$save_LC_ALL"; export LC_ALL
-      fi
-      if test "${save_LANG+set}" = set; then
-       LANG="$save_LANG"; export LANG
-      fi
+      for lt_var in LANG LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES
+      do
+       eval "if test \"\${save_$lt_var+set}\" = set; then
+               $lt_var=\$save_$lt_var; export $lt_var
+             else
+               $lt_unset $lt_var
+             fi"
+      done
+
 
       # Now prepare to actually exec the command.
       exec_cmd="\$cmd$args"
@@ -6077,9 +6553,17 @@ relink_command=\"$relink_command\""
            rmfiles="$rmfiles $objdir/$n"
          done
          test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library"
-         test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
 
-         if test "$mode" = uninstall; then
+         case "$mode" in
+         clean)
+           case "  $library_names " in
+           # "  " in the beginning catches empty $dlname
+           *" $dlname "*) ;;
+           *) rmfiles="$rmfiles $objdir/$dlname" ;;
+           esac
+            test -n "$libdir" && rmfiles="$rmfiles $objdir/$name $objdir/${name}i"
+           ;;
+         uninstall)
            if test -n "$library_names"; then
              # Do each command in the postuninstall commands.
              cmds=$postuninstall_cmds
@@ -6112,7 +6596,8 @@ relink_command=\"$relink_command\""
              IFS="$save_ifs"
            fi
            # FIXME: should reinstall the best remaining shared library.
-         fi
+           ;;
+         esac
        fi
        ;;
 
@@ -6336,9 +6821,9 @@ The following components of LINK-COMMAND are treated specially:
   -dlpreopen FILE   link in FILE and add its symbols to lt_preloaded_symbols
   -export-dynamic   allow symbols from OUTPUT-FILE to be resolved with dlsym(3)
   -export-symbols SYMFILE
-                   try to export only the symbols listed in SYMFILE
+                    try to export only the symbols listed in SYMFILE
   -export-symbols-regex REGEX
-                   try to export only the symbols matching REGEX
+                    try to export only the symbols matching REGEX
   -LLIBDIR          search LIBDIR for required installed libraries
   -lNAME            OUTPUT-FILE requires the installed library libNAME
   -module           build a library that can dlopened
@@ -6352,9 +6837,11 @@ The following components of LINK-COMMAND are treated specially:
   -release RELEASE  specify package release information
   -rpath LIBDIR     the created library will eventually be installed in LIBDIR
   -R[ ]LIBDIR       add LIBDIR to the runtime path of programs and libraries
-  -static           do not do any dynamic linking of libtool libraries
+  -static           do not do any dynamic linking of uninstalled libtool libraries
+  -static-libtool-libs
+                    do not do any dynamic linking of libtool libraries
   -version-info CURRENT[:REVISION[:AGE]]
-                   specify library version info [each variable defaults to 0]
+                    specify library version info [each variable defaults to 0]
 
 All other options (arguments beginning with \`-') are ignored.
 
@@ -6397,7 +6884,7 @@ esac
 $echo
 $echo "Try \`$modename --help' for more information about other modes."
 
-exit $EXIT_SUCCESS
+exit $?
 
 # The TAGs below are defined such that we never get into a situation
 # in which we disable both kinds of libraries.  Given conflicting
@@ -6411,12 +6898,11 @@ exit $EXIT_SUCCESS
 # configuration.  But we'll never go from static-only to shared-only.
 
 # ### BEGIN LIBTOOL TAG CONFIG: disable-shared
-build_libtool_libs=no
-build_old_libs=yes
+disable_libs=shared
 # ### END LIBTOOL TAG CONFIG: disable-shared
 
 # ### BEGIN LIBTOOL TAG CONFIG: disable-static
-build_old_libs=`case $build_libtool_libs in yes) $echo no;; *) $echo yes;; esac`
+disable_libs=static
 # ### END LIBTOOL TAG CONFIG: disable-static
 
 # Local Variables:
index 9d46119..fa11fd8 100644 (file)
@@ -1,20 +1,20 @@
-AUTOMAKE_OPTIONS = foreign\r
-\r
-plugindir = $(libdir)/@PACKAGE@\r
-plugin_LTLIBRARIES = memcache-store.la\r
-\r
-AM_CFLAGS = $(MEMCACHED_CFLAGS)\r
-AM_CXXFLAGS = $(MEMCACHED_CFLAGS)\r
-\r
-memcache_store_la_LIBADD = \\r
-       $(MEMCACHED_LIBS)\r
-\r
-memcache_store_la_SOURCES = \\r
-       memcache-store.cpp\r
-\r
-memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)\r
-\r
-install-exec-hook:\r
-       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done\r
-\r
-EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h\r
+AUTOMAKE_OPTIONS = foreign
+
+plugindir = $(libdir)/@PACKAGE@
+plugin_LTLIBRARIES = memcache-store.la
+
+AM_CFLAGS = $(MEMCACHED_CFLAGS)
+AM_CXXFLAGS = $(MEMCACHED_CFLAGS)
+
+memcache_store_la_LIBADD = \
+       $(MEMCACHED_LIBS)
+
+memcache_store_la_SOURCES = \
+       memcache-store.cpp
+
+memcache_store_la_LDFLAGS = -module -avoid-version $(XMLSEC_LIBS)
+
+install-exec-hook:
+       for la in $(plugin_LTLIBRARIES) ; do rm -f $(DESTDIR)$(plugindir)/$$la ; done
+
+EXTRA_DIST = memcache-store.vcproj memcache-store.rc resource.h
index 105883a..1c5d4a4 100644 (file)
@@ -82,6 +82,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index c208108..49d238d 100644 (file)
-/*\r
- *  Copyright 2001-2008 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * memcache-store.cpp\r
- *\r
- * Storage Service using memcache (pre memcache tags)\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-# define MCEXT_EXPORTS __declspec(dllexport)\r
-#else\r
-# define MCEXT_EXPORTS\r
-#endif\r
-\r
-#include <xmltooling/base.h>\r
-\r
-#include <iostream> \r
-#include <libmemcached/memcached.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-#include <xmltooling/logging.h>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/NDC.h>\r
-#include <xmltooling/util/StorageService.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace xercesc;\r
-using namespace std;\r
-\r
-namespace xmltooling {\r
-  static const XMLCh Hosts[] = UNICODE_LITERAL_5(H,o,s,t,s);\r
-  static const XMLCh prefix[] = UNICODE_LITERAL_6(p,r,e,f,i,x);\r
-  static const XMLCh buildMap[] = UNICODE_LITERAL_8(b,u,i,l,d,M,a,p);\r
-  \r
-  class mc_record {\r
-  public:\r
-    string value;\r
-    time_t expiration;\r
-    mc_record(){};\r
-    mc_record(string _v, time_t _e) :\r
-      value(_v), expiration(_e)\r
-    {}\r
-  };\r
-\r
-  class MemcacheBase {\r
-  public:\r
-    MemcacheBase(const DOMElement* e);\r
-    ~MemcacheBase();\r
-        \r
-    bool addMemcache(const char *key,\r
-                     string &value,\r
-                     time_t timeout,\r
-                     uint32_t flags,\r
-                     bool use_prefix = true);\r
-    bool setMemcache(const char *key,\r
-                     string &value,\r
-                     time_t timeout,\r
-                     uint32_t flags,\r
-                     bool use_prefix = true);\r
-    bool replaceMemcache(const char *key,\r
-                         string &value,\r
-                         time_t timeout,\r
-                         uint32_t flags,\r
-                         bool use_prefix = true);\r
-    bool getMemcache(const char *key,\r
-                     string &dest,\r
-                     uint32_t *flags,\r
-                     bool use_prefix = true);\r
-    bool deleteMemcache(const char *key,\r
-                        time_t timeout,\r
-                        bool use_prefix = true);\r
-\r
-    void serialize(mc_record &source, string &dest);\r
-    void serialize(list<string> &source, string &dest);\r
-    void deserialize(string &source, mc_record &dest);\r
-    void deserialize(string &source, list<string> &dest);\r
-\r
-    bool addSessionToUser(string &key, string &user);\r
-    bool addLock(string what, bool use_prefix = true);\r
-    void deleteLock(string what, bool use_prefix = true);\r
-\r
-  protected:\r
-    const DOMElement* m_root; // can only use this during initialization\r
-    Category& log;\r
-    memcached_st *memc;\r
-    string m_memcacheHosts;\r
-    string m_prefix;\r
-    Mutex* m_lock;\r
-  };\r
-  \r
-  class MemcacheStorageService : public StorageService, public MemcacheBase {\r
-\r
-  public:\r
-    MemcacheStorageService(const DOMElement* e);\r
-    ~MemcacheStorageService();\r
-    \r
-    bool createString(const char* context, const char* key, const char* value, time_t expiration);\r
-    int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);\r
-    int updateString(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0);\r
-    bool deleteString(const char* context, const char* key);\r
-    \r
-    bool createText(const char* context, const char* key, const char* value, time_t expiration) {\r
-      return createString(context, key, value, expiration);\r
-    }\r
-    int readText(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0) {\r
-      return readString(context, key, pvalue, pexpiration, version);\r
-    }\r
-    int updateText(const char* context, const char* key, const char* value=NULL, time_t expiration=0, int version=0) {\r
-      return updateString(context, key, value, expiration, version);\r
-    }\r
-    bool deleteText(const char* context, const char* key) {\r
-      return deleteString(context, key);\r
-    }\r
-    \r
-    void reap(const char* context) {}\r
-\r
-    void updateContext(const char* context, time_t expiration);\r
-    void deleteContext(const char* context);\r
-\r
-    private:\r
-\r
-    Category& m_log;\r
-    bool m_buildMap;\r
-\r
-\r
-  };\r
-\r
-  StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {\r
-    return new MemcacheStorageService(e);\r
-  }\r
-\r
-};\r
-\r
-bool MemcacheBase::addLock(string what, bool use_prefix) {\r
-  string lock_name = what + ":LOCK";\r
-  string set_val = "1";\r
-  unsigned tries = 5;\r
-  while (!addMemcache(lock_name.c_str(), set_val, 5, 0, use_prefix)) {\r
-    if (tries-- == 0) {\r
-      log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());\r
-      return false;\r
-    }\r
-    log.debug("Unable to get lock %s... Retrying.", lock_name.c_str());\r
-    \r
-    // sleep 100ms\r
-#ifdef WIN32\r
-    Sleep(100);\r
-#else\r
-    struct timeval tv = { 0, 100000 };\r
-    select(0, 0, 0, 0, &tv);\r
-#endif\r
-  }\r
-  return true;\r
-}\r
-\r
-void MemcacheBase::deleteLock(string what, bool use_prefix) {\r
-\r
-  string lock_name = what + ":LOCK";\r
-  deleteMemcache(lock_name.c_str(), 0, use_prefix);\r
-  return;\r
-\r
-}  \r
-\r
-void MemcacheBase::deserialize(string &source, mc_record &dest) {\r
-  istringstream is(source, stringstream::in | stringstream::out);\r
-  is >> dest.expiration;\r
-  is.ignore(1); // ignore delimiter\r
-  dest.value = is.str().c_str() + is.tellg();\r
-}\r
-\r
-void MemcacheBase::deserialize(string &source, list<string> &dest) {\r
-  istringstream is(source, stringstream::in | stringstream::out);\r
-  while (!is.eof()) {\r
-    string s;\r
-    is >> s;\r
-    dest.push_back(s);\r
-  }  \r
-}\r
-\r
-void MemcacheBase::serialize(mc_record &source, string &dest) {\r
-  ostringstream os(stringstream::in | stringstream::out);\r
-  os << source.expiration;\r
-  os << "-"; // delimiter\r
-  os << source.value;\r
-  dest = os.str();\r
-}\r
-\r
-void MemcacheBase::serialize(list<string> &source, string &dest) {  \r
-  ostringstream os(stringstream::in | stringstream::out);\r
-  for(list<string>::iterator iter = source.begin(); iter != source.end(); iter++) {\r
-    if (iter != source.begin()) {\r
-      os << endl;\r
-    }\r
-    os << *iter;\r
-  }\r
-  dest = os.str();\r
-}\r
-\r
-bool MemcacheBase::addSessionToUser(string &key, string &user) {\r
-\r
-  if (! addLock(user, false)) {\r
-    return false;\r
-  }\r
-\r
-  // Aquired lock\r
-\r
-  string sessid = m_prefix + key; // add specific prefix to session\r
-  string delimiter = ";";\r
-  string user_key = "UDATA:";\r
-  user_key += user;\r
-  string user_val;\r
-  uint32_t flags;\r
-  bool result = getMemcache(user_key.c_str(), user_val, &flags, false);\r
-\r
-  if (result) {\r
-    bool already_there = false;\r
-    // skip delimiters at beginning.\r
-    string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);\r
-    \r
-    // find first "non-delimiter".\r
-    string::size_type pos = user_val.find_first_of(delimiter, lastPos);\r
-    \r
-    while (string::npos != pos || string::npos != lastPos) {\r
-      // found a token, add it to the vector.\r
-      string session = user_val.substr(lastPos, pos - lastPos);\r
-      if (strcmp(session.c_str(), sessid.c_str()) == 0) {\r
-        already_there = true;\r
-        break;\r
-      }\r
-      \r
-      // skip delimiters.  Note the "not_of"\r
-      lastPos = user_val.find_first_not_of(delimiter, pos);\r
-      \r
-      // find next "non-delimiter"\r
-      pos = user_val.find_first_of(delimiter, lastPos);\r
-    }\r
-    \r
-    if (!already_there) {\r
-      user_val += delimiter + sessid;\r
-      replaceMemcache(user_key.c_str(), user_val, 0, 0, false);\r
-    }\r
-  } else {\r
-    addMemcache(user_key.c_str(), sessid, 0, 0, false);\r
-  }\r
-\r
-  deleteLock(user, false);\r
-  return true;\r
-  \r
-}\r
-\r
-bool MemcacheBase::deleteMemcache(const char *key,\r
-                                  time_t timeout,\r
-                                  bool use_prefix) {\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTFOUND) {\r
-    // Key wasn't there... No biggie.\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    log.error(string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
-    success = false;\r
-  } else {\r
-    log.error(string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv));\r
-    // shouldn't be here\r
-    success = false;\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::getMemcache(const char *key,\r
-                               string &dest,\r
-                               uint32_t *flags,\r
-                               bool use_prefix) {\r
-  memcached_return rv;\r
-  size_t len;\r
-  char *result;\r
-  string final_key;\r
-  bool success;\r
-  \r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    dest = result;\r
-    free(result);\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTFOUND) {\r
-    log.debug("Key %s not found in memcache...", key);\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    log.error(string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
-    success = false;\r
-  } else {\r
-    log.error(string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv));\r
-    success = false;\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::addMemcache(const char *key,\r
-                               string &value,\r
-                               time_t timeout,\r
-                               uint32_t flags,\r
-                               bool use_prefix) {\r
-\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTSTORED) {\r
-    // already there\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    log.error(string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
-    success = false;\r
-  } else {\r
-    // shouldn't be here\r
-    log.error(string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv));\r
-    success = false;\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::setMemcache(const char *key,\r
-                               string &value,\r
-                               time_t timeout,\r
-                               uint32_t flags,\r
-                               bool use_prefix) {\r
-\r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    log.error(string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
-    success = false;\r
-  } else {\r
-    // shouldn't be here\r
-    log.error(string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv));\r
-    success = false;\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-bool MemcacheBase::replaceMemcache(const char *key,\r
-                                   string &value,\r
-                                   time_t timeout,\r
-                                   uint32_t flags,\r
-                                   bool use_prefix) {\r
-  \r
-  memcached_return rv;\r
-  string final_key;\r
-  bool success;\r
-\r
-  if (use_prefix) {\r
-    final_key = m_prefix + key;\r
-  } else {\r
-    final_key = key;\r
-  }\r
-\r
-  m_lock->lock();\r
-  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);\r
-  m_lock->unlock();\r
-\r
-  if (rv == MEMCACHED_SUCCESS) {\r
-    success = true;\r
-  } else if (rv == MEMCACHED_NOTSTORED) {\r
-    // not there\r
-    success = false;\r
-  } else if (rv == MEMCACHED_ERRNO) {\r
-    // System error\r
-    log.error(string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno)));\r
-    success = false;\r
-  } else {\r
-    // shouldn't be here\r
-    log.error(string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv));\r
-    success = false;\r
-  }\r
-\r
-  return success;\r
-}\r
-\r
-MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_memcacheHosts(""), m_prefix("") {\r
-\r
-  auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);\r
-  if (p.get() && *p.get()) {\r
-    log.debug("INIT: GOT key prefix: %s", p.get());\r
-    m_prefix = p.get();\r
-  }\r
-\r
-  // Grab hosts from the configuration.\r
-  e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;\r
-  if (!e || !e->hasChildNodes()) {\r
-    throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");\r
-  }\r
-  auto_ptr_char h(e->getFirstChild()->getNodeValue());\r
-  log.debug("INIT: GOT Hosts: %s", h.get());\r
-  m_memcacheHosts = h.get();\r
-\r
-  m_lock = Mutex::create();\r
-  log.debug("Lock created");\r
-\r
-  memc = memcached_create(NULL);\r
-  if (memc == NULL) {\r
-    throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");\r
-  }\r
-\r
-  log.debug("Memcache created");\r
-\r
-  unsigned int hash = MEMCACHED_HASH_CRC;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);\r
-  log.debug("CRC hash set");\r
-\r
-  int32_t timeout = 1000000;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, timeout);\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, timeout);\r
-\r
-  int32_t poll_timeout = 1000;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);\r
-\r
-  int32_t fail_limit = 5;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);\r
-\r
-  int32_t retry_timeout = 30;\r
-  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);\r
-\r
-  memcached_server_st *servers;\r
-  servers = memcached_servers_parse((char *)m_memcacheHosts.c_str());\r
-  log.debug("Got %u hosts.",  memcached_server_list_count(servers));\r
-  if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {\r
-    throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed");    \r
-  }\r
-  memcached_server_list_free(servers);\r
-\r
-  log.debug("Memcache object initialized");\r
-}\r
-\r
-MemcacheBase::~MemcacheBase() {\r
-  memcached_free(memc);\r
-  delete m_lock;\r
-  log.debug("Base object destroyed");\r
-}\r
-\r
-MemcacheStorageService::MemcacheStorageService(const DOMElement* e)\r
-  : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {\r
-\r
-    const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;\r
-    if (tag && *tag && XMLString::parseInt(tag) != 0) {\r
-        m_buildMap = true;\r
-        m_log.debug("Cache built with buildMap ON");\r
-    }\r
-\r
-}\r
-\r
-MemcacheStorageService::~MemcacheStorageService() {\r
-\r
-  \r
-}\r
-\r
-bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {\r
-\r
-  log.debug("createString ctx: %s - key: %s", context, key);\r
-\r
-  string final_key = string(context) + ":" + string(key);\r
-\r
-  mc_record rec(value, expiration);\r
-  string final_value;\r
-  serialize(rec, final_value);\r
-\r
-  bool result = addMemcache(final_key.c_str(), final_value, expiration, 1); // the flag will be the version\r
-\r
-  if (result && m_buildMap) {\r
-    log.debug("Got result, updating map");\r
-\r
-    string map_name = context;\r
-    // we need to update the context map\r
-    if (! addLock(map_name)) {\r
-      log.error("Unable to get lock for context %s!", context);\r
-      deleteMemcache(final_key.c_str(), 0);\r
-      return false;\r
-    }\r
-\r
-    string ser_arr;\r
-    uint32_t flags;\r
-    bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-    \r
-    list<string> contents;\r
-    if (result) {\r
-      log.debug("Match found. Parsing...");\r
-\r
-      deserialize(ser_arr, contents);\r
-      \r
-      log.debug("Iterating retrieved session map...");\r
-      list<string>::iterator iter;\r
-      for(iter = contents.begin(); \r
-          iter != contents.end();\r
-          iter++) {\r
-        log.debug("value = " + *iter);\r
-      }\r
-\r
-    } else {\r
-      log.debug("New context: %s", map_name.c_str());\r
-\r
-    }\r
-\r
-    contents.push_back(key);\r
-    serialize(contents, ser_arr);    \r
-    setMemcache(map_name.c_str(), ser_arr, expiration, 0);    \r
-    \r
-    deleteLock(map_name);\r
-  }\r
-\r
-  return result;  \r
-\r
-}\r
-\r
-int MemcacheStorageService::readString(const char* context, const char* key, string* pvalue, time_t* pexpiration, int version) {\r
-\r
-  log.debug("readString ctx: %s - key: %s", context, key);\r
-\r
-  string final_key = string(context) + ":" + string(key);\r
-  uint32_t rec_version;\r
-  string value;\r
-\r
-  if (m_buildMap) {\r
-    log.debug("Checking context");\r
-\r
-    string map_name = context;\r
-    string ser_arr;\r
-    uint32_t flags;\r
-    bool ctx_found = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-\r
-    if (!ctx_found) {\r
-      return 0;\r
-    }\r
-  }\r
-\r
-  bool found = getMemcache(final_key.c_str(), value, &rec_version);\r
-  if (!found) {\r
-    return 0;\r
-  }\r
-\r
-  if (version && rec_version <= (uint32_t)version) {\r
-    return version;\r
-  }\r
-\r
-  if (pexpiration || pvalue) {\r
-    mc_record rec;\r
-    deserialize(value, rec);\r
-    \r
-    if (pexpiration) {\r
-      *pexpiration = rec.expiration;\r
-    }\r
-    \r
-    if (pvalue) {\r
-      *pvalue = rec.value;\r
-    }\r
-  }\r
-  \r
-  return rec_version;\r
-\r
-}\r
-\r
-int MemcacheStorageService::updateString(const char* context, const char* key, const char* value, time_t expiration, int version) {\r
-\r
-  log.debug("updateString ctx: %s - key: %s", context, key);\r
-\r
-  time_t final_exp = expiration;\r
-  time_t *want_expiration = NULL;\r
-  if (! final_exp) {\r
-    want_expiration = &final_exp;\r
-  }\r
-\r
-  int read_res = readString(context, key, NULL, want_expiration, version);\r
-\r
-  if (!read_res) {\r
-    // not found\r
-    return read_res;\r
-  }\r
-\r
-  if (version && version != read_res) {\r
-    // version incorrect\r
-    return -1;\r
-  }\r
-\r
-  // Proceding with update\r
-  string final_key = string(context) + ":" + string(key);\r
-  mc_record rec(value, final_exp);\r
-  string final_value;\r
-  serialize(rec, final_value);\r
-\r
-  replaceMemcache(final_key.c_str(), final_value, final_exp, ++version);\r
-  return version;\r
-\r
-}\r
-\r
-bool MemcacheStorageService::deleteString(const char* context, const char* key) {\r
-\r
-  log.debug("deleteString ctx: %s - key: %s", context, key);\r
-  \r
-  string final_key = string(context) + ":" + string(key);\r
-\r
-  // Not updating context map, if there is one. There is no need.\r
-\r
-  return deleteMemcache(final_key.c_str(), 0);\r
-\r
-}\r
-\r
-void MemcacheStorageService::updateContext(const char* context, time_t expiration) {\r
-\r
-  log.debug("updateContext ctx: %s", context);\r
-\r
-  if (!m_buildMap) {\r
-    log.error("updateContext invoked on a Storage with no context map built!");\r
-    return;\r
-  }\r
-\r
-  string map_name = context;\r
-  string ser_arr;\r
-  uint32_t flags;\r
-  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-  \r
-  list<string> contents;\r
-  if (result) {\r
-    log.debug("Match found. Parsing...");\r
-    \r
-    deserialize(ser_arr, contents);\r
-    \r
-    log.debug("Iterating retrieved session map...");\r
-    list<string>::iterator iter;\r
-    for(iter = contents.begin(); \r
-        iter != contents.end();\r
-        iter++) {\r
-\r
-      // Update expiration times\r
-      string value;      \r
-      int read_res = readString(context, iter->c_str(), &value, NULL, 0);\r
-      \r
-      if (!read_res) {\r
-        // not found\r
-        continue;\r
-      }\r
-\r
-      updateString(context, iter->c_str(), value.c_str(), expiration, read_res);\r
-    }\r
-    replaceMemcache(map_name.c_str(), ser_arr, expiration, flags);\r
-  }\r
-  \r
-}\r
-\r
-void MemcacheStorageService::deleteContext(const char* context) {\r
-\r
-  log.debug("deleteContext ctx: %s", context);\r
-\r
-  if (!m_buildMap) {\r
-    log.error("deleteContext invoked on a Storage with no context map built!");\r
-    return;\r
-  }\r
-\r
-  string map_name = context;\r
-  string ser_arr;\r
-  uint32_t flags;\r
-  bool result = getMemcache(map_name.c_str(), ser_arr, &flags);\r
-  \r
-  list<string> contents;\r
-  if (result) {\r
-    log.debug("Match found. Parsing...");\r
-    \r
-    deserialize(ser_arr, contents);\r
-    \r
-    log.debug("Iterating retrieved session map...");\r
-    list<string>::iterator iter;\r
-    for(iter = contents.begin(); \r
-        iter != contents.end();\r
-        iter++) {\r
-      string final_key = map_name + *iter;\r
-      deleteMemcache(final_key.c_str(), 0);\r
-    }\r
-    \r
-    deleteMemcache(map_name.c_str(), 0);\r
-  }\r
-  \r
-}\r
-\r
-extern "C" int MCEXT_EXPORTS xmltooling_extension_init(void*) {\r
-    // Register this SS type\r
-    XMLToolingConfig::getConfig().StorageServiceManager.registerFactory("MEMCACHE", MemcacheStorageServiceFactory);\r
-    return 0;\r
-}\r
-\r
-extern "C" void MCEXT_EXPORTS xmltooling_extension_term() {\r
-    XMLToolingConfig::getConfig().StorageServiceManager.deregisterFactory("MEMCACHE");\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ * 
+ * Licensed 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 std;
+
+namespace xmltooling {
+  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);
+  
+  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 addSessionToUser(string &key, string &user);
+    bool addLock(string what, bool use_prefix = true);
+    void deleteLock(string what, bool use_prefix = true);
+
+  protected:
+    const DOMElement* m_root; // can only use this during initialization
+    Category& log;
+    memcached_st *memc;
+    string m_prefix;
+    Mutex* m_lock;
+  };
+  
+  class MemcacheStorageService : public StorageService, public MemcacheBase {
+
+  public:
+    MemcacheStorageService(const DOMElement* e);
+    ~MemcacheStorageService();
+    
+    bool createString(const char* context, const char* key, const char* value, time_t expiration);
+    int readString(const char* context, const char* key, string* pvalue=NULL, time_t* pexpiration=NULL, int version=0);
+    int updateString(const char* context, const char* key, const char* value=NULL, 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=NULL, time_t* pexpiration=NULL, int version=0) {
+      return readString(context, key, pvalue, pexpiration, version);
+    }
+    int updateText(const char* context, const char* key, const char* value=NULL, 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* context) {}
+
+    void updateContext(const char* context, time_t expiration);
+    void deleteContext(const char* context);
+
+    private:
+
+    Category& m_log;
+    bool m_buildMap;
+
+
+  };
+
+  StorageService* MemcacheStorageServiceFactory(const DOMElement* const & e) {
+    return new MemcacheStorageService(e);
+  }
+
+};
+
+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) {
+      log.debug("Unable to get lock %s... FAILED.", lock_name.c_str());
+      return false;
+    }
+    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::addSessionToUser(string &key, string &user) {
+
+  if (! addLock(user, false)) {
+    return false;
+  }
+
+  // Aquired lock
+
+  string sessid = m_prefix + key; // add specific prefix to session
+  string delimiter = ";";
+  string user_key = "UDATA:";
+  user_key += user;
+  string user_val;
+  uint32_t flags;
+  bool result = getMemcache(user_key.c_str(), user_val, &flags, false);
+
+  if (result) {
+    bool already_there = false;
+    // skip delimiters at beginning.
+    string::size_type lastPos = user_val.find_first_not_of(delimiter, 0);
+    
+    // find first "non-delimiter".
+    string::size_type pos = user_val.find_first_of(delimiter, lastPos);
+    
+    while (string::npos != pos || string::npos != lastPos) {
+      // found a token, add it to the vector.
+      string session = user_val.substr(lastPos, pos - lastPos);
+      if (strcmp(session.c_str(), sessid.c_str()) == 0) {
+        already_there = true;
+        break;
+      }
+      
+      // skip delimiters.  Note the "not_of"
+      lastPos = user_val.find_first_not_of(delimiter, pos);
+      
+      // find next "non-delimiter"
+      pos = user_val.find_first_of(delimiter, lastPos);
+    }
+    
+    if (!already_there) {
+      user_val += delimiter + sessid;
+      replaceMemcache(user_key.c_str(), user_val, 0, 0, false);
+    }
+  } else {
+    addMemcache(user_key.c_str(), sessid, 0, 0, false);
+  }
+
+  deleteLock(user, false);
+  return true;
+  
+}
+
+bool MemcacheBase::deleteMemcache(const char *key,
+                                  time_t timeout,
+                                  bool use_prefix) {
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_delete(memc, (char *)final_key.c_str(), final_key.length(), timeout);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTFOUND) {
+    // Key wasn't there... No biggie.
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::deleteMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::deleteMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::getMemcache(const char *key,
+                               string &dest,
+                               uint32_t *flags,
+                               bool use_prefix) {
+  memcached_return rv;
+  size_t len;
+  char *result;
+  string final_key;
+  bool success;
+  
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  result = memcached_get(memc, (char *)final_key.c_str(), final_key.length(), &len, flags, &rv);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    dest = result;
+    free(result);
+    success = true;
+  } else if (rv == MEMCACHED_NOTFOUND) {
+    log.debug("Key %s not found in memcache...", key);
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::getMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::getMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::addMemcache(const char *key,
+                               string &value,
+                               time_t timeout,
+                               uint32_t flags,
+                               bool use_prefix) {
+
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_add(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTSTORED) {
+    // already there
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::addMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::addMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::setMemcache(const char *key,
+                               string &value,
+                               time_t timeout,
+                               uint32_t flags,
+                               bool use_prefix) {
+
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_set(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::setMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::setMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+bool MemcacheBase::replaceMemcache(const char *key,
+                                   string &value,
+                                   time_t timeout,
+                                   uint32_t flags,
+                                   bool use_prefix) {
+  
+  memcached_return rv;
+  string final_key;
+  bool success;
+
+  if (use_prefix) {
+    final_key = m_prefix + key;
+  } else {
+    final_key = key;
+  }
+
+  m_lock->lock();
+  rv = memcached_replace(memc, (char *)final_key.c_str(), final_key.length(), (char *)value.c_str(), value.length(), timeout, flags);
+  m_lock->unlock();
+
+  if (rv == MEMCACHED_SUCCESS) {
+    success = true;
+  } else if (rv == MEMCACHED_NOTSTORED) {
+    // not there
+    success = false;
+  } else if (rv == MEMCACHED_ERRNO) {
+    // System error
+    string error = string("Memcache::replaceMemcache() SYSTEM ERROR: ") + string(strerror(memc->cached_errno));
+    log.error(error);
+    throw IOException(error);
+  } else {
+    string error = string("Memcache::replaceMemcache() Problems: ") + memcached_strerror(memc, rv);
+    log.error(error);
+    throw IOException(error);
+  }
+
+  return success;
+}
+
+MemcacheBase::MemcacheBase(const DOMElement* e) : m_root(e), log(Category::getInstance("XMLTooling.MemcacheBase")), m_prefix("") {
+
+  auto_ptr_char p(e ? e->getAttributeNS(NULL,prefix) : NULL);
+  if (p.get() && *p.get()) {
+    log.debug("INIT: GOT key prefix: %s", p.get());
+    m_prefix = p.get();
+  }
+
+  m_lock = Mutex::create();
+  log.debug("Lock created");
+
+  memc = memcached_create(NULL);
+  if (memc == NULL) {
+    throw XMLToolingException("MemcacheBase::Memcache(): memcached_create() failed");
+  }
+
+  log.debug("Memcache created");
+
+  unsigned int hash = MEMCACHED_HASH_CRC;
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_HASH, hash);
+  log.debug("CRC hash set");
+
+  int32_t send_timeout = 1000000;
+  const XMLCh* tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+  if (tag && *tag) {
+    send_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_SND_TIMEOUT will be set to %d", send_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SND_TIMEOUT, send_timeout);
+
+  int32_t recv_timeout = 1000000;
+  tag = e ? e->getAttributeNS(NULL, sendTimeout) : NULL;
+  if (tag && *tag) {
+    recv_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_RCV_TIMEOUT will be set to %d", recv_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RCV_TIMEOUT, recv_timeout);
+
+  int32_t poll_timeout = 1000;
+  tag = e ? e->getAttributeNS(NULL, pollTimeout) : NULL;
+  if (tag && *tag) {
+    poll_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_POLL_TIMEOUT will be set to %d", poll_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_POLL_TIMEOUT, poll_timeout);
+
+  int32_t fail_limit = 5;
+  tag = e ? e->getAttributeNS(NULL, failLimit) : NULL;
+  if (tag && *tag) {
+    fail_limit = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT will be set to %d", fail_limit);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_SERVER_FAILURE_LIMIT, fail_limit);
+
+  int32_t retry_timeout = 30;
+  tag = e ? e->getAttributeNS(NULL, retryTimeout) : NULL;
+  if (tag && *tag) {
+    retry_timeout = XMLString::parseInt(tag);
+  }
+  log.debug("MEMCACHED_BEHAVIOR_RETRY_TIMEOUT will be set to %d", retry_timeout);
+  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_RETRY_TIMEOUT, retry_timeout);
+
+  // Grab hosts from the configuration.
+  e = e ? XMLHelper::getFirstChildElement(e,Hosts) : NULL;
+  if (!e || !e->hasChildNodes()) {
+    throw XMLToolingException("Memcache StorageService requires Hosts element in configuration.");
+  }
+  auto_ptr_char h(e->getFirstChild()->getNodeValue());
+  log.debug("INIT: GOT Hosts: %s", h.get());
+  memcached_server_st *servers;
+  servers = memcached_servers_parse(const_cast<char*>(h.get()));
+  log.debug("Got %u hosts.",  memcached_server_list_count(servers));
+  if (memcached_server_push(memc, servers) != MEMCACHED_SUCCESS) {
+    throw IOException("MemcacheBase::Memcache(): memcached_server_push() failed");    
+  }
+  memcached_server_list_free(servers);
+
+  log.debug("Memcache object initialized");
+}
+
+MemcacheBase::~MemcacheBase() {
+  memcached_free(memc);
+  delete m_lock;
+  log.debug("Base object destroyed");
+}
+
+MemcacheStorageService::MemcacheStorageService(const DOMElement* e)
+  : MemcacheBase(e), m_log(Category::getInstance("XMLTooling.MemcacheStorageService")), m_buildMap(false) {
+
+    const XMLCh* tag=e ? e->getAttributeNS(NULL,buildMap) : NULL;
+    if (tag && *tag && XMLString::parseInt(tag) != 0) {
+        m_buildMap = true;
+        m_log.debug("Cache built with buildMap ON");
+    }
+
+}
+
+MemcacheStorageService::~MemcacheStorageService() {
+
+  
+}
+
+bool MemcacheStorageService::createString(const char* context, const char* key, const char* value, time_t expiration) {
+
+  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) {
+    log.debug("Got result, updating map");
+
+    string map_name = context;
+    // we need to update the context map
+    if (! addLock(map_name)) {
+      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) {
+      log.debug("Match found. Parsing...");
+
+      deserialize(ser_arr, contents);
+      
+      log.debug("Iterating retrieved session map...");
+      list<string>::iterator iter;
+      for(iter = contents.begin(); 
+          iter != contents.end();
+          iter++) {
+        log.debug("value = " + *iter);
+      }
+
+    } else {
+      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) {
+
+  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) {
+    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;
+  }
+
+  if (version && rec_version <= (uint32_t)version) {
+    return version;
+  }
+
+  if (pexpiration || pvalue) {
+    mc_record rec;
+    deserialize(value, rec);
+    
+    if (pexpiration) {
+      *pexpiration = rec.expiration;
+    }
+    
+    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) {
+
+  log.debug("updateString ctx: %s - key: %s", context, key);
+
+  time_t final_exp = expiration;
+  time_t *want_expiration = NULL;
+  if (! final_exp) {
+    want_expiration = &final_exp;
+  }
+
+  int read_res = readString(context, key, NULL, 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) {
+
+  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) {
+
+  log.debug("updateContext ctx: %s", context);
+
+  if (!m_buildMap) {
+    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) {
+    log.debug("Match found. Parsing...");
+    
+    deserialize(ser_arr, contents);
+    
+    log.debug("Iterating retrieved session map...");
+    list<string>::iterator iter;
+    for(iter = contents.begin(); 
+        iter != contents.end();
+        iter++) {
+
+      // Update expiration times
+      string value;      
+      int read_res = readString(context, iter->c_str(), &value, NULL, 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) {
+
+  log.debug("deleteContext ctx: %s", context);
+
+  if (!m_buildMap) {
+    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) {
+    log.debug("Match found. Parsing...");
+    
+    deserialize(ser_arr, contents);
+    
+    log.debug("Iterating retrieved session map...");
+    list<string>::iterator iter;
+    for(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");
+}
index ffd78ff..5edb5b1 100644 (file)
@@ -53,8 +53,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -71,12 +71,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth Memcache Storage Service Plugin\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "memcache-store\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "OriginalFilename", "memcache-store.so\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
         END
     END
     BLOCK "VarFileInfo"
index 42c4d44..bd4e56a 100644 (file)
@@ -1,14 +1,14 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by memcache-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1001\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{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
index 0af2484..ee81186 100644 (file)
@@ -85,6 +85,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 960409d..8914e7e 100644 (file)
 # 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 <sstream>
+#include <stdexcept>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 
-#include <memory>
-#include <fstream>
-#include <sstream>
-#include <stdexcept>
-
 #ifdef WIN32
 # include <process.h>
 # define XP_WIN32
@@ -420,6 +422,7 @@ public:
       setResponseHeader("Content-Type", type);
   }
   void setResponseHeader(const char* name, const char* value) {
+    HTTPResponse::setResponseHeader(name, value);
     pblock_nvinsert(name, value, m_rq->srvhdrs);
   }
 
@@ -438,6 +441,7 @@ public:
     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", "01-Jan-1997 12:00:00 GMT", m_rq->srvhdrs);
index ba31800..a551403 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth NSAPI Extension\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "nsapi_shib\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "LegalTrademarks", "\0"
             VALUE "OriginalFilename", "nsapi_shib.dll\0"
             VALUE "PrivateBuild", "\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
             VALUE "SpecialBuild", "\0"
         END
     END
index aa61b65..6c1228d 100644 (file)
@@ -82,6 +82,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 8bb7989..546eefc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 /**
  * odbc-store.cpp
  *
- * Storage Service using ODBC
+ * Storage Service using ODBC.
  */
 
 #if defined (_MSC_VER) || defined(__BORLANDC__)
@@ -39,6 +39,7 @@
 
 #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>
index 1a9eb39..0190222 100644 (file)
@@ -53,8 +53,8 @@ END
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,2,1,0
- PRODUCTVERSION 2,2,1,0
+ FILEVERSION 2,3,0,0
+ PRODUCTVERSION 2,3,0,0
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -71,12 +71,12 @@ BEGIN
         BEGIN
             VALUE "CompanyName", "Internet2\0"
             VALUE "FileDescription", "Shibboleth ODBC Storage Service Plugin\0"
-            VALUE "FileVersion", "2, 2, 1, 0\0"
+            VALUE "FileVersion", "2, 3, 0, 0\0"
             VALUE "InternalName", "odbc-store\0"
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"
             VALUE "OriginalFilename", "odbc-store.so\0"
-            VALUE "ProductName", "Shibboleth 2.2.1\0"
-            VALUE "ProductVersion", "2, 2, 1, 0\0"
+            VALUE "ProductName", "Shibboleth 2.3\0"
+            VALUE "ProductVersion", "2, 3, 0, 0\0"
         END
     END
     BLOCK "VarFileInfo"
index 7a79a45..625d6ee 100644 (file)
@@ -1,14 +1,14 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Visual C++ generated include file.\r
-// Used by odbc-store.rc\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1001\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{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/pkginfo b/pkginfo
index cd040c3..6184208 100644 (file)
--- a/pkginfo
+++ b/pkginfo
@@ -1,5 +1,5 @@
 PKG=SHIBsp
-VERSION=2.2.1
+VERSION=2.3
 BASEDIR=/
 NAME=shibboleth-sp
 CATEGORY=application,security
index 790f33f..a4d5110 100644 (file)
@@ -15,6 +15,7 @@ CONFIGFILES=" \
     discoveryTemplate.html \
     localLogout.html \
     globalLogout.html \
+    partialLogout.html \
     attribute-map.xml \
     attribute-policy.xml \
     example-metadata.xml \
index 1e73766..561e87f 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am 2566 2007-10-24 02:19:26Z cantor $ 
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $ 
 
 AUTOMAKE_OPTIONS = foreign
 
index a0771af..45a831c 100644 (file)
@@ -65,6 +65,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 675f41f..ded4423 100644 (file)
@@ -4,10 +4,10 @@
     xmlns="http://www.w3.org/2001/XMLSchema"
     xmlns:afp="urn:mace:shibboleth:2.0:afp"
     xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
-    elementFormDefault="qualified">\r
-\r
-    <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />\r
-\r
+    elementFormDefault="qualified">
+
+    <import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="classpath:/schema/xmldsig-core-schema.xsd" />
+
     <annotation>
         <documentation>Schema for the attribute filter policies.</documentation>
     </annotation>
@@ -51,7 +51,7 @@
                                 Defines an attribute rule that may be reused across multiple filter policies.
                             </documentation>
                         </annotation>
-                    </element>\r
+                    </element>
                     <element ref="afp:AttributeFilterPolicy" minOccurs="0" maxOccurs="unbounded">
                         <annotation>
                             <documentation>
                                 such as a federation site, should be signed.
                             </documentation>
                         </annotation>
-                    </element>\r
-                </sequence>\r
+                    </element>
+                </sequence>
             </extension>
-        </complexContent>\r
+        </complexContent>
     </complexType>
 
     <element name="AttributeFilterPolicy" type="afp:AttributeFilterPolicyType">
                 </sequence>
             </extension>
         </complexContent>
-    </complexType>\r
-\r
+    </complexType>
+
     <element name="AttributeRule" type="afp:AttributeRuleType">
         <annotation>
             <documentation>A rule that describes how values of an attribute will be filtered.</documentation>
         </annotation>
-    </element>\r
+    </element>
     <complexType name="AttributeRuleType">
         <complexContent>
             <extension base="afp:IdentityType">
                     </annotation>
                 </attribute>
             </extension>
-        </complexContent>\r
+        </complexContent>
     </complexType>
 
     <element name="PolicyRequirementRule" type="afp:MatchFunctorType">
         </attribute>
     </complexType>
 
-</schema>
\ No newline at end of file
+</schema>
index caf5e1e..4fa9883 100644 (file)
@@ -3,7 +3,7 @@
         xmlns="http://www.w3.org/2001/XMLSchema"
         xmlns:am="urn:mace:shibboleth:2.0:attribute-map"
         elementFormDefault="qualified"
-        version="2.2">
+        version="2.3">
 
     <annotation>
         <documentation>
                 <documentation>Flag controlling whether the resulting attribute should be exported for CGI use.</documentation>
             </annotation>
         </attribute>
+        <attribute name="hashAlg" type="am:string">
+            <annotation>
+                <documentation>
+                    Crypto-provider-specific name of hash algorithm to use,
+                    turning the decoded result into a simple string.
+                </documentation>
+            </annotation>
+        </attribute>
     </complexType>
     
     <complexType name="StringAttributeDecoder">
         </complexContent>
     </complexType>
 
-</schema>
\ No newline at end of file
+    <complexType name="KeyInfoAttributeDecoder">
+        <annotation>
+            <documentation>
+                Decoder for attributes with ds:KeyInfo values.
+            </documentation>
+        </annotation>
+        <complexContent>
+            <extension base="am:AttributeDecoderType">
+                <sequence>
+                    <element name="KeyInfoResolver" type="am:PluggableType" minOccurs="0"/>
+                </sequence>
+                <attribute name="hash" type="boolean">
+                    <annotation>
+                        <documentation>
+                            Flag controlling whether to hash keys before base64-encoding them.
+                        </documentation>
+                    </annotation>
+                </attribute>
+                <attribute name="keyInfoHashAlg" type="am:string">
+                    <annotation>
+                        <documentation>
+                            Crypto-provider-specific name of hash algorithm to use.
+                        </documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
+
+    <complexType name="XMLAttributeDecoder">
+        <annotation>
+            <documentation>
+                Decoder for directly serializing XML values.
+            </documentation>
+        </annotation>
+        <complexContent>
+            <extension base="am:AttributeDecoderType"/>
+        </complexContent>
+    </complexType>
+
+    <complexType name="DOMAttributeDecoder">
+        <annotation>
+            <documentation>
+                Decoder for extracting information from XML values.
+            </documentation>
+        </annotation>
+        <complexContent>
+            <extension base="am:AttributeDecoderType">
+                <sequence>
+                    <element name="Mapping" minOccurs="0">
+                        <annotation>
+                            <documentation>Optional transform to turn qualified XML names into string names.</documentation>
+                        </annotation>
+                        <complexType>
+                            <attribute name="from" type="QName" use="required"/>
+                            <attribute name="to" type="am:string" use="required"/>
+                        </complexType>
+                    </element>
+                </sequence>
+                <attribute name="formatter" type="am:string">
+                    <annotation>
+                        <documentation>
+                            The pattern used to generate strings from the XML.
+                        </documentation>
+                    </annotation>
+                </attribute>
+            </extension>
+        </complexContent>
+    </complexType>
+
+</schema>
index 88befab..411b037 100644 (file)
@@ -8,7 +8,7 @@
        elementFormDefault="qualified"\r
        attributeFormDefault="unqualified"\r
        blockDefault="substitution"\r
-       version="2.2">\r
+       version="2.3">\r
 \r
        <import namespace="urn:oasis:names:tc:SAML:2.0:assertion" schemaLocation="saml-schema-assertion-2.0.xsd"/>\r
        <import namespace="urn:oasis:names:tc:SAML:2.0:protocol" schemaLocation="saml-schema-protocol-2.0.xsd"/>\r
        \r
        <complexType name="PluggableType">\r
                <sequence>\r
-                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                       <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                </sequence>\r
                <attribute name="type" type="conf:string" use="required"/>\r
-               <anyAttribute namespace="##any" processContents="lax"/>\r
+               <anyAttribute namespace="##any" processContents="skip"/>\r
        </complexType>\r
 \r
        <element name="SPConfig">\r
                 <element name="RequestMapper" type="conf:PluggableType" minOccurs="0"/>\r
                                <element ref="conf:ApplicationDefaults"/>\r
                                <element ref="conf:SecurityPolicies"/>\r
-                <element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>
+                <element ref="conf:TransportOption" minOccurs="0" maxOccurs="unbounded"/>\r
                        </sequence>\r
                        <attribute name="logger" type="anyURI"/>\r
                        <attribute name="clockSkew" type="unsignedInt"/>\r
-            <attribute name="unsafeChars" type="conf:string"/>
+            <attribute name="unsafeChars" type="conf:string"/>\r
+            <attribute name="allowedSchemes" type="conf:listOfStrings"/>\r
                        <anyAttribute namespace="##other" processContents="lax"/>\r
                </complexType>\r
        </element>\r
                                <element name="Library" minOccurs="0" maxOccurs="unbounded">\r
                                        <complexType>\r
                                                <sequence>\r
-                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                                       <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                                </sequence>\r
                                                <attribute name="path" type="anyURI" use="required"/>\r
                                                <attribute name="fatal" type="boolean"/>\r
-                                               <anyAttribute namespace="##any" processContents="lax"/>\r
+                                               <anyAttribute namespace="##any" processContents="skip"/>\r
                                        </complexType>\r
                                </element>\r
                                <any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
                        <complexContent>\r
                                <restriction base="conf:PluggableType">\r
                                        <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                               <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                        </sequence>\r
                                        <attribute name="id" type="ID" use="required"/>\r
                                        <attribute name="cleanupInterval" type="unsignedInt"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                                       <anyAttribute namespace="##any" processContents="skip"/>\r
                                </restriction>\r
                        </complexContent>\r
                </complexType>\r
                        <complexContent>\r
                                <restriction base="conf:PluggableType">\r
                                        <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                               <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                        </sequence>\r
                                        <attribute name="StorageService" type="IDREF"/>\r
                                        <attribute name="cacheTimeout" type="unsignedInt"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                                       <anyAttribute namespace="##any" processContents="skip"/>\r
                                </restriction>\r
                        </complexContent>\r
                </complexType>\r
                <attribute name="exportAssertion" type="boolean"/>\r
                <attribute name="redirectToSSL" type="unsignedInt"/>\r
                <attribute name="entityID" type="anyURI"/>\r
+        <attribute name="discoveryURL" type="anyURI"/>\r
                <attribute name="isPassive" type="boolean"/>\r
                <attribute name="forceAuthn" type="boolean"/>\r
                <attribute name="authnContextClassRef" type="anyURI"/>\r
                <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
+        <attribute name="NameIDFormat" type="anyURI"/>\r
+        <attribute name="SPNameQualifier" type="conf:string"/>\r
         <attribute name="redirectErrors" type="anyURI"/>\r
                <attribute name="sessionError" type="anyURI"/>\r
                <attribute name="metadataError" type="anyURI"/>\r
                                                <complexContent>\r
                                                        <restriction base="conf:PluggableType">\r
                                                                <sequence>\r
-                                                                       <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                                                       <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                                                </sequence>\r
                                                                <attribute name="Location" type="anyURI" use="required"/>\r
                                                            <attribute name="acl" type="conf:listOfStrings"/>\r
-                                                               <anyAttribute namespace="##any" processContents="lax"/>\r
+                                                               <anyAttribute namespace="##any" processContents="skip"/>\r
                                                        </restriction>\r
                                                </complexContent>\r
                                        </complexType>\r
                        <complexContent>\r
                                <restriction base="conf:PluggableType">\r
                                        <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                               <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                        </sequence>\r
                                        <attribute name="Location" type="anyURI"/>\r
                                        <attribute name="id" type="conf:string"/>\r
                                        <attribute name="template" type="anyURI"/>\r
                                        <attribute name="postArtifact" type="boolean"/>\r
                                        <attribute name="acsByIndex" type="boolean"/>\r
-                                       <attribute name="defaultACSIndex" type="unsignedShort"/>\r
+                    <attribute name="acsIndex" type="unsignedShort"/>\r
+                                       <attribute name="defaultACSIndex" type="unsignedShort"/>   <!-- deprecated -->\r
                     <attribute name="isPassive" type="boolean"/>\r
                     <attribute name="forceAuthn" type="boolean"/>\r
                     <attribute name="authnContextClassRef" type="anyURI"/>\r
                     <attribute name="authnContextComparison" type="samlp:AuthnContextComparisonType"/>\r
+                    <attribute name="NameIDFormat" type="anyURI"/>\r
+                    <attribute name="SPNameQualifier" type="conf:string"/>\r
                     <attribute name="requestDelegation" type="boolean"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                                       <anyAttribute namespace="##any" processContents="skip"/>\r
                                </restriction>\r
                        </complexContent>\r
                </complexType>\r
                        <complexContent>\r
                                <restriction base="conf:PluggableType">\r
                                        <sequence>\r
-                                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                                               <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                                        </sequence>\r
                                        <attribute name="Location" type="anyURI"/>\r
                                    <attribute name="relayState" type="conf:string"/>\r
                                        <attribute name="outgoingBindings" type="conf:listOfURIs"/>\r
                                        <attribute name="template" type="anyURI"/>\r
                                        <attribute name="postArtifact" type="boolean"/>\r
-                                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                                       <anyAttribute namespace="##any" processContents="skip"/>\r
                                </restriction>\r
                        </complexContent>\r
                </complexType>\r
                </annotation>\r
                <complexType>\r
                        <sequence>\r
-                               <any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>\r
+                               <any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>\r
                        </sequence>\r
             <attribute name="redirectErrors" type="anyURI"/>\r
                        <attribute name="session" type="anyURI"/>\r
                        <attribute name="ssl" type="anyURI"/>\r
             <attribute name="localLogout" type="anyURI"/>\r
             <attribute name="globalLogout" type="anyURI"/>\r
+            <attribute name="partialLogout" type="anyURI"/>\r
                        <attribute name="supportContact" type="conf:string"/>\r
                        <attribute name="logoLocation" type="anyURI"/>\r
                        <attribute name="styleSheet" type="anyURI"/>\r
-                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                       <anyAttribute namespace="##any" processContents="skip"/>\r
                </complexType>\r
        </element>\r
 \r
                                </simpleType>\r
                        </attribute>\r
                        <attribute name="Location" type="anyURI" use="required"/>\r
-                       <anyAttribute namespace="##any" processContents="lax"/>\r
+                       <anyAttribute namespace="##any" processContents="skip"/>\r
                </complexType>\r
        </element>\r
        \r
                                                </choice>\r
                                                <attribute name="id" type="conf:string" use="required"/>\r
                                                <attribute name="validate" type="boolean"/>\r
-                                               <anyAttribute namespace="##any" processContents="lax"/>\r
+                                               <anyAttribute namespace="##any" processContents="skip"/>\r
                                        </complexType>\r
                                </element>\r
                        </sequence>\r
index 40c68f5..936a875 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am 2308 2007-06-12 04:56:15Z cantor $ 
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $ 
 
 AUTOMAKE_OPTIONS = foreign
 
index 0f6d823..d2ac12e 100644 (file)
@@ -66,6 +66,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 393507a..b5bb7c8 100644 (file)
@@ -1,6 +1,6 @@
 Name:          shibboleth
-Version:       2.2.1
-Release:       1
+Version:       2.3
+Release:       2
 Summary:    Open source system for attribute-based Web SSO
 Group:         System Environment/Libraries
 Vendor:     Internet2
@@ -8,18 +8,20 @@ License:      Apache 2.0
 URL:           http://shibboleth.internet2.edu/
 Source:     %{name}-sp-%{version}.tar.gz
 BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+PreReq:     openssl
 %if 0%{?suse_version} > 1030
+PreReq:         %{insserv_prereq}
 BuildRequires:  libXerces-c-devel >= 2.8.0
 BuildRequires:  libxml-security-c-devel >= 1.4.0
-BuildRequires:  libxmltooling-devel >= 1.2
-BuildRequires:  libsaml-devel >= 2.2
+BuildRequires:  libxmltooling-devel >= 1.3
+BuildRequires:  libsaml-devel >= 2.3
 %{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: liblog4shib-devel}
 %else
 BuildRequires:  xerces%{?xercesver}-c-devel >= 2.8.0
 BuildRequires:  xml-security-c-devel >= 1.4.0
-BuildRequires:  xmltooling-devel >= 1.2
-BuildRequires:  opensaml-devel >= 2.2
+BuildRequires:  xmltooling-devel >= 1.3
+BuildRequires:  opensaml-devel >= 2.3
 %{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: log4shib-devel}
 %endif
@@ -30,6 +32,7 @@ BuildRequires:  zlib-devel
 %{?_with_fastcgi:BuildRequires: fcgi-devel}
 %if "%{_vendor}" == "redhat"
 %{!?_without_builtinapache:BuildRequires: httpd-devel}
+BuildRequires: redhat-rpm-config
 %endif
 %if "%{_vendor}" == "suse"
 %{!?_without_builtinapache:BuildRequires: apache2-devel}
@@ -56,15 +59,15 @@ Requires: %{name} = %{version}
 %if 0%{?suse_version} > 1030
 Requires: libXerces-c-devel >= 2.8.0
 Requires: libxml-security-c-devel >= 1.4.0
-Requires: libxmltooling-devel >= 1.2
-Requires: libsaml-devel >= 2.2
+Requires: libxmltooling-devel >= 1.3
+Requires: libsaml-devel >= 2.3
 %{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
 %{!?_with_log4cpp:Requires: liblog4shib-devel}
 %else
 Requires: xerces%{?xercesver}-c-devel >= 2.8.0
 Requires: xml-security-c-devel >= 1.4.0
-Requires: xmltooling-devel >= 1.2
-Requires: opensaml-devel >= 2.2
+Requires: xmltooling-devel >= 1.3
+Requires: opensaml-devel >= 2.3
 %{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:Requires: log4shib-devel}
 %endif
@@ -122,9 +125,12 @@ fi
 
 %if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
        # %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
-       mkdir -p $RPM_BUILD_ROOT%{_initrddir}
-       %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
-       %{__chmod} 755 $RPM_BUILD_ROOT%{_initrddir}/shibd
+       install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
+       install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/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
 %endif
 
 %check
@@ -149,17 +155,13 @@ sh ./keygen.sh -b
     if [ "$1" -gt "1" ] ; then
         /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
         %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+        exit 0
     fi
 %endif
 %if "%{_vendor}" == "suse"
     # This adds the proper /etc/rc*.d links for the script
-    /sbin/chkconfig --add shibd
-    cd /usr/sbin && ln -s /etc/init.d/shibd rcshibd
-    # On upgrade, restart components if they're already running.
-    if [ "$1" -gt "1" ] ; then
-        /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
-        %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
-    fi
+    cd /
+    %insserv_force_if_yast shibd
 %endif
 
 %preun
@@ -167,18 +169,26 @@ sh ./keygen.sh -b
        if [ "$1" = 0 ] ; then
                /sbin/service shibd stop >/dev/null 2>&1
                /sbin/chkconfig --del shibd
+        %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
        fi
 %endif
 %if "%{_vendor}" == "suse"
+    %stop_on_removal shibd
     if [ "$1" = 0 ] ; then
-        /sbin/service shibd stop >/dev/null 2>&1
-        /sbin/chkconfig --del shibd
-        cd /usr/sbin && %{__rm} -f rcshibd
+        %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
     fi
 %endif
+exit 0
 
+%postun
 %ifnos solaris2.8 solaris2.9 solaris2.10
-%postun -p /sbin/ldconfig
+/sbin/ldconfig
+%endif
+%if "%{_vendor}" == "suse"
+cd /
+%restart_on_update shibd
+%{!?_without_builtinapache:%restart_on_update apache2}
+%{insserv_cleanup}
 %endif
 
 %posttrans
@@ -212,7 +222,10 @@ sh ./keygen.sh -b
 %config(noreplace) %{_sysconfdir}/%{name}/*.html
 %config(noreplace) %{_sysconfdir}/%{name}/*.logger
 %if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
-%attr(755, root, root) %{_initrddir}/shibd
+%config %{_initrddir}/shibd
+%endif
+%if "%{_vendor}" == "suse"
+%{_sbindir}/rcshibd
 %endif
 %{_sysconfdir}/%{name}/*.dist
 %{_sysconfdir}/%{name}/apache*.config
@@ -231,6 +244,11 @@ sh ./keygen.sh -b
 %doc %{pkgdocdir}/api
 
 %changelog
+* Wed Aug 19 2009 Scott Cantor  <cantor.2@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@osu.edu>  - 2.2.1-1
 - Doc handling changes
 - SuSE init script
index b6f89d8..a6c612f 100644 (file)
@@ -1,6 +1,6 @@
 Name:          @PACKAGE@
 Version:       @PACKAGE_VERSION@
-Release:       1
+Release:       2
 Summary:    Open source system for attribute-based Web SSO
 Group:         System Environment/Libraries
 Vendor:     Internet2
@@ -8,18 +8,20 @@ License:      Apache 2.0
 URL:           http://shibboleth.internet2.edu/
 Source:     %{name}-sp-%{version}.tar.gz
 BuildRoot:     %{_tmppath}/%{name}-%{version}-root
+PreReq:     openssl
 %if 0%{?suse_version} > 1030
+PreReq:         %{insserv_prereq}
 BuildRequires:  libXerces-c-devel >= 2.8.0
 BuildRequires:  libxml-security-c-devel >= 1.4.0
-BuildRequires:  libxmltooling-devel >= 1.2
-BuildRequires:  libsaml-devel >= 2.2
+BuildRequires:  libxmltooling-devel >= 1.3
+BuildRequires:  libsaml-devel >= 2.3
 %{?_with_log4cpp:BuildRequires: liblog4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: liblog4shib-devel}
 %else
 BuildRequires:  xerces%{?xercesver}-c-devel >= 2.8.0
 BuildRequires:  xml-security-c-devel >= 1.4.0
-BuildRequires:  xmltooling-devel >= 1.2
-BuildRequires:  opensaml-devel >= 2.2
+BuildRequires:  xmltooling-devel >= 1.3
+BuildRequires:  opensaml-devel >= 2.3
 %{?_with_log4cpp:BuildRequires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:BuildRequires: log4shib-devel}
 %endif
@@ -30,6 +32,7 @@ BuildRequires:  zlib-devel
 %{?_with_fastcgi:BuildRequires: fcgi-devel}
 %if "%{_vendor}" == "redhat"
 %{!?_without_builtinapache:BuildRequires: httpd-devel}
+BuildRequires: redhat-rpm-config
 %endif
 %if "%{_vendor}" == "suse"
 %{!?_without_builtinapache:BuildRequires: apache2-devel}
@@ -56,15 +59,15 @@ Requires: %{name} = %{version}
 %if 0%{?suse_version} > 1030
 Requires: libXerces-c-devel >= 2.8.0
 Requires: libxml-security-c-devel >= 1.4.0
-Requires: libxmltooling-devel >= 1.2
-Requires: libsaml-devel >= 2.2
+Requires: libxmltooling-devel >= 1.3
+Requires: libsaml-devel >= 2.3
 %{?_with_log4cpp:Requires: liblog4cpp-devel >= 1.0}
 %{!?_with_log4cpp:Requires: liblog4shib-devel}
 %else
 Requires: xerces%{?xercesver}-c-devel >= 2.8.0
 Requires: xml-security-c-devel >= 1.4.0
-Requires: xmltooling-devel >= 1.2
-Requires: opensaml-devel >= 2.2
+Requires: xmltooling-devel >= 1.3
+Requires: opensaml-devel >= 2.3
 %{?_with_log4cpp:Requires: log4cpp-devel >= 1.0}
 %{!?_with_log4cpp:Requires: log4shib-devel}
 %endif
@@ -122,9 +125,12 @@ fi
 
 %if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
        # %{_initddir} not yet in RHEL5, use deprecated %{_initrddir}
-       mkdir -p $RPM_BUILD_ROOT%{_initrddir}
-       %{__cp} -p $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/shibd-%{_vendor} $RPM_BUILD_ROOT%{_initrddir}/shibd
-       %{__chmod} 755 $RPM_BUILD_ROOT%{_initrddir}/shibd
+       install -d -m 0755 $RPM_BUILD_ROOT%{_initrddir}
+       install -m 0755 $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/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
 %endif
 
 %check
@@ -149,17 +155,13 @@ sh ./keygen.sh -b
     if [ "$1" -gt "1" ] ; then
         /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
         %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
+        exit 0
     fi
 %endif
 %if "%{_vendor}" == "suse"
     # This adds the proper /etc/rc*.d links for the script
-    /sbin/chkconfig --add shibd
-    cd /usr/sbin && ln -s /etc/init.d/shibd rcshibd
-    # On upgrade, restart components if they're already running.
-    if [ "$1" -gt "1" ] ; then
-        /etc/init.d/shibd status 1>/dev/null && /etc/init.d/shibd restart 1>/dev/null
-        %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
-    fi
+    cd /
+    %insserv_force_if_yast shibd
 %endif
 
 %preun
@@ -167,18 +169,26 @@ sh ./keygen.sh -b
        if [ "$1" = 0 ] ; then
                /sbin/service shibd stop >/dev/null 2>&1
                /sbin/chkconfig --del shibd
+        %{!?_without_builtinapache:/etc/init.d/httpd status 1>/dev/null && /etc/init.d/httpd restart 1>/dev/null}
        fi
 %endif
 %if "%{_vendor}" == "suse"
+    %stop_on_removal shibd
     if [ "$1" = 0 ] ; then
-        /sbin/service shibd stop >/dev/null 2>&1
-        /sbin/chkconfig --del shibd
-        cd /usr/sbin && %{__rm} -f rcshibd
+        %{!?_without_builtinapache:/etc/init.d/apache2 status 1>/dev/null && /etc/init.d/apache2 restart 1>/dev/null}
     fi
 %endif
+exit 0
 
+%postun
 %ifnos solaris2.8 solaris2.9 solaris2.10
-%postun -p /sbin/ldconfig
+/sbin/ldconfig
+%endif
+%if "%{_vendor}" == "suse"
+cd /
+%restart_on_update shibd
+%{!?_without_builtinapache:%restart_on_update apache2}
+%{insserv_cleanup}
 %endif
 
 %posttrans
@@ -212,7 +222,10 @@ sh ./keygen.sh -b
 %config(noreplace) %{_sysconfdir}/%{name}/*.html
 %config(noreplace) %{_sysconfdir}/%{name}/*.logger
 %if "%{_vendor}" == "redhat" || "%{_vendor}" == "suse"
-%attr(755, root, root) %{_initrddir}/shibd
+%config %{_initrddir}/shibd
+%endif
+%if "%{_vendor}" == "suse"
+%{_sbindir}/rcshibd
 %endif
 %{_sysconfdir}/%{name}/*.dist
 %{_sysconfdir}/%{name}/apache*.config
@@ -231,6 +244,11 @@ sh ./keygen.sh -b
 %doc %{pkgdocdir}/api
 
 %changelog
+* Wed Aug 19 2009 Scott Cantor  <cantor.2@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@osu.edu>  - 2.2.1-1
 - Doc handling changes
 - SuSE init script
index b545cdc..1e3d276 100644 (file)
@@ -1,4 +1,4 @@
-## $Id: Makefile.am 2283 2007-06-01 17:35:42Z cantor $
+## $Id: Makefile.am 3168 2009-10-31 20:34:11Z cantor $
 
 AUTOMAKE_OPTIONS = foreign
 
index eb59ce5..9d29d2d 100644 (file)
@@ -76,6 +76,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 4c86dae..2ac256d 100644 (file)
-/*\r
- *  Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/*\r
- * shar.cpp -- the shibd "main" code.  All the functionality is elsewhere\r
- *\r
- * Created By: Derek Atkins <derek@ihtfp.com>\r
- *\r
- * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $\r
- */\r
-\r
-\r
-// eventually we might be able to support autoconf via cygwin...\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/SPConfig.h>\r
-\r
-#ifdef HAVE_UNISTD_H\r
-#include <unistd.h>\r
-#include <sys/select.h>\r
-#endif\r
-\r
-#include <stdio.h>\r
-#include <signal.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/remoting/ListenerService.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xmltooling/XMLToolingConfig.h>\r
-#include <xmltooling/util/XMLConstants.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-bool shibd_shutdown = false;\r
-const char* shar_config = NULL;\r
-const char* shar_schemadir = NULL;\r
-const char* shar_prefix = NULL;\r
-bool shar_checkonly = false;\r
-bool shar_version = false;\r
-static bool unlink_socket = false;\r
-const char* pidfile = NULL;\r
-\r
-#ifdef WIN32\r
-\r
-//#include <CRTDBG.H>\r
-\r
-#define nNoMansLandSize 4\r
-typedef struct _CrtMemBlockHeader\r
-{\r
-        struct _CrtMemBlockHeader * pBlockHeaderNext;\r
-        struct _CrtMemBlockHeader * pBlockHeaderPrev;\r
-        char *                      szFileName;\r
-        int                         nLine;\r
-        size_t                      nDataSize;\r
-        int                         nBlockUse;\r
-        long                        lRequest;\r
-        unsigned char               gap[nNoMansLandSize];\r
-        /* followed by:\r
-         *  unsigned char           data[nDataSize];\r
-         *  unsigned char           anotherGap[nNoMansLandSize];\r
-         */\r
-} _CrtMemBlockHeader;\r
-\r
-/*\r
-int MyAllocHook(int nAllocType, void *pvData,\r
-      size_t nSize, int nBlockUse, long lRequest,\r
-      const unsigned char * szFileName, int nLine)\r
-{\r
-    if ( nBlockUse == _CRT_BLOCK )\r
-      return( TRUE );\r
-    if (nAllocType == _HOOK_FREE) {\r
-        _CrtMemBlockHeader* ptr = (_CrtMemBlockHeader*)(((_CrtMemBlockHeader *)pvData)-1);\r
-        if (ptr->nDataSize == 8192)\r
-            fprintf(stderr,"free  request %u size %u\n", ptr->lRequest, ptr->nDataSize);\r
-    }\r
-    else if (nAllocType == _HOOK_ALLOC && nSize == 8192)\r
-        fprintf(stderr,"%s request %u size %u\n", ((nAllocType == _HOOK_ALLOC) ? "alloc" : "realloc"), lRequest, nSize);\r
-    return (TRUE);\r
-}\r
-*/\r
-\r
-int real_main(int preinit)\r
-{\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    if (preinit) {\r
-\r
-        // Initialize the SP library.\r
-        conf.setFeatures(\r
-            SPConfig::Listener |\r
-            SPConfig::Caching |\r
-            SPConfig::Metadata |\r
-            SPConfig::Trust |\r
-            SPConfig::Credentials |\r
-            SPConfig::AttributeResolution |\r
-            SPConfig::Handlers |\r
-            SPConfig::OutOfProcess |\r
-            (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
-            );\r
-        if (!conf.init(shar_schemadir, shar_prefix)) {\r
-            fprintf(stderr, "configuration is invalid, see console for specific problems\n");\r
-            return -1;\r
-        }\r
-\r
-        if (!conf.instantiate(shar_config)) {\r
-            fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-            conf.term();\r
-            return -2;\r
-        }\r
-\r
-        // If just a test run, bail.\r
-        if (shar_checkonly) {\r
-            fprintf(stdout, "overall configuration is loadable, check console for non-fatal problems\n");\r
-            return 0;\r
-        }\r
-    }\r
-    else {\r
-\r
-        //_CrtSetAllocHook(MyAllocHook);\r
-\r
-        if (!shar_checkonly) {\r
-            // Run the listener.\r
-            ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
-            if (!listener->init(unlink_socket)) {\r
-                fprintf(stderr, "listener failed to initialize\n");\r
-                conf.term();\r
-                return -3;\r
-            }\r
-            else if (!listener->run(&shibd_shutdown)) {\r
-                fprintf(stderr, "listener failed during service\n");\r
-                listener->term();\r
-                conf.term();\r
-                return -3;\r
-            }\r
-            listener->term();\r
-        }\r
-\r
-        conf.term();\r
-    }\r
-    return 0;\r
-}\r
-\r
-#else\r
-\r
-int daemon_wait = 3;\r
-bool shibd_running = false;\r
-bool daemonize = true;\r
-\r
-static void term_handler(int arg)\r
-{\r
-    shibd_shutdown = true;\r
-}\r
-\r
-static void run_handler(int arg)\r
-{\r
-    shibd_running = true;\r
-}\r
-\r
-static void child_handler(int arg)\r
-{\r
-    // Terminate the parent's wait/sleep if the newly born daemon dies early.\r
-}\r
-\r
-static int setup_signals(void)\r
-{\r
-    struct sigaction sa;\r
-    memset(&sa, 0, sizeof (sa));\r
-    sa.sa_handler = SIG_IGN;\r
-    sa.sa_flags = SA_RESTART;\r
-\r
-    if (sigaction(SIGPIPE, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-\r
-    memset(&sa, 0, sizeof (sa));\r
-    sa.sa_handler = term_handler;\r
-    sa.sa_flags = SA_RESTART;\r
-\r
-    if (sigaction(SIGHUP, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGINT, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGQUIT, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-    if (sigaction(SIGTERM, &sa, NULL) < 0) {\r
-        return -1;\r
-    }\r
-\r
-    if (daemonize) {\r
-        memset(&sa, 0, sizeof (sa));\r
-        sa.sa_handler = run_handler;\r
-\r
-        if (sigaction(SIGUSR1, &sa, NULL) < 0) {\r
-            return -1;\r
-        }\r
-\r
-        memset(&sa, 0, sizeof (sa));\r
-        sa.sa_handler = child_handler;\r
-\r
-        if (sigaction(SIGCHLD, &sa, NULL) < 0) {\r
-            return -1;\r
-        }\r
-    }\r
-\r
-    return 0;\r
-}\r
-\r
-static void usage(char* whoami)\r
-{\r
-    fprintf(stderr, "usage: %s [-dcxtfpvh]\n", whoami);\r
-    fprintf(stderr, "  -d\tinstallation prefix to use.\n");\r
-    fprintf(stderr, "  -c\tconfig file to use.\n");\r
-    fprintf(stderr, "  -x\tXML schema catalogs to use.\n");\r
-    fprintf(stderr, "  -t\ttest configuration file for problems.\n");\r
-    fprintf(stderr, "  -f\tforce removal of listener socket.\n");\r
-    fprintf(stderr, "  -F\tstay in the foreground.\n");\r
-    fprintf(stderr, "  -p\tpid file to use.\n");\r
-    fprintf(stderr, "  -w\tseconds to wait for successful daemonization.\n");\r
-    fprintf(stderr, "  -v\tprint software version.\n");\r
-    fprintf(stderr, "  -h\tprint this help message.\n");\r
-    exit(1);\r
-}\r
-\r
-static int parse_args(int argc, char* argv[])\r
-{\r
-    int opt;\r
-\r
-    while ((opt = getopt(argc, argv, "d:c:x:p:w:fFtvh")) > 0) {\r
-        switch (opt) {\r
-            case 'd':\r
-                shar_prefix=optarg;\r
-                break;\r
-            case 'c':\r
-                shar_config=optarg;\r
-                break;\r
-            case 'x':\r
-                shar_schemadir=optarg;\r
-                break;\r
-            case 'f':\r
-                unlink_socket = true;\r
-                break;\r
-            case 'F':\r
-                daemonize = false;\r
-                break;\r
-            case 't':\r
-                shar_checkonly=true;\r
-                daemonize=false;\r
-                break;\r
-            case 'v':\r
-                shar_version=true;\r
-                break;\r
-            case 'p':\r
-                pidfile=optarg;\r
-                break;\r
-            case 'w':\r
-                if (optarg)\r
-                    daemon_wait = atoi(optarg);\r
-                if (daemon_wait <= 0)\r
-                    daemon_wait = 3;\r
-                break;\r
-            default:\r
-                return -1;\r
-        }\r
-    }\r
-    return 0;\r
-}\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-    if (parse_args(argc, argv) != 0)\r
-        usage(argv[0]);\r
-    else if (shar_version) {\r
-        fprintf(stdout, PACKAGE_STRING"\n");\r
-        return 0;\r
-    }\r
-\r
-    if (setup_signals() != 0)\r
-        return -1;\r
-\r
-    // initialize the shib-target library\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.setFeatures(\r
-        SPConfig::Listener |\r
-        SPConfig::Caching |\r
-        SPConfig::Metadata |\r
-        SPConfig::Trust |\r
-        SPConfig::Credentials |\r
-        SPConfig::AttributeResolution |\r
-        SPConfig::Handlers |\r
-        SPConfig::OutOfProcess |\r
-        (shar_checkonly ? SPConfig::RequestMapping : SPConfig::Logging)\r
-        );\r
-    if (!conf.init(shar_schemadir, shar_prefix)) {\r
-        fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-        return -1;\r
-    }\r
-\r
-    if (daemonize) {\r
-        // We must fork() early, while we're single threaded.\r
-        // StorageService cleanup thread is about to start.\r
-        switch (fork()) {\r
-            case 0:\r
-                break;\r
-            case -1:\r
-                perror("forking");\r
-                exit(EXIT_FAILURE);\r
-            default:\r
-                sleep(daemon_wait);\r
-                exit(shibd_running ? EXIT_SUCCESS : EXIT_FAILURE);\r
-        }\r
-    }\r
-\r
-    if (!conf.instantiate(shar_config)) {\r
-        fprintf(stderr, "configuration is invalid, check console for specific problems\n");\r
-        conf.term();\r
-        return -2;\r
-    }\r
-\r
-    if (shar_checkonly)\r
-        fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");\r
-    else {\r
-        // Init the listener.\r
-        ListenerService* listener = conf.getServiceProvider()->getListenerService();\r
-        if (!listener->init(unlink_socket)) {\r
-            fprintf(stderr, "listener failed to initialize\n");\r
-            conf.term();\r
-            return -3;\r
-        }\r
-\r
-        if (daemonize) {\r
-            if (setsid() == -1) {\r
-                perror("setsid");\r
-                exit(EXIT_FAILURE);\r
-            }\r
-            if (chdir("/") == -1) {\r
-                perror("chdir to root");\r
-                exit(EXIT_FAILURE);\r
-            }\r
-\r
-            if (pidfile) {\r
-                FILE* pidf = fopen(pidfile, "w");\r
-                if (pidf) {\r
-                    fprintf(pidf, "%d\n", getpid());\r
-                    fclose(pidf);\r
-                }\r
-                else {\r
-                    perror(pidfile);\r
-                }\r
-            }\r
-\r
-            freopen("/dev/null", "r", stdin);\r
-            freopen("/dev/null", "w", stdout);\r
-            freopen("/dev/null", "w", stderr);\r
-\r
-            // Signal our parent that we are A-OK.\r
-            kill(getppid(), SIGUSR1);\r
-        }\r
-\r
-        // Run the listener.\r
-        if (!listener->run(&shibd_shutdown)) {\r
-            fprintf(stderr, "listener failure during service\n");\r
-            listener->term();\r
-            conf.term();\r
-            if (pidfile)\r
-                unlink(pidfile);\r
-            return -3;\r
-        }\r
-        listener->term();\r
-    }\r
-\r
-    conf.term();\r
-    if (pidfile)\r
-        unlink(pidfile);\r
-    return 0;\r
-}\r
-\r
-#endif\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.cpp -- the shibd "main" code.  All the functionality is elsewhere
+ *
+ * Created By: Derek Atkins <derek@ihtfp.com>
+ *
+ * $Id: shar.cpp 2164 2007-02-11 05:26:18 +0000 (Sun, 11 Feb 2007) cantor $
+ */
+
+
+// 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
+
+#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>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+bool shibd_shutdown = false;
+const char* shar_config = NULL;
+const char* shar_schemadir = NULL;
+const char* shar_prefix = NULL;
+bool shar_checkonly = false;
+bool shar_version = false;
+static bool unlink_socket = false;
+const char* pidfile = NULL;
+
+#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)
+{
+    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 for specific problems\n");
+            return -1;
+        }
+
+        if (!conf.instantiate(shar_config)) {
+            fprintf(stderr, "configuration is invalid, check console 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 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;
+
+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, NULL) < 0) {
+        return -1;
+    }
+
+    memset(&sa, 0, sizeof (sa));
+    sa.sa_handler = term_handler;
+    sa.sa_flags = SA_RESTART;
+
+    if (sigaction(SIGHUP, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGINT, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGQUIT, &sa, NULL) < 0) {
+        return -1;
+    }
+    if (sigaction(SIGTERM, &sa, NULL) < 0) {
+        return -1;
+    }
+
+    if (daemonize) {
+        memset(&sa, 0, sizeof (sa));
+        sa.sa_handler = run_handler;
+
+        if (sigaction(SIGUSR1, &sa, NULL) < 0) {
+            return -1;
+        }
+
+        memset(&sa, 0, sizeof (sa));
+        sa.sa_handler = child_handler;
+
+        if (sigaction(SIGCHLD, &sa, NULL) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static void usage(char* whoami)
+{
+    fprintf(stderr, "usage: %s [-dcxtfpvh]\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, "  -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: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;
+            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;
+
+    // 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, "configuration is invalid, check console 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, "configuration is invalid, check console for specific problems\n");
+        conf.term();
+        return -2;
+    }
+
+    if (shar_checkonly)
+        fprintf(stderr, "overall configuration is loadable, check console for non-fatal problems\n");
+    else {
+        // Init the listener.
+        ListenerService* listener = conf.getServiceProvider()->getListenerService();
+        if (!listener->init(unlink_socket)) {
+            fprintf(stderr, "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.
+        if (!listener->run(&shibd_shutdown)) {
+            fprintf(stderr, "listener failure during service\n");
+            listener->term();
+            conf.term();
+            if (pidfile)
+                unlink(pidfile);
+            return -3;
+        }
+        listener->term();
+    }
+
+    conf.term();
+    if (pidfile)
+        unlink(pidfile);
+    return 0;
+}
+
+#endif
index 4f11667..264fc0c 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 2,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 2,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -47,14 +47,14 @@ BEGIN
             VALUE "Comments", "\0"\r
             VALUE "CompanyName", "Internet2\0"\r
             VALUE "FileDescription", "Shibboleth Daemon Service\0"\r
-            VALUE "FileVersion", "2, 2, 1, 0\0"\r
+            VALUE "FileVersion", "2, 3, 0, 0\0"\r
             VALUE "InternalName", "shibd\0"\r
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
             VALUE "OriginalFilename", "shibd.exe\0"\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
-            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.3\0"\r
+            VALUE "ProductVersion", "2, 3, 0, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index b196ea8..7a9a602 100644 (file)
-/*\r
- *  Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/*\r
- * shar_win32.cpp -- the SHAR "main" code on Win32\r
- *\r
- * Created By: Scott Cantor (cantor.2@osu.edu)\r
- *\r
- * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $\r
- */\r
-\r
-#include "config_win32.h"\r
-\r
-#define _CRT_NONSTDC_NO_DEPRECATE 1\r
-#define _CRT_SECURE_NO_DEPRECATE 1\r
-\r
-#include <shibsp/base.h>\r
-#include <string>\r
-#include <windows.h>\r
-\r
-using namespace std;\r
-\r
-extern bool shibd_shutdown;                    // signals shutdown to Unix side\r
-extern const char* shar_schemadir;\r
-extern const char* shar_config;\r
-extern const char* shar_prefix;\r
-extern bool shar_checkonly;\r
-\r
-// internal variables\r
-SERVICE_STATUS          ssStatus;       // current status of the service\r
-SERVICE_STATUS_HANDLE   sshStatusHandle;\r
-DWORD                   dwErr = 0;\r
-BOOL                    bConsole = FALSE;\r
-char                    szErr[256];\r
-LPCSTR                  lpszInstall = NULL;\r
-LPCSTR                  lpszRemove = NULL;\r
-\r
-// internal function prototypes\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode);\r
-VOID WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID CmdInstallService(LPCSTR);\r
-VOID CmdRemoveService(LPCSTR);\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize );\r
-\r
-BOOL LogEvent(\r
-    LPCTSTR  lpUNCServerName,\r
-    WORD  wType,\r
-    DWORD  dwEventID,\r
-    PSID  lpUserSid,\r
-    LPCTSTR  message);\r
-\r
-VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);\r
-VOID ServiceStop();\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);\r
-void AddToMessageLog(LPSTR lpszMsg);\r
-\r
-BOOL WINAPI BreakHandler(DWORD dwCtrlType)\r
-{\r
-   switch(dwCtrlType)\r
-    {\r
-        case CTRL_BREAK_EVENT:  // use Ctrl+C or Ctrl+Break to simulate\r
-        case CTRL_C_EVENT:      // SERVICE_CONTROL_STOP in console mode\r
-            ServiceStop();\r
-            return TRUE;\r
-    }\r
-    return FALSE;\r
-}\r
-\r
-\r
-int real_main(int);  // The revised two-phase main() in shar.cpp\r
-\r
-int main(int argc, char *argv[])\r
-{\r
-    int i=1;\r
-    while ((argc > i) && ((*argv[i] == '-') || (*argv[i] == '/')))\r
-    {\r
-        if (_stricmp("install", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                lpszInstall = argv[i++];\r
-        }\r
-        else if (_stricmp("remove", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                lpszRemove = argv[i++];\r
-        }\r
-        else if (_stricmp( "console", argv[i]+1) == 0)\r
-        {\r
-            i++;\r
-            bConsole = TRUE;\r
-        }\r
-        else if (_stricmp( "check", argv[i]+1) == 0)\r
-        {\r
-            i++;\r
-            bConsole = TRUE;\r
-            shar_checkonly=true;\r
-        }\r
-        else if (_stricmp( "config", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_config = argv[i++];\r
-        }\r
-        else if (_stricmp( "prefix", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_prefix = argv[i++];\r
-        }\r
-        else if (_stricmp( "catalogs", argv[i]+1) == 0)\r
-        {\r
-            if (argc > ++i)\r
-                shar_schemadir = argv[i++];\r
-        }\r
-        else\r
-        {\r
-            goto dispatch;\r
-        }\r
-    }\r
-    \r
-    if (bConsole)\r
-    {\r
-        // Install break handler, then run the C routine twice, once to setup, once to start running.\r
-        SetConsoleCtrlHandler(&BreakHandler,TRUE);\r
-        if ((i=real_main(1))!=0)\r
-        {\r
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
-            return i;\r
-        }\r
-        return real_main(0);\r
-    }\r
-    else if (lpszInstall)\r
-    {\r
-        CmdInstallService(lpszInstall);\r
-        return 0;\r
-    }\r
-    else if (lpszRemove)\r
-    {\r
-        CmdRemoveService(lpszRemove);\r
-        return 0;\r
-    }\r
-    \r
-\r
-    // if it doesn't match any of the above parameters\r
-    // the service control manager may be starting the service\r
-    // so we must call StartServiceCtrlDispatcher\r
-    dispatch:\r
-        // this is just to be friendly\r
-        printf("%s -install <name>   to install the named service\n", argv[0]);\r
-        printf("%s -remove <name>    to remove the named service\n", argv[0]);\r
-        printf("%s -console          to run as a console app for debugging\n", argv[0]);\r
-        printf("%s -check            to run as a console app and check configuration\n", argv[0]);\r
-        printf("\t-prefix <dir> to specify the installation directory\n");\r
-        printf("\t-config <file> to specify the config file to use\n");\r
-        printf("\t-catalogs <catalog1:catalog2> to specify schema catalogs\n");\r
-        printf("\nService starting.\nThis may take several seconds. Please wait.\n" );\r
-\r
-    SERVICE_TABLE_ENTRY dispatchTable[] =\r
-    {\r
-        { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },\r
-        { NULL, NULL }\r
-    };\r
-\r
-    if (!StartServiceCtrlDispatcher(dispatchTable))\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "StartServiceCtrlDispatcher failed.");\r
-    return 0;\r
-}\r
-\r
-//\r
-//  FUNCTION: ServiceStart\r
-//\r
-//  PURPOSE: Actual code of the service\r
-//          that does the work.\r
-//\r
-VOID ServiceStart (DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
-    if (real_main(1)!=0)\r
-    {\r
-        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");\r
-        return;\r
-    }\r
-\r
-    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");\r
-\r
-    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))\r
-        return;\r
-\r
-    real_main(0);\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: ServiceStop\r
-//\r
-//   PURPOSE: Stops the service\r
-//\r
-VOID ServiceStop()\r
-{\r
-    if (!bConsole)\r
-        LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd stopping...");\r
-    shibd_shutdown=true;\r
-}\r
-\r
-\r
-void WINAPI service_main(DWORD dwArgc, LPSTR *lpszArgv)\r
-{\r
-\r
-    // register our service control handler:\r
-    sshStatusHandle=RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);\r
-    if (!sshStatusHandle)\r
-        goto cleanup;\r
-\r
-    // SERVICE_STATUS members that don't change in example\r
-    ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;\r
-    ssStatus.dwServiceSpecificExitCode = 0;\r
-\r
-\r
-    // report the status to the service control manager.\r
-    if (!ReportStatusToSCMgr(\r
-        SERVICE_START_PENDING, // service state\r
-        NO_ERROR,              // exit code\r
-        3000))                 // wait hint\r
-        goto cleanup;\r
-\r
-\r
-    ServiceStart(dwArgc, lpszArgv);\r
-\r
-cleanup:\r
-\r
-    // try to report the stopped status to the service control manager.\r
-    //\r
-    if (sshStatusHandle)\r
-        (VOID)ReportStatusToSCMgr(\r
-                            SERVICE_STOPPED,\r
-                            dwErr,\r
-                            0);\r
-\r
-    return;\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: service_ctrl\r
-//\r
-//  PURPOSE: This function is called by the SCM whenever\r
-//           ControlService() is called on this service.\r
-//\r
-//  PARAMETERS:\r
-//    dwCtrlCode - type of control requested\r
-//\r
-//  RETURN VALUE:\r
-//    none\r
-//\r
-VOID WINAPI service_ctrl(DWORD dwCtrlCode)\r
-{\r
-    // Handle the requested control code.\r
-    //\r
-    switch(dwCtrlCode)\r
-    {\r
-        // Stop the service.\r
-        //\r
-        case SERVICE_CONTROL_STOP:\r
-            ssStatus.dwCurrentState = SERVICE_STOP_PENDING;\r
-            ServiceStop();\r
-            break;\r
-\r
-        // Update the service status.\r
-        //\r
-        case SERVICE_CONTROL_INTERROGATE:\r
-            break;\r
-\r
-        // invalid control code\r
-        //\r
-        default:\r
-            break;\r
-\r
-    }\r
-\r
-    ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: ReportStatusToSCMgr()\r
-//\r
-//  PURPOSE: Sets the current status of the service and\r
-//           reports it to the Service Control Manager\r
-//\r
-//  PARAMETERS:\r
-//    dwCurrentState - the state of the service\r
-//    dwWin32ExitCode - error code to report\r
-//    dwWaitHint - worst case estimate to next checkpoint\r
-//\r
-//  RETURN VALUE:\r
-//    TRUE  - success\r
-//    FALSE - failure\r
-//\r
-BOOL ReportStatusToSCMgr(DWORD dwCurrentState,\r
-                         DWORD dwWin32ExitCode,\r
-                         DWORD dwWaitHint)\r
-{\r
-    static DWORD dwCheckPoint = 1;\r
-    BOOL fResult = TRUE;\r
-\r
-\r
-    if (!bConsole) // when console we don't report to the SCM\r
-    {\r
-        if (dwCurrentState == SERVICE_START_PENDING)\r
-            ssStatus.dwControlsAccepted = 0;\r
-        else\r
-            ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;\r
-\r
-        ssStatus.dwCurrentState = dwCurrentState;\r
-        ssStatus.dwWin32ExitCode = dwWin32ExitCode;\r
-        ssStatus.dwWaitHint = dwWaitHint;\r
-\r
-        if ( ( dwCurrentState == SERVICE_RUNNING ) ||\r
-             ( dwCurrentState == SERVICE_STOPPED ) )\r
-            ssStatus.dwCheckPoint = 0;\r
-        else\r
-            ssStatus.dwCheckPoint = dwCheckPoint++;\r
-\r
-\r
-        // Report the status of the service to the service control manager.\r
-        //\r
-        if (!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus)))\r
-            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "SetServiceStatus failed.");\r
-    }\r
-    return fResult;\r
-}\r
-\r
-\r
-///////////////////////////////////////////////////////////////////\r
-//\r
-//  The following code handles service installation and removal\r
-//\r
-//\r
-void CmdInstallService(LPCSTR name)\r
-{\r
-    SC_HANDLE   schService;\r
-    SC_HANDLE   schSCManager;\r
-\r
-    char szPath[256];\r
-\r
-    if ( GetModuleFileName( NULL, szPath, 256 ) == 0 )\r
-    {\r
-        printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));\r
-        return;\r
-    }\r
-    \r
-    string dispName = string("Shibboleth ") + PACKAGE_VERSION + " Daemon (" + name + ")";\r
-    string realName = string("shibd_") + name;\r
-    string cmd(szPath);\r
-    if (shar_prefix)\r
-        cmd = cmd + " -prefix " + shar_prefix;\r
-    if (shar_config)\r
-        cmd = cmd + " -config " + shar_config;\r
-    if (shar_schemadir)\r
-        cmd = cmd + " -schemadir " + shar_schemadir;\r
-\r
-    schSCManager = OpenSCManager(\r
-                        NULL,                   // machine (NULL == local)\r
-                        NULL,                   // database (NULL == default)\r
-                        SC_MANAGER_ALL_ACCESS   // access required\r
-                        );\r
-    \r
-    \r
-    if ( schSCManager )\r
-    {\r
-        schService = CreateService(\r
-            schSCManager,               // SCManager database\r
-            realName.c_str(),           // name of service\r
-            dispName.c_str(),           // name to display\r
-            SERVICE_ALL_ACCESS,         // desired access\r
-            SERVICE_WIN32_OWN_PROCESS,  // service type\r
-            SERVICE_AUTO_START,         // start type\r
-            SERVICE_ERROR_NORMAL,       // error control type\r
-            cmd.c_str(),                // service's command line\r
-            NULL,                       // no load ordering group\r
-            NULL,                       // no tag identifier\r
-            NULL,                       // dependencies\r
-            NULL,                       // LocalSystem account\r
-            NULL);                      // no password\r
-\r
-        if ( schService )\r
-        {\r
-            printf("%s installed.\n", realName.c_str());\r
-            CloseServiceHandle(schService);\r
-        }\r
-        else\r
-        {\r
-            printf("CreateService failed - %s\n", GetLastErrorText(szErr, 256));\r
-        }\r
-\r
-        CloseServiceHandle(schSCManager);\r
-    }\r
-    else\r
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-void CmdRemoveService(LPCSTR name)\r
-{\r
-    SC_HANDLE   schService;\r
-    SC_HANDLE   schSCManager;\r
-    char        realName[512];\r
-\r
-    _snprintf(realName,sizeof(realName),"shibd_%s",name);\r
-\r
-    schSCManager = OpenSCManager(\r
-                        NULL,                   // machine (NULL == local)\r
-                        NULL,                   // database (NULL == default)\r
-                        SC_MANAGER_ALL_ACCESS   // access required\r
-                        );\r
-    if ( schSCManager )\r
-    {\r
-        schService = OpenService(schSCManager, realName, SERVICE_ALL_ACCESS);\r
-\r
-        if (schService)\r
-        {\r
-            // try to stop the service\r
-            if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )\r
-            {\r
-                printf("Stopping shibd (%s).", name);\r
-                Sleep( 1000 );\r
-\r
-                while( QueryServiceStatus( schService, &ssStatus ) )\r
-                {\r
-                    if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )\r
-                    {\r
-                        printf(".");\r
-                        Sleep( 1000 );\r
-                    }\r
-                    else\r
-                        break;\r
-                }\r
-\r
-                if ( ssStatus.dwCurrentState == SERVICE_STOPPED )\r
-                    printf("\n%s stopped.\n", realName);\r
-                else\r
-                    printf("\n%s failed to stop.\n", realName);\r
-\r
-            }\r
-\r
-            // now remove the service\r
-            if( DeleteService(schService) )\r
-                printf("%s removed.\n", realName);\r
-            else\r
-                printf("DeleteService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
-\r
-            CloseServiceHandle(schService);\r
-        }\r
-        else\r
-            printf("OpenService failed - %s\n", GetLastErrorText(szErr,256));\r
-\r
-        CloseServiceHandle(schSCManager);\r
-    }\r
-    else\r
-        printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr,256));\r
-}\r
-\r
-\r
-//\r
-//  FUNCTION: GetLastErrorText\r
-//\r
-//  PURPOSE: copies error message text to string\r
-//\r
-//  PARAMETERS:\r
-//    lpszBuf - destination buffer\r
-//    dwSize - size of buffer\r
-//\r
-//  RETURN VALUE:\r
-//    destination buffer\r
-//\r
-//  COMMENTS:\r
-//\r
-LPTSTR GetLastErrorText( LPSTR lpszBuf, DWORD dwSize )\r
-{\r
-    DWORD dwRet;\r
-    LPSTR lpszTemp = NULL;\r
-\r
-    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,\r
-                           NULL,\r
-                           GetLastError(),\r
-                           LANG_NEUTRAL,\r
-                           (LPSTR)&lpszTemp,\r
-                           0,\r
-                           NULL );\r
-\r
-    // supplied buffer is not long enough\r
-    if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )\r
-        lpszBuf[0] = '\0';\r
-    else\r
-    {\r
-        lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character\r
-        sprintf( lpszBuf, "%s (0x%x)", lpszTemp, GetLastError() );\r
-    }\r
-\r
-    if ( lpszTemp )\r
-        LocalFree((HLOCAL) lpszTemp );\r
-\r
-    return lpszBuf;\r
-}\r
-\r
-BOOL LogEvent(\r
-    LPCSTR  lpUNCServerName,\r
-    WORD  wType,\r
-    DWORD  dwEventID,\r
-    PSID  lpUserSid,\r
-    LPCSTR  message)\r
-{\r
-    LPCSTR  messages[] = {message, NULL};\r
-    \r
-    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");\r
-    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);\r
-    return (DeregisterEventSource(hElog) && res);\r
-}\r
+/*
+ *  Copyright 2001-2007 Internet2
+ * 
+ * Licensed 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
+ *
+ * Created By: Scott Cantor (cantor.2@osu.edu)
+ *
+ * $Id: shar_win32.cpp 2150 2007-02-02 04:06:15 +0000 (Fri, 02 Feb 2007) cantor $
+ */
+
+#include "config_win32.h"
+
+#define _CRT_NONSTDC_NO_DEPRECATE 1
+#define _CRT_SECURE_NO_DEPRECATE 1
+
+#include <shibsp/base.h>
+#include <string>
+#include <windows.h>
+
+using namespace std;
+
+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;
+
+// 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 = NULL;
+LPCSTR                  lpszRemove = NULL;
+
+// 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(
+    LPCTSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCTSTR  message);
+
+VOID ServiceStart(DWORD dwArgc, LPSTR *lpszArgv);
+VOID ServiceStop();
+BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
+void AddToMessageLog(LPSTR lpszMsg);
+
+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 shar.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( "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( "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)
+        {
+            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further 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("\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" );
+
+    SERVICE_TABLE_ENTRY dispatchTable[] =
+    {
+        { "SHIBD", (LPSERVICE_MAIN_FUNCTION)service_main },
+        { NULL, NULL }
+    };
+
+    if (!StartServiceCtrlDispatcher(dispatchTable))
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "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)
+    {
+        LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "shibd startup failed, check shibd.log for further details");
+        return;
+    }
+
+    LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7700, NULL, "shibd started successfully.");
+
+    if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0))
+        return;
+
+    real_main(0);
+}
+
+
+//
+//  FUNCTION: ServiceStop
+//
+//   PURPOSE: Stops the service
+//
+VOID ServiceStop()
+{
+    if (!bConsole)
+        LogEvent(NULL, EVENTLOG_INFORMATION_TYPE, 7701, NULL, "shibd 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)))
+            LogEvent(NULL, EVENTLOG_ERROR_TYPE, 2100, NULL, "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( NULL, szPath, 256 ) == 0 )
+    {
+        printf("Unable to install %s - %s\n", name, GetLastErrorText(szErr, 256));
+        return;
+    }
+    
+    string dispName = string("Shibboleth ") + PACKAGE_VERSION + " 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;
+
+    schSCManager = OpenSCManager(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == 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
+            NULL,                       // no load ordering group
+            NULL,                       // no tag identifier
+            NULL,                       // dependencies
+            NULL,                       // LocalSystem account
+            NULL);                      // 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(
+                        NULL,                   // machine (NULL == local)
+                        NULL,                   // database (NULL == 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 = NULL;
+
+    dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
+                           NULL,
+                           GetLastError(),
+                           LANG_NEUTRAL,
+                           (LPSTR)&lpszTemp,
+                           0,
+                           NULL );
+
+    // 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;
+}
+
+BOOL LogEvent(
+    LPCSTR  lpUNCServerName,
+    WORD  wType,
+    DWORD  dwEventID,
+    PSID  lpUserSid,
+    LPCSTR  message)
+{
+    LPCSTR  messages[] = {message, NULL};
+    
+    HANDLE hElog = RegisterEventSource(lpUNCServerName, "Shibboleth Daemon");
+    BOOL res = ReportEvent(hElog, wType, 0, dwEventID, lpUserSid, 1, 0, messages, NULL);
+    return (DeregisterEventSource(hElog) && res);
+}
index c18d826..249db33 100644 (file)
 /**
  * AbstractSPRequest.cpp
  *
- * Abstract base for SPRequest implementations
+ * Abstract base for SPRequest implementations.
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "AbstractSPRequest.h"
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCache.h"
+#include "util/CGIParser.h"
 
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling;
 using namespace std;
 
+SPRequest::SPRequest()
+{
+}
+
+SPRequest::~SPRequest()
+{
+}
+
+string SPRequest::getSecureHeader(const char* name) const
+{
+    return getHeader(name);
+}
+
+void SPRequest::setAuthType(const char* authtype)
+{
+}
+
 AbstractSPRequest::AbstractSPRequest(const char* category)
     : m_sp(NULL), m_mapper(NULL), m_app(NULL), m_sessionTried(false), m_session(NULL),
         m_log(&Category::getInstance(category)), m_parser(NULL)
@@ -50,6 +69,11 @@ AbstractSPRequest::~AbstractSPRequest()
     delete m_parser;
 }
 
+const ServiceProvider& AbstractSPRequest::getServiceProvider() const
+{
+    return *m_sp;
+}
+
 RequestMapper::Settings AbstractSPRequest::getRequestSettings() const
 {
     if (!m_mapper) {
@@ -147,6 +171,11 @@ void AbstractSPRequest::setRequestURI(const char* uri)
     }
 }
 
+const char* AbstractSPRequest::getRequestURI() const
+{
+    return m_uri.c_str();
+}
+
 const char* AbstractSPRequest::getRequestURL() const
 {
     if (m_url.empty()) {
index 1253256..318f68c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 /**
  * @file shibsp/AbstractSPRequest.h
  * 
- * Abstract base for SPRequest implementations  
+ * Abstract base for SPRequest implementations.
  */
 
 #ifndef __shibsp_abstreq_h__
 #define __shibsp_abstreq_h__
 
-#include <shibsp/exceptions.h>
 #include <shibsp/SPRequest.h>
-#include <shibsp/util/CGIParser.h>
 
 namespace shibsp {
     
+    class SHIBSP_API CGIParser;
+
 #if defined (_MSC_VER)
     #pragma warning( push )
     #pragma warning( disable : 4251 )
@@ -49,7 +49,7 @@ namespace shibsp {
         
         /**
          * Stores a normalized request URI to ensure it contains no %-encoded characters
-         * or other undesirable artifacts, such as ;jsessionid appendage.
+         * or other undesirable artifacts.
          *
          * @param uri   the request URI as obtained from the client
          */
@@ -58,32 +58,18 @@ namespace shibsp {
     public:
         virtual ~AbstractSPRequest();
 
-        const ServiceProvider& getServiceProvider() const {
-            return *m_sp;
-        }
-
+        // Virtual function overrides.
+        const ServiceProvider& getServiceProvider() const;
         RequestMapper::Settings getRequestSettings() const;
-
         const Application& getApplication() const;
-        
         Session* getSession(bool checkTimeout=true, bool ignoreAddress=false, bool cache=true);
-
-        const char* getRequestURI() const {
-            return m_uri.c_str();
-        }
-
+        const char* getRequestURI() const;
         const char* getRequestURL() const;
-        
         std::string getRemoteAddr() const;
-        
         const char* getParameter(const char* name) const;
-
         std::vector<const char*>::size_type getParameters(const char* name, std::vector<const char*>& values) const;
-
         const char* getHandlerURL(const char* resource=NULL) const;
-
         void log(SPLogLevel level, const std::string& msg) const;
-
         bool isPriorityEnabled(SPLogLevel level) const;
 
     private:
index 59178aa..c94e969 100644 (file)
@@ -42,9 +42,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(AccessControl);
     protected:
-        AccessControl() {}
+        AccessControl();
     public:
-        virtual ~AccessControl() {}
+        virtual ~AccessControl();
 
         /**
          * Possible results from an access control decision.
index 6ee7919..b54e5d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -28,6 +28,7 @@
 #include "remoting/ListenerService.h"
 
 #include <algorithm>
+#include <xmltooling/util/Threads.h>
 
 using namespace shibsp;
 using namespace xmltooling;
@@ -42,6 +43,16 @@ Application::~Application()
     delete m_lock;
 }
 
+const ServiceProvider& Application::getServiceProvider() const
+{
+    return *m_sp;
+}
+
+const char* Application::getId() const
+{
+    return getString("id").second;
+}
+
 pair<string,const char*> Application::getCookieNameProps(const char* prefix, time_t* lifetime) const
 {
     static const char* defProps="; path=/";
index cfd38e7..676b24c 100644 (file)
 
 #include <shibsp/util/PropertySet.h>
 
-#include <set>
+#include <string>
+#include <vector>
 #ifndef SHIBSP_LITE
 # include <saml/binding/MessageEncoder.h>
-# include <saml/saml2/metadata/MetadataProvider.h>
-# include <xmltooling/security/CredentialResolver.h>
-# include <xmltooling/security/TrustEngine.h>
 #endif
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/util/Threads.h>
+
+namespace xmltooling {
+    class XMLTOOL_API CredentialResolver;
+    class XMLTOOL_API RWLock;
+    class XMLTOOL_API SOAPTransport;
+    class XMLTOOL_API StorageService;
+    class XMLTOOL_API TrustEngine;
+};
+
+#ifndef SHIBSP_LITE
+namespace opensaml {
+    class SAML_API SecurityPolicyRule;
+    namespace saml2md {
+        class SAML_API MetadataProvider;
+    };
+};
+#endif
 
 namespace shibsp {
 
@@ -90,18 +103,14 @@ namespace shibsp {
          *
          * @return a locked ServiceProvider
          */
-        const ServiceProvider& getServiceProvider() const {
-            return *m_sp;
-        }
+        const ServiceProvider& getServiceProvider() const;
 
         /**
          * Returns the Application's ID.
          *
          * @return  the ID
          */
-        virtual const char* getId() const {
-            return getString("id").second;
-        }
+        virtual const char* getId() const;
 
         /**
          * Returns a unique hash for the Application.
index 811d4ed..dea7654 100644 (file)
@@ -107,6 +107,10 @@ common_sources = \
        SPConfig.cpp \
        attribute/Attribute.cpp \
        attribute/ExtensibleAttribute.cpp \
+       attribute/NameIDAttribute.cpp \
+       attribute/SimpleAttribute.cpp \
+       attribute/ScopedAttribute.cpp \
+       attribute/XMLAttribute.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
        handler/impl/AssertionLookup.cpp \
@@ -164,6 +168,7 @@ libshibsp_la_SOURCES = \
        attribute/filtering/impl/AttributeFilter.cpp \
        attribute/filtering/impl/ChainingAttributeFilter.cpp \
        attribute/filtering/impl/XMLAttributeFilter.cpp \
+       attribute/filtering/impl/BasicFilteringContext.cpp \
        attribute/filtering/impl/MatchFunctor.cpp \
        attribute/filtering/impl/AndMatchFunctor.cpp \
        attribute/filtering/impl/AnyMatchFunctor.cpp \
@@ -195,13 +200,14 @@ libshibsp_la_SOURCES = \
        metadata/DynamicMetadataProvider.cpp \
        metadata/MetadataExtImpl.cpp \
        metadata/MetadataExtSchemaValidators.cpp \
+       metadata/MetadataProviderCriteria.cpp \
        security/PKIXTrustEngine.cpp \
        security/SecurityPolicy.cpp
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 4:0:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 4:0:0
 libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
 
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
index 43015a5..6e3bd9c 100644 (file)
@@ -76,6 +76,10 @@ am__objects_1 = libshibsp_lite_la-AbstractSPRequest.lo \
        libshibsp_lite_la-ServiceProvider.lo \
        libshibsp_lite_la-SPConfig.lo libshibsp_lite_la-Attribute.lo \
        libshibsp_lite_la-ExtensibleAttribute.lo \
+       libshibsp_lite_la-NameIDAttribute.lo \
+       libshibsp_lite_la-SimpleAttribute.lo \
+       libshibsp_lite_la-ScopedAttribute.lo \
+       libshibsp_lite_la-XMLAttribute.lo \
        libshibsp_lite_la-AbstractHandler.lo \
        libshibsp_lite_la-AssertionConsumerService.lo \
        libshibsp_lite_la-AssertionLookup.lo \
@@ -121,7 +125,8 @@ libshibsp_lite_la_OBJECTS = $(am_libshibsp_lite_la_OBJECTS)
 libshibsp_la_LIBADD =
 am__objects_2 = AbstractSPRequest.lo Application.lo ServiceProvider.lo \
        SPConfig.lo Attribute.lo ExtensibleAttribute.lo \
-       AbstractHandler.lo AssertionConsumerService.lo \
+       NameIDAttribute.lo SimpleAttribute.lo ScopedAttribute.lo \
+       XMLAttribute.lo AbstractHandler.lo AssertionConsumerService.lo \
        AssertionLookup.lo ChainingLogoutInitiator.lo \
        ChainingSessionInitiator.lo CookieSessionInitiator.lo \
        FormSessionInitiator.lo LocalLogoutInitiator.lo \
@@ -142,9 +147,9 @@ am_libshibsp_la_OBJECTS = $(am__objects_2) DOMAttributeDecoder.lo \
        NameIDFromScopedAttributeDecoder.lo ScopedAttributeDecoder.lo \
        StringAttributeDecoder.lo XMLAttributeDecoder.lo \
        AttributeFilter.lo ChainingAttributeFilter.lo \
-       XMLAttributeFilter.lo MatchFunctor.lo AndMatchFunctor.lo \
-       AnyMatchFunctor.lo NotMatchFunctor.lo OrMatchFunctor.lo \
-       AttributeIssuerStringFunctor.lo \
+       XMLAttributeFilter.lo BasicFilteringContext.lo MatchFunctor.lo \
+       AndMatchFunctor.lo AnyMatchFunctor.lo NotMatchFunctor.lo \
+       OrMatchFunctor.lo AttributeIssuerStringFunctor.lo \
        AttributeRequesterStringFunctor.lo \
        AttributeScopeStringFunctor.lo AttributeValueStringFunctor.lo \
        AuthenticationMethodStringFunctor.lo \
@@ -162,7 +167,8 @@ am_libshibsp_la_OBJECTS = $(am__objects_2) DOMAttributeDecoder.lo \
        KeyDescriptorAttributeExtractor.lo XMLAttributeExtractor.lo \
        ArtifactResolver.lo SOAPClient.lo DynamicMetadataProvider.lo \
        MetadataExtImpl.lo MetadataExtSchemaValidators.lo \
-       PKIXTrustEngine.lo SecurityPolicy.lo
+       MetadataProviderCriteria.lo PKIXTrustEngine.lo \
+       SecurityPolicy.lo
 libshibsp_la_OBJECTS = $(am_libshibsp_la_OBJECTS)
 DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -203,6 +209,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
@@ -490,6 +498,10 @@ common_sources = \
        SPConfig.cpp \
        attribute/Attribute.cpp \
        attribute/ExtensibleAttribute.cpp \
+       attribute/NameIDAttribute.cpp \
+       attribute/SimpleAttribute.cpp \
+       attribute/ScopedAttribute.cpp \
+       attribute/XMLAttribute.cpp \
        handler/impl/AbstractHandler.cpp \
        handler/impl/AssertionConsumerService.cpp \
        handler/impl/AssertionLookup.cpp \
@@ -547,6 +559,7 @@ libshibsp_la_SOURCES = \
        attribute/filtering/impl/AttributeFilter.cpp \
        attribute/filtering/impl/ChainingAttributeFilter.cpp \
        attribute/filtering/impl/XMLAttributeFilter.cpp \
+       attribute/filtering/impl/BasicFilteringContext.cpp \
        attribute/filtering/impl/MatchFunctor.cpp \
        attribute/filtering/impl/AndMatchFunctor.cpp \
        attribute/filtering/impl/AnyMatchFunctor.cpp \
@@ -578,14 +591,15 @@ libshibsp_la_SOURCES = \
        metadata/DynamicMetadataProvider.cpp \
        metadata/MetadataExtImpl.cpp \
        metadata/MetadataExtSchemaValidators.cpp \
+       metadata/MetadataProviderCriteria.cpp \
        security/PKIXTrustEngine.cpp \
        security/SecurityPolicy.cpp
 
 
 # this is different from the project version
 # http://sources.redhat.com/autobook/autobook/autobook_91.html
-libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 3:1:0
-libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 3:1:0
+libshibsp_la_LDFLAGS = $(XMLSEC_LIBS) -version-info 4:0:0
+libshibsp_lite_la_LDFLAGS = $(LITE_LIBS) -version-info 4:0:0
 libshibsp_lite_la_CPPFLAGS = -DSHIBSP_LITE
 pkgsysconfdir = $(sysconfdir)/@PACKAGE@
 pkgxmldir = $(datadir)/xml/@PACKAGE@
@@ -689,6 +703,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AttributeValueStringFunctor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthenticationMethodRegexFunctor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/AuthenticationMethodStringFunctor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/BasicFilteringContext.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/CGIParser.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAccessControl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ChainingAttributeExtractor.Plo@am__quote@
@@ -712,6 +727,8 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataExtImpl.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataExtSchemaValidators.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataGenerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/MetadataProviderCriteria.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NameIDFromScopedAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/NotMatchFunctor.Plo@am__quote@
@@ -731,6 +748,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SOAPClient.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SPConfig.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SPConstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScopedAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ScopedAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SecurityPolicy.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServiceProvider.Plo@am__quote@
@@ -738,6 +756,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Shib1SessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleAggregationAttributeResolver.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SimpleAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/SocketListener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StatusHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/StorageServiceSessionCache.Plo@am__quote@
@@ -748,6 +767,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/UnixListener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/WAYFSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAccessControl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeDecoder.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeExtractor.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/XMLAttributeFilter.Plo@am__quote@
@@ -773,6 +793,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-LocalLogoutInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-LogoutHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-MetadataGenerator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-RemotedHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAML1Consumer.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAML2ArtifactResolution.Plo@am__quote@
@@ -785,10 +806,12 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SAMLDSSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SPConfig.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SPConstants.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ServiceProvider.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SessionHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-Shib1SessionInitiator.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-SocketListener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-StatusHandler.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-StorageServiceSessionCache.Plo@am__quote@
@@ -798,6 +821,7 @@ distclean-compile:
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-UnixListener.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-WAYFSessionInitiator.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLAccessControl.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLRequestMapper.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-XMLServiceProvider.Plo@am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libshibsp_lite_la-ddf.Plo@am__quote@
@@ -865,6 +889,34 @@ libshibsp_lite_la-ExtensibleAttribute.lo: attribute/ExtensibleAttribute.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp
 
+libshibsp_lite_la-NameIDAttribute.lo: attribute/NameIDAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-NameIDAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo" -c -o libshibsp_lite_la-NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-NameIDAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/NameIDAttribute.cpp' object='libshibsp_lite_la-NameIDAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp
+
+libshibsp_lite_la-SimpleAttribute.lo: attribute/SimpleAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-SimpleAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo" -c -o libshibsp_lite_la-SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-SimpleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/SimpleAttribute.cpp' object='libshibsp_lite_la-SimpleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp
+
+libshibsp_lite_la-ScopedAttribute.lo: attribute/ScopedAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-ScopedAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo" -c -o libshibsp_lite_la-ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-ScopedAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/ScopedAttribute.cpp' object='libshibsp_lite_la-ScopedAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp
+
+libshibsp_lite_la-XMLAttribute.lo: attribute/XMLAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-XMLAttribute.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo" -c -o libshibsp_lite_la-XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo" "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-XMLAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/XMLAttribute.cpp' object='libshibsp_lite_la-XMLAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o libshibsp_lite_la-XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp
+
 libshibsp_lite_la-AbstractHandler.lo: handler/impl/AbstractHandler.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libshibsp_lite_la_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT libshibsp_lite_la-AbstractHandler.lo -MD -MP -MF "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo" -c -o libshibsp_lite_la-AbstractHandler.lo `test -f 'handler/impl/AbstractHandler.cpp' || echo '$(srcdir)/'`handler/impl/AbstractHandler.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo" "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Plo"; else rm -f "$(DEPDIR)/libshibsp_lite_la-AbstractHandler.Tpo"; exit 1; fi
@@ -1166,6 +1218,34 @@ ExtensibleAttribute.lo: attribute/ExtensibleAttribute.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ExtensibleAttribute.lo `test -f 'attribute/ExtensibleAttribute.cpp' || echo '$(srcdir)/'`attribute/ExtensibleAttribute.cpp
 
+NameIDAttribute.lo: attribute/NameIDAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT NameIDAttribute.lo -MD -MP -MF "$(DEPDIR)/NameIDAttribute.Tpo" -c -o NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/NameIDAttribute.Tpo" "$(DEPDIR)/NameIDAttribute.Plo"; else rm -f "$(DEPDIR)/NameIDAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/NameIDAttribute.cpp' object='NameIDAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o NameIDAttribute.lo `test -f 'attribute/NameIDAttribute.cpp' || echo '$(srcdir)/'`attribute/NameIDAttribute.cpp
+
+SimpleAttribute.lo: attribute/SimpleAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT SimpleAttribute.lo -MD -MP -MF "$(DEPDIR)/SimpleAttribute.Tpo" -c -o SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/SimpleAttribute.Tpo" "$(DEPDIR)/SimpleAttribute.Plo"; else rm -f "$(DEPDIR)/SimpleAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/SimpleAttribute.cpp' object='SimpleAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o SimpleAttribute.lo `test -f 'attribute/SimpleAttribute.cpp' || echo '$(srcdir)/'`attribute/SimpleAttribute.cpp
+
+ScopedAttribute.lo: attribute/ScopedAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT ScopedAttribute.lo -MD -MP -MF "$(DEPDIR)/ScopedAttribute.Tpo" -c -o ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/ScopedAttribute.Tpo" "$(DEPDIR)/ScopedAttribute.Plo"; else rm -f "$(DEPDIR)/ScopedAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/ScopedAttribute.cpp' object='ScopedAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o ScopedAttribute.lo `test -f 'attribute/ScopedAttribute.cpp' || echo '$(srcdir)/'`attribute/ScopedAttribute.cpp
+
+XMLAttribute.lo: attribute/XMLAttribute.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT XMLAttribute.lo -MD -MP -MF "$(DEPDIR)/XMLAttribute.Tpo" -c -o XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/XMLAttribute.Tpo" "$(DEPDIR)/XMLAttribute.Plo"; else rm -f "$(DEPDIR)/XMLAttribute.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/XMLAttribute.cpp' object='XMLAttribute.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o XMLAttribute.lo `test -f 'attribute/XMLAttribute.cpp' || echo '$(srcdir)/'`attribute/XMLAttribute.cpp
+
 AbstractHandler.lo: handler/impl/AbstractHandler.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT AbstractHandler.lo -MD -MP -MF "$(DEPDIR)/AbstractHandler.Tpo" -c -o AbstractHandler.lo `test -f 'handler/impl/AbstractHandler.cpp' || echo '$(srcdir)/'`handler/impl/AbstractHandler.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/AbstractHandler.Tpo" "$(DEPDIR)/AbstractHandler.Plo"; else rm -f "$(DEPDIR)/AbstractHandler.Tpo"; exit 1; fi
@@ -1509,6 +1589,13 @@ XMLAttributeFilter.lo: attribute/filtering/impl/XMLAttributeFilter.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o XMLAttributeFilter.lo `test -f 'attribute/filtering/impl/XMLAttributeFilter.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/XMLAttributeFilter.cpp
 
+BasicFilteringContext.lo: attribute/filtering/impl/BasicFilteringContext.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT BasicFilteringContext.lo -MD -MP -MF "$(DEPDIR)/BasicFilteringContext.Tpo" -c -o BasicFilteringContext.lo `test -f 'attribute/filtering/impl/BasicFilteringContext.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/BasicFilteringContext.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/BasicFilteringContext.Tpo" "$(DEPDIR)/BasicFilteringContext.Plo"; else rm -f "$(DEPDIR)/BasicFilteringContext.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='attribute/filtering/impl/BasicFilteringContext.cpp' object='BasicFilteringContext.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o BasicFilteringContext.lo `test -f 'attribute/filtering/impl/BasicFilteringContext.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/BasicFilteringContext.cpp
+
 MatchFunctor.lo: attribute/filtering/impl/MatchFunctor.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT MatchFunctor.lo -MD -MP -MF "$(DEPDIR)/MatchFunctor.Tpo" -c -o MatchFunctor.lo `test -f 'attribute/filtering/impl/MatchFunctor.cpp' || echo '$(srcdir)/'`attribute/filtering/impl/MatchFunctor.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/MatchFunctor.Tpo" "$(DEPDIR)/MatchFunctor.Plo"; else rm -f "$(DEPDIR)/MatchFunctor.Tpo"; exit 1; fi
@@ -1726,6 +1813,13 @@ MetadataExtSchemaValidators.lo: metadata/MetadataExtSchemaValidators.cpp
 @AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o MetadataExtSchemaValidators.lo `test -f 'metadata/MetadataExtSchemaValidators.cpp' || echo '$(srcdir)/'`metadata/MetadataExtSchemaValidators.cpp
 
+MetadataProviderCriteria.lo: metadata/MetadataProviderCriteria.cpp
+@am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT MetadataProviderCriteria.lo -MD -MP -MF "$(DEPDIR)/MetadataProviderCriteria.Tpo" -c -o MetadataProviderCriteria.lo `test -f 'metadata/MetadataProviderCriteria.cpp' || echo '$(srcdir)/'`metadata/MetadataProviderCriteria.cpp; \
+@am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/MetadataProviderCriteria.Tpo" "$(DEPDIR)/MetadataProviderCriteria.Plo"; else rm -f "$(DEPDIR)/MetadataProviderCriteria.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     source='metadata/MetadataProviderCriteria.cpp' object='MetadataProviderCriteria.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@     DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o MetadataProviderCriteria.lo `test -f 'metadata/MetadataProviderCriteria.cpp' || echo '$(srcdir)/'`metadata/MetadataProviderCriteria.cpp
+
 PKIXTrustEngine.lo: security/PKIXTrustEngine.cpp
 @am__fastdepCXX_TRUE@  if $(LIBTOOL) --tag=CXX --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT PKIXTrustEngine.lo -MD -MP -MF "$(DEPDIR)/PKIXTrustEngine.Tpo" -c -o PKIXTrustEngine.lo `test -f 'security/PKIXTrustEngine.cpp' || echo '$(srcdir)/'`security/PKIXTrustEngine.cpp; \
 @am__fastdepCXX_TRUE@  then mv -f "$(DEPDIR)/PKIXTrustEngine.Tpo" "$(DEPDIR)/PKIXTrustEngine.Plo"; else rm -f "$(DEPDIR)/PKIXTrustEngine.Tpo"; exit 1; fi
index 646cbdd..12971e2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <shibsp/base.h>
 #include <xmltooling/Lockable.h>
-#include <xmltooling/io/HTTPRequest.h>
+
+namespace xmltooling {
+    class XMLTOOL_API HTTPRequest;
+};
 
 namespace shibsp {
 
@@ -42,9 +45,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(RequestMapper);
     protected:
-        RequestMapper() {}
+        RequestMapper();
     public:
-        virtual ~RequestMapper() {}
+        virtual ~RequestMapper();
 
         /** Combination of configuration settings and effective access control. */
         typedef std::pair<const PropertySet*,AccessControl*> Settings;
index cbc9f8c..c5c8d4e 100644 (file)
@@ -18,7 +18,7 @@
 /**
  * SPConfig.cpp
  *
- * Library configuration
+ * Library configuration.
  */
 
 #include "internal.h"
@@ -41,6 +41,7 @@
 #include "ServiceProvider.h"
 #include "SessionCache.h"
 #include "SPConfig.h"
+#include "TransactionLog.h"
 #include "attribute/Attribute.h"
 #include "handler/SessionInitiator.h"
 #include "remoting/ListenerService.h"
 # include "metadata/MetadataExt.h"
 # include "security/PKIXTrustEngine.h"
 # include <saml/SAMLConfig.h>
-#else
-# include <xmltooling/XMLToolingConfig.h>
 #endif
 
 #include <ctime>
 #include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
 #include <xmltooling/util/PathResolver.h>
 #include <xmltooling/util/TemplateEngine.h>
+#include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
@@ -96,12 +98,52 @@ SPConfig& SPConfig::getConfig()
     return g_config;
 }
 
+SPConfig::SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL),
+#ifndef SHIBSP_LITE
+    m_artifactResolver(NULL),
+#endif
+    m_features(0), m_configDoc(NULL)
+{
+}
+
+SPConfig::~SPConfig()
+{
+}
+
+void SPConfig::setFeatures(unsigned long enabled)
+{
+    m_features = enabled;
+}
+
+bool SPConfig::isEnabled(components_t feature)
+{
+    return (m_features & feature)>0;
+}
+
+ServiceProvider* SPConfig::getServiceProvider() const
+{
+    return m_serviceProvider;
+}
+
 void SPConfig::setServiceProvider(ServiceProvider* serviceProvider)
 {
     delete m_serviceProvider;
     m_serviceProvider = serviceProvider;
 }
 
+#ifndef SHIBSP_LITE
+void SPConfig::setArtifactResolver(MessageDecoder::ArtifactResolver* artifactResolver)
+{
+    delete m_artifactResolver;
+    m_artifactResolver = artifactResolver;
+}
+
+const MessageDecoder::ArtifactResolver* SPConfig::getArtifactResolver() const
+{
+    return m_artifactResolver;
+}
+#endif
+
 bool SPConfig::init(const char* catalog_path, const char* inst_prefix)
 {
 #ifdef _DEBUG
@@ -342,3 +384,23 @@ bool SPConfig::instantiate(const char* config, bool rethrow)
     }
     return false;
 }
+
+TransactionLog::TransactionLog() : log(logging::Category::getInstance(SHIBSP_TX_LOGCAT)), m_lock(Mutex::create())
+{
+}
+
+TransactionLog::~TransactionLog()
+{
+    delete m_lock;
+}
+
+Lockable* TransactionLog::lock()
+{
+    m_lock->lock();
+    return this;
+}
+
+void TransactionLog::unlock()
+{
+    m_lock->unlock();
+}
index 99f1a22..3764eda 100644 (file)
 #define __shibsp_config_h__
 
 #include <shibsp/base.h>
+
+#include <string>
 #ifndef SHIBSP_LITE
 # include <saml/binding/MessageDecoder.h>
+# include <saml/binding/MessageEncoder.h>
 #endif
 #include <xmltooling/PluginManager.h>
+#include <xmltooling/QName.h>
 #include <xercesc/dom/DOM.hpp>
 
 /**
@@ -65,14 +69,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(SPConfig);
     public:
-        SPConfig() : attribute_value_delimeter(';'), m_serviceProvider(NULL),
-#ifndef SHIBSP_LITE
-            m_artifactResolver(NULL),
-#endif
-            m_features(0), m_configDoc(NULL) {
-        }
+        SPConfig();
 
-        virtual ~SPConfig() {}
+        virtual ~SPConfig();
 
         /**
          * Returns the global configuration object for the library.
@@ -105,9 +104,7 @@ namespace shibsp {
          *
          * @param enabled   bitmask of component constants
          */
-        void setFeatures(unsigned long enabled) {
-            m_features = enabled;
-        }
+        void setFeatures(unsigned long enabled);
 
         /**
          * Test whether a subsystem is enabled.
@@ -115,9 +112,7 @@ namespace shibsp {
          * @param feature   subsystem/component to test
          * @return true iff feature is enabled
          */
-        bool isEnabled(components_t feature) {
-            return (m_features & feature)>0;
-        }
+        bool isEnabled(components_t feature);
 
         /**
          * Initializes library
@@ -153,9 +148,7 @@ namespace shibsp {
          *
          * @return  global ServiceProvider or NULL
          */
-        ServiceProvider* getServiceProvider() const {
-            return m_serviceProvider;
-        }
+        ServiceProvider* getServiceProvider() const;
 
         /**
          * Instantiates and installs a ServiceProvider instance based on an XML configuration string
@@ -176,19 +169,14 @@ namespace shibsp {
          *
          * @param artifactResolver   new ArtifactResolver instance to store
          */
-        void setArtifactResolver(opensaml::MessageDecoder::ArtifactResolver* artifactResolver) {
-            delete m_artifactResolver;
-            m_artifactResolver = artifactResolver;
-        }
+        void setArtifactResolver(opensaml::MessageDecoder::ArtifactResolver* artifactResolver);
 
         /**
          * Returns the global ArtifactResolver instance.
          *
          * @return  global ArtifactResolver or NULL
          */
-        const opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const {
-            return m_artifactResolver;
-        }
+        const opensaml::MessageDecoder::ArtifactResolver* getArtifactResolver() const;
 #endif
 
         /** Separator for serialized values of multi-valued attributes. */
index 255e8b5..6ce9eff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 /**
  * @file shibsp/SPRequest.h
  *
- * Interface to server request being processed
+ * Interface to server request being processed.
  */
 
 #ifndef __shibsp_req_h__
@@ -45,9 +45,9 @@ namespace shibsp {
     class SHIBSP_API SPRequest : public virtual xmltooling::HTTPRequest, public virtual xmltooling::HTTPResponse
     {
     protected:
-        SPRequest() {}
+        SPRequest();
     public:
-        virtual ~SPRequest() {}
+        virtual ~SPRequest();
 
         /**
          * Returns the locked ServiceProvider processing the request.
@@ -98,9 +98,7 @@ namespace shibsp {
          * @param name  the name of the secure header to return
          * @return the header's value, or an empty string
          */
-        virtual std::string getSecureHeader(const char* name) const {
-            return getHeader(name);
-        }
+        virtual std::string getSecureHeader(const char* name) const;
 
         /**
          * Ensures no value exists for a request header.
@@ -130,8 +128,7 @@ namespace shibsp {
          *
          * @param authtype  AUTH_TYPE value to set or NULL to clear
          */
-        virtual void setAuthType(const char* authtype) {
-        }
+        virtual void setAuthType(const char* authtype);
 
         /** Portable logging levels. */
         enum SPLogLevel {
index 0006dbc..a43a9e0 100644 (file)
 
 #include <fstream>
 #include <sstream>
+#ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
+#endif
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/PathResolver.h>
@@ -99,23 +103,30 @@ namespace shibsp {
             if (!pathname.first)
                 pathname=props->getString(page);
         }
-        if (pathname.first) {
-            string fname(pathname.second);
-            ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
-            if (infile) {
-                tp.setPropertySet(props);
-                stringstream str;
-                XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException());
-                return request.sendError(str);
-            }
+
+        string fname;
+        if (!pathname.first) {
+            fname = string(page) + "Error.html";
+            pathname.second = fname.c_str();
+        }
+        else {
+            fname = pathname.second;
+        }
+
+        ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
+        if (infile) {
+            tp.setPropertySet(props);
+            stringstream str;
+            XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp, tp.getRichException());
+            return request.sendError(str);
         }
 
-        if (!strcmp(page,"access")) {
+        if (!strcmp(page, "access")) {
             istringstream msg("Access Denied");
             return request.sendResponse(msg, HTTPResponse::XMLTOOLING_HTTP_STATUS_FORBIDDEN);
         }
 
-        log.error("sendError could not process error template (%s)", page);
+        log.error("sendError could not process error template (%s)", pathname.second);
         istringstream msg("Internal Server Error. Please contact the site administrator.");
         return request.sendError(msg);
     }
@@ -139,6 +150,14 @@ void SHIBSP_API shibsp::registerServiceProviders()
     SPConfig::getConfig().ServiceProviderManager.registerFactory(XML_SERVICE_PROVIDER, XMLServiceProviderFactory);
 }
 
+ServiceProvider::ServiceProvider()
+{
+}
+
+ServiceProvider::~ServiceProvider()
+{
+}
+
 pair<bool,long> ServiceProvider::doAuthentication(SPRequest& request, bool handler) const
 {
 #ifdef _DEBUG
index 9ef1dae..2d0694a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #define __shibsp_sp_h__
 
 #include <shibsp/util/PropertySet.h>
+
+#include <xmltooling/Lockable.h>
+
+namespace xmltooling {
+    class XMLTOOL_API SOAPTransport;
+    class XMLTOOL_API StorageService;
+};
+
 #ifndef SHIBSP_LITE
-# include <saml/binding/SecurityPolicyRule.h>
-# include <xmltooling/soap/SOAPTransport.h>
-# include <xmltooling/util/StorageService.h>
+namespace opensaml {
+    class SAML_API SecurityPolicyRule;
+};
 #endif
-#include <xmltooling/Lockable.h>
 
 namespace shibsp {
 
@@ -54,9 +61,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(ServiceProvider);
     protected:
-        ServiceProvider() {}
+        ServiceProvider();
     public:
-        virtual ~ServiceProvider() {}
+        virtual ~ServiceProvider();
         
         /**
          * Loads a configuration and prepares the instance for use.
index ad3af9d..38fa126 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 /**
  * @file shibsp/SessionCache.h
  *
- * Caches and manages user sessions
+ * Caches and manages user sessions.
  */
 
 #ifndef __shibsp_sessioncache_h__
 #define __shibsp_sessioncache_h__
 
 #include <shibsp/base.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <ctime>
+#include <xmltooling/Lockable.h>
+
+namespace xmltooling {
+    class XMLTOOL_API HTTPRequest;
+    class XMLTOOL_API HTTPResponse;
+};
+
 #ifndef SHIBSP_LITE
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
+# include <set>
+namespace opensaml {
+    class SAML_API Assertion;
+    namespace saml2 {
+        class SAML_API NameID;
+    };
+};
 #endif
-#include <xmltooling/Lockable.h>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
 
 namespace shibsp {
 
@@ -49,8 +64,8 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(Session);
     protected:
-        Session() {}
-        virtual ~Session() {}
+        Session();
+        virtual ~Session();
     public:
         /**
          * Returns the session key.
@@ -203,9 +218,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(SessionCache);
     protected:
-        SessionCache() {}
+        SessionCache();
     public:
-        virtual ~SessionCache() {}
+        virtual ~SessionCache();
 
 #ifndef SHIBSP_LITE
         /**
index b71f568..61a35fb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,9 +33,9 @@ namespace shibsp {
     class SHIBSP_API SessionCacheEx : public SessionCache
     {
     protected:
-        SessionCacheEx() {}
+        SessionCacheEx();
     public:
-        virtual ~SessionCacheEx() {}
+        virtual ~SessionCacheEx();
         
 #ifndef SHIBSP_LITE
         /**
index 64ba2bc..96461c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include <shibsp/base.h>
 #include <xmltooling/logging.h>
 #include <xmltooling/Lockable.h>
-#include <xmltooling/util/Threads.h>
 
-namespace shibsp {
+namespace xmltooling {
+    class XMLTOOL_API Mutex;
+};
 
+namespace shibsp {
     /**
      * Interface to a synchronized logging object.
      * 
@@ -39,22 +41,13 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(TransactionLog);
     public:
-        TransactionLog()
-            : log(xmltooling::logging::Category::getInstance(SHIBSP_TX_LOGCAT)), m_lock(xmltooling::Mutex::create()) {
-        }
+        TransactionLog();
 
-        virtual ~TransactionLog() {
-            delete m_lock;
-        }
+        virtual ~TransactionLog();
         
-        xmltooling::Lockable* lock() {
-            m_lock->lock();
-            return this;
-        }
+        xmltooling::Lockable* lock();
 
-        void unlock() {
-            m_lock->unlock();
-        }
+        void unlock();
 
         /** Logging object. */
         xmltooling::logging::Category& log;
index 36c32bc..8b99f45 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "SPConfig.h"
 #ifndef SHIBSP_LITE
 # include "attribute/AttributeDecoder.h"
 #include "attribute/XMLAttribute.h"
 #include "util/SPConstants.h"
 
-#include <xercesc/util/Base64.hpp>
 #include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/security/SecurityHelper.h>
 
 using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
 namespace shibsp {
-
-    SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in) {
-        return new SimpleAttribute(in);
-    }
-
-    SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in) {
-        return new ScopedAttribute(in);
-    }
-
-    SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in) {
-        return new NameIDAttribute(in);
-    }
-
-    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
-        return new ExtensibleAttribute(in);
-    }
-
-    SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
-        return new XMLAttribute(in);
-    }
+    SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in);
+    SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in);
+    SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in);
+    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in);
+    SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in);
 
 #ifndef SHIBSP_LITE
     SHIBSP_DLLLOCAL PluginManager<AttributeDecoder,xmltooling::QName,const DOMElement*>::Factory StringAttributeDecoderFactory;
@@ -79,6 +65,7 @@ namespace shibsp {
     static const XMLCh _XMLAttributeDecoder[] =    UNICODE_LITERAL_19(X,M,L,A,t,t,r,i,b,u,t,e,D,e,c,o,d,e,r);
 
     static const XMLCh caseSensitive[] =           UNICODE_LITERAL_13(c,a,s,e,S,e,n,s,i,t,i,v,e);
+    static const XMLCh hashAlg[] =                 UNICODE_LITERAL_7(h,a,s,h,A,l,g);
     static const XMLCh internal[] =                UNICODE_LITERAL_8(i,n,t,e,r,n,a,l);
 #endif
 };
@@ -104,7 +91,8 @@ void shibsp::registerAttributeDecoders()
     conf.AttributeDecoderManager.registerFactory(XMLAttributeDecoderType, XMLAttributeDecoderFactory);
 }
 
-AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true), m_internal(false)
+AttributeDecoder::AttributeDecoder(const DOMElement *e)
+    : m_caseSensitive(true), m_internal(false), m_hashAlg(e ? e->getAttributeNS(NULL, hashAlg) : NULL)
 {
     if (e) {
         const XMLCh* flag = e->getAttributeNS(NULL, caseSensitive);
@@ -116,6 +104,36 @@ AttributeDecoder::AttributeDecoder(const DOMElement *e) : m_caseSensitive(true),
             m_internal = true;
     }
 }
+
+AttributeDecoder::~AttributeDecoder()
+{
+}
+
+Attribute* AttributeDecoder::_decode(Attribute* attr) const
+{
+    if (attr) {
+        attr->setCaseSensitive(m_caseSensitive);
+        attr->setInternal(m_internal);
+
+        if (m_hashAlg.get() && *m_hashAlg.get()) {
+            // We turn the values into strings using the supplied hash algorithm and return a SimpleAttribute instead.
+            auto_ptr<SimpleAttribute> simple(new SimpleAttribute(attr->getAliases()));
+            simple->setCaseSensitive(false);
+            simple->setInternal(m_internal);
+            vector<string>& newdest = simple->getValues();
+            const vector<string>& serialized = attr->getSerializedValues();
+            for (vector<string>::const_iterator ser = serialized.begin(); ser != serialized.end(); ++ser) {
+                newdest.push_back(SecurityHelper::doHash(m_hashAlg.get(), ser->data(), ser->length()));
+                if (newdest.back().empty())
+                    newdest.pop_back();
+            }
+            delete attr;
+            return newdest.empty() ? NULL : simple.release();
+        }
+
+    }
+    return attr;
+}
 #endif
 
 void shibsp::registerAttributeFactories()
@@ -130,6 +148,25 @@ void shibsp::registerAttributeFactories()
 
 map<string,Attribute::AttributeFactory*> Attribute::m_factoryMap;
 
+void Attribute::registerFactory(const char* type, AttributeFactory* factory)
+{
+    m_factoryMap[type] = factory;
+}
+
+void Attribute::deregisterFactory(const char* type)
+{
+    m_factoryMap.erase(type);
+}
+
+void Attribute::deregisterFactories()
+{
+    m_factoryMap.clear();
+}
+
+Attribute::Attribute(const vector<string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false)
+{
+}
+
 Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull()), m_internal(!in["internal"].isnull())
 {
     const char* id = in.first().name();
@@ -147,6 +184,71 @@ Attribute::Attribute(DDF& in) : m_caseSensitive(in["case_insensitive"].isnull())
     }
 }
 
+Attribute::~Attribute()
+{
+}
+
+const char* Attribute::getId() const
+{
+    return m_id.front().c_str();
+}
+
+const vector<string>& Attribute::getAliases() const
+{
+    return m_id;
+}
+
+vector<string>& Attribute::getAliases()
+{
+    return m_id;
+}
+
+void Attribute::setCaseSensitive(bool caseSensitive)
+{
+    m_caseSensitive = caseSensitive;
+}
+
+void Attribute::setInternal(bool internal)
+{
+    m_internal = internal;
+}
+
+bool Attribute::isCaseSensitive() const
+{
+    return m_caseSensitive;
+}
+
+bool Attribute::isInternal() const
+{
+    return m_internal;
+}
+
+size_t Attribute::valueCount() const
+{
+    return m_serialized.size();
+}
+
+const vector<string>& Attribute::getSerializedValues() const
+{
+    return m_serialized;
+}
+
+const char* Attribute::getString(size_t index) const
+{
+    return m_serialized[index].c_str();
+}
+
+const char* Attribute::getScope(size_t index) const
+{
+    return NULL;
+}
+
+void Attribute::removeValue(size_t index)
+{
+    if (index < m_serialized.size())
+        m_serialized.erase(m_serialized.begin() + index);
+}
+
 DDF Attribute::marshall() const
 {
     DDF ddf(NULL);
@@ -173,27 +275,3 @@ Attribute* Attribute::unmarshall(DDF& in)
         throw AttributeException("No registered factory for Attribute of type ($1).", params(1,in.name()));
     return (i->second)(in);
 }
-
-const vector<string>& XMLAttribute::getSerializedValues() const
-{
-    xsecsize_t len;
-    XMLByte *pos, *pos2;\r
-    if (m_serialized.empty()) {
-        for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
-            XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
-            if (enc) {
-                for (pos=enc, pos2=enc; *pos2; pos2++)\r
-                    if (isgraph(*pos2))\r
-                        *pos++=*pos2;\r
-                *pos=0;\r
-                m_serialized.push_back(reinterpret_cast<char*>(enc));
-#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
-                XMLString::release(&enc);
-#else
-                XMLString::release((char**)&enc);
-#endif
-            }
-        }
-    }
-    return Attribute::getSerializedValues();
-}
index 37e1d39..39dae79 100644 (file)
@@ -23,7 +23,6 @@
 #ifndef __shibsp_attribute_h__
 #define __shibsp_attribute_h__
 
-#include <shibsp/exceptions.h>
 #include <shibsp/remoting/ddf.h>
 
 #include <map>
@@ -59,8 +58,7 @@ namespace shibsp {
          *
          * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        Attribute(const std::vector<std::string>& ids) : m_id(ids), m_caseSensitive(true), m_internal(false) {
-        }
+        Attribute(const std::vector<std::string>& ids);
 
         /**
          * Constructs based on a remoted Attribute.
@@ -81,88 +79,70 @@ namespace shibsp {
         mutable std::vector<std::string> m_serialized;
 
     public:
-        virtual ~Attribute() {}
+        virtual ~Attribute();
 
         /**
          * Returns the Attribute identifier.
          *
          * @return the Attribute identifier
          */
-        const char* getId() const {
-            return m_id.front().c_str();
-        }
+        const char* getId() const;
 
         /**
          * Returns all of the effective names for the Attribute.
          *
          * @return immutable array of identifiers, with the primary ID in the first position
          */
-        const std::vector<std::string>& getAliases() const {
-            return m_id;
-        }
+        const std::vector<std::string>& getAliases() const;
 
         /**
          * Returns all of the effective names for the Attribute.
          *
          * @return mutable array of identifiers, with the primary ID in the first position
          */
-        std::vector<std::string>& getAliases() {
-            return m_id;
-        }
+        std::vector<std::string>& getAliases();
 
         /**
          * Sets whether case sensitivity should apply to basic value comparisons.
          *
          * @param caseSensitive  true iff value comparisons should be case sensitive
          */
-        void setCaseSensitive(bool caseSensitive) {
-            m_caseSensitive = caseSensitive;
-        }
+        void setCaseSensitive(bool caseSensitive);
 
         /**
          * Sets whether the attribute should be exported for CGI use.
          *
          * @param export  true iff the attribute should <strong>NOT</strong> be exported
          */
-        void setInternal(bool internal) {
-            m_internal = internal;
-        }
+        void setInternal(bool internal);
 
         /**
          * Indicates whether case sensitivity should apply to basic value comparisons.
          *
          * @return  true iff value comparisons should be case sensitive
          */
-        bool isCaseSensitive() const {
-            return m_caseSensitive;
-        }
+        bool isCaseSensitive() const;
 
         /**
          * Indicates whether the attribute should be exported for CGI use.
          *
          * @return  true iff the attribute should <strong>NOT</strong> be exported
          */
-        bool isInternal() const {
-            return m_internal;
-        }
+        bool isInternal() const;
 
         /**
          * Returns the number of values.
          *
          * @return  number of values
          */
-        virtual size_t valueCount() const {
-            return m_serialized.size();
-        }
+        virtual size_t valueCount() const;
 
         /**
          * Returns serialized Attribute values encoded as UTF-8 strings.
          *
          * @return  an immutable vector of values
          */
-        virtual const std::vector<std::string>& getSerializedValues() const {
-            return m_serialized;
-        }
+        virtual const std::vector<std::string>& getSerializedValues() const;
 
         /**
          * Informs the Attribute that values have changed and any serializations
@@ -176,9 +156,7 @@ namespace shibsp {
          * @param index position of value
          * @return the specified value in its "string" form, or NULL if undefined
          */
-        virtual const char* getString(size_t index) const {
-            return m_serialized[index].c_str();
-        }
+        virtual const char* getString(size_t index) const;
 
         /**
          * Gets the "scope" of the value at the specified position (starting from zero).
@@ -186,19 +164,14 @@ namespace shibsp {
          * @param index position of value
          * @return the specified value's "scope", or NULL if attribute is unscoped
          */
-        virtual const char* getScope(size_t index) const {
-            return NULL;
-        }
+        virtual const char* getScope(size_t index) const;
 
         /**
          * Removes the value at the specified position (starting from zero).
          *
          * @param index position of value to remove
          */
-        virtual void removeValue(size_t index) {
-            if (index < m_serialized.size())
-                m_serialized.erase(m_serialized.begin() + index);
-        }
+        virtual void removeValue(size_t index);
 
         /**
          * Marshalls an Attribute for remoting.
@@ -227,25 +200,19 @@ namespace shibsp {
          * @param type      string used at the root of remoted Attribute structures
          * @param factory   factory function
          */
-        static void registerFactory(const char* type, AttributeFactory* factory) {
-            m_factoryMap[type] = factory;
-        }
+        static void registerFactory(const char* type, AttributeFactory* factory);
 
         /**
          * Deregisters an AttributeFactory function for a given attribute "type".
          *
          * @param type      string used at the root of remoted Attribute structures
          */
-        static void deregisterFactory(const char* type) {
-            m_factoryMap.erase(type);
-        }
+        static void deregisterFactory(const char* type);
 
         /**
          * Clears the map of factories.
          */
-        static void deregisterFactories() {
-            m_factoryMap.clear();
-        }
+        static void deregisterFactories();
 
     private:
         static std::map<std::string,AttributeFactory*> m_factoryMap;
index 5b0ad48..a4ffd04 100644 (file)
 #ifndef __shibsp_attrdecoder_h__
 #define __shibsp_attrdecoder_h__
 
-#include <shibsp/attribute/Attribute.h>
-#include <xmltooling/XMLObject.h>
+#include <shibsp/base.h>
+
+#include <string>
+#include <vector>
+
+namespace xmltooling {
+    class XMLTOOL_API QName;
+    class XMLTOOL_API XMLObject;
+};
 
 namespace shibsp {
 
+    class SHIBSP_API Attribute;
+
     /**
      * Decodes XML objects into resolved Attributes.
      */
@@ -48,20 +57,19 @@ namespace shibsp {
         /** Flag for hiding attributes from CGI export. */
         bool m_internal;
 
+        /** Hash algorithm to apply to decoded values. */
+        xmltooling::auto_ptr_char m_hashAlg;
+
         /**
          * Helper method to handle base class decoding housekeeping.
          *
          * @param attr  the new Attribute object being created
          * @return  the attr parameter
          */
-        virtual Attribute* _decode(Attribute* attr) const {
-            attr->setCaseSensitive(m_caseSensitive);
-            attr->setInternal(m_internal);
-            return attr;
-        }
+        virtual Attribute* _decode(Attribute* attr) const;
 
     public:
-        virtual ~AttributeDecoder() {}
+        virtual ~AttributeDecoder();
 
         /**
          * Decodes an XMLObject into a resolved Attribute.
index 98cb87c..d996be3 100644 (file)
-/*\r
- *  Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * DOMAttributeDecoder.cpp\r
- *\r
- * Decodes a DOM into an ExtensibleAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/ExtensibleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        DOMAttributeDecoder(const DOMElement* e);\r
-        ~DOMAttributeDecoder() {}\r
-\r
-        Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-\r
-    private:\r
-        DDF convert(DOMElement* e, bool nameit=true) const;\r
-        auto_ptr_char m_formatter;\r
-        map<pair<xstring,xstring>,string> m_tagMap;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new DOMAttributeDecoder(e);\r
-    }\r
-\r
-    static const XMLCh Mapping[] =  UNICODE_LITERAL_7(M,a,p,p,i,n,g);\r
-    static const XMLCh _from[] =    UNICODE_LITERAL_4(f,r,o,m);\r
-    static const XMLCh _to[] =      UNICODE_LITERAL_2(t,o);\r
-    static const XMLCh formatter[] =      UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
-};\r
-\r
-DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)\r
-    : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)\r
-{\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
-\r
-    e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;\r
-    while (e) {\r
-        if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {\r
-            auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));\r
-            auto_ptr_char t(e->getAttributeNS(NULL, _to));\r
-            if (f.get() && t.get() && *t.get()) {\r
-                if (log.isDebugEnabled())\r
-                    log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());\r
-                m_tagMap.insert(\r
-                    pair< const pair<xstring,xstring>,string>(\r
-                        pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),\r
-                        t.get()\r
-                        )\r
-                    );\r
-            }\r
-        }\r
-        e = XMLHelper::getNextSiblingElement(e, Mapping);\r
-    }\r
-}\r
-\r
-Attribute* DOMAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");\r
-\r
-    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
-        log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
-        return NULL;\r
-    }\r
-\r
-    auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));\r
-    DDF dest = attr->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
-    if (saml2attr) {\r
-        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
-        v = values.begin();\r
-        stop = values.end();\r
-        if (log.isDebugEnabled()) {\r
-            auto_ptr_char n(saml2attr->getName());\r
-            log.debug(\r
-                "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
-                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                );\r
-        }\r
-    }\r
-    else {\r
-        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
-        if (saml1attr) {\r
-            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
-            v = values.begin();\r
-            stop = values.end();\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char n(saml1attr->getAttributeName());\r
-                log.debug(\r
-                    "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-            }\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    for (; v!=stop; ++v) {\r
-        DOMElement* e = (*v)->getDOM();\r
-        if (e) {\r
-            DDF converted = convert(e, false);\r
-            if (!converted.isnull())\r
-                dest.add(converted);\r
-        }\r
-        else\r
-            log.warn("skipping AttributeValue without a backing DOM");\r
-    }\r
-\r
-    return dest.integer() ? _decode(attr.release()) : NULL;\r
-}\r
-\r
-DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const\r
-{\r
-    const XMLCh* nsURI;\r
-    const XMLCh* local;\r
-    map<pair<xstring,xstring>,string>::const_iterator mapping;\r
-    DDF obj = DDF(NULL).structure();\r
-\r
-    if (nameit) {\r
-        // Name this structure.\r
-        nsURI = e->getNamespaceURI();\r
-        local = e->getLocalName();\r
-        mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));\r
-        if (mapping == m_tagMap.end()) {\r
-            auto_ptr_char temp(local);\r
-            obj.name(temp.get());\r
-        }\r
-        else {\r
-            obj.name(mapping->second.c_str());\r
-        }\r
-    }\r
-\r
-    // Process non-xmlns attributes.\r
-    DOMNamedNodeMap* attrs = e->getAttributes();\r
-    for (XMLSize_t a = attrs->getLength(); a > 0; --a) {\r
-        DOMNode* attr = attrs->item(a-1);\r
-        nsURI = attr->getNamespaceURI();\r
-        if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))\r
-            continue;\r
-        local = attr->getLocalName();\r
-        mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));\r
-        if (mapping == m_tagMap.end()) {\r
-            auto_ptr_char temp(local);\r
-            obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);\r
-        }\r
-        else {\r
-            obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);\r
-        }\r
-    }\r
-\r
-    DOMElement* child = XMLHelper::getFirstChildElement(e);\r
-    if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {\r
-        // Attach a _text member if a text node is present.\r
-        obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);\r
-    }\r
-    else {\r
-        while (child) {\r
-            // Convert the child element.\r
-            DDF converted = convert(child);\r
-            if (!converted.isnull()) {\r
-                // Now identify it and attach it.\r
-                if (obj[converted.name()].isnull()) {\r
-                    // We're a new child, so just attach as a structure member.\r
-                    obj.add(converted);\r
-                }\r
-                else if (obj[converted.name()].islist()) {\r
-                    // We're already a repeating child, so add it to the list.\r
-                    obj[converted.name()].add(converted);\r
-                }\r
-                else if (obj[converted.name()].isstruct()) {\r
-                    // This is the complex case where we see a child for the second\r
-                    // time and have to convert a structure member into a named list.\r
-                    DDF newlist = DDF(converted.name()).list();\r
-                    newlist.add(obj[converted.name()].remove());\r
-                    newlist.add(converted);\r
-                    obj.add(newlist);\r
-                }\r
-            }\r
-            child = XMLHelper::getNextSiblingElement(child);\r
-        }\r
-    }\r
-\r
-    // If we're empty, just delete.\r
-    if (obj.integer() == 0)\r
-        obj.destroy();\r
-    return obj;\r
-}\r
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * DOMAttributeDecoder.cpp
+ *
+ * Decodes a DOM into an ExtensibleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/ExtensibleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL DOMAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        DOMAttributeDecoder(const DOMElement* e);
+        ~DOMAttributeDecoder() {}
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        DDF convert(DOMElement* e, bool nameit=true) const;
+        auto_ptr_char m_formatter;
+        map<pair<xstring,xstring>,string> m_tagMap;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL DOMAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new DOMAttributeDecoder(e);
+    }
+
+    static const XMLCh Mapping[] =  UNICODE_LITERAL_7(M,a,p,p,i,n,g);
+    static const XMLCh _from[] =    UNICODE_LITERAL_4(f,r,o,m);
+    static const XMLCh _to[] =      UNICODE_LITERAL_2(t,o);
+    static const XMLCh formatter[] =      UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+};
+
+DOMAttributeDecoder::DOMAttributeDecoder(const DOMElement* e)
+    : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL,formatter) : NULL)
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+    e = e ? XMLHelper::getFirstChildElement(e, Mapping) : NULL;
+    while (e) {
+        if (e->hasAttributeNS(NULL, _from) && e->hasAttributeNS(NULL, _to)) {
+            auto_ptr<xmltooling::QName> f(XMLHelper::getNodeValueAsQName(e->getAttributeNodeNS(NULL, _from)));
+            auto_ptr_char t(e->getAttributeNS(NULL, _to));
+            if (f.get() && t.get() && *t.get()) {
+                if (log.isDebugEnabled())
+                    log.debug("mapping (%s) to (%s)", f->toString().c_str(), t.get());
+                m_tagMap.insert(
+                    pair< const pair<xstring,xstring>,string>(
+                        pair<xstring,xstring>(f->getLocalPart(), f->hasNamespaceURI() ? f->getNamespaceURI() : &chNull),
+                        t.get()
+                        )
+                    );
+            }
+        }
+        e = XMLHelper::getNextSiblingElement(e, Mapping);
+    }
+}
+
+Attribute* DOMAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.DOM");
+
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+        return NULL;
+    }
+
+    auto_ptr<ExtensibleAttribute> attr(new ExtensibleAttribute(ids, m_formatter.get()));
+    DDF dest = attr->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding ExtensibleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding ExtensibleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by DOMAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        DOMElement* e = (*v)->getDOM();
+        if (e) {
+            DDF converted = convert(e, false);
+            if (!converted.isnull())
+                dest.add(converted);
+        }
+        else
+            log.warn("skipping AttributeValue without a backing DOM");
+    }
+
+    return dest.integer() ? _decode(attr.release()) : NULL;
+}
+
+DDF DOMAttributeDecoder::convert(DOMElement* e, bool nameit) const
+{
+    const XMLCh* nsURI;
+    const XMLCh* local;
+    map<pair<xstring,xstring>,string>::const_iterator mapping;
+    DDF obj = DDF(NULL).structure();
+
+    if (nameit) {
+        // Name this structure.
+        nsURI = e->getNamespaceURI();
+        local = e->getLocalName();
+        mapping = m_tagMap.find(pair<xstring,xstring>(local,nsURI));
+        if (mapping == m_tagMap.end()) {
+            auto_ptr_char temp(local);
+            obj.name(temp.get());
+        }
+        else {
+            obj.name(mapping->second.c_str());
+        }
+    }
+
+    // Process non-xmlns attributes.
+    DOMNamedNodeMap* attrs = e->getAttributes();
+    for (XMLSize_t a = attrs->getLength(); a > 0; --a) {
+        DOMNode* attr = attrs->item(a-1);
+        nsURI = attr->getNamespaceURI();
+        if (XMLString::equals(nsURI, xmlconstants::XMLNS_NS))
+            continue;
+        local = attr->getLocalName();
+        mapping = m_tagMap.find(pair<xstring,xstring>(local, nsURI ? nsURI : &chNull));
+        if (mapping == m_tagMap.end()) {
+            auto_ptr_char temp(local);
+            obj.addmember(temp.get()).string(toUTF8(attr->getNodeValue(), true), false);
+        }
+        else {
+            obj.addmember(mapping->second.c_str()).string(toUTF8(attr->getNodeValue(), true), false);
+        }
+    }
+
+    DOMElement* child = XMLHelper::getFirstChildElement(e);
+    if (!child && e->hasChildNodes() && e->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE) {
+        // Attach a _text member if a text node is present.
+        obj.addmember("_string").string(toUTF8(e->getFirstChild()->getNodeValue(), true), false);
+    }
+    else {
+        while (child) {
+            // Convert the child element.
+            DDF converted = convert(child);
+            if (!converted.isnull()) {
+                // Now identify it and attach it.
+                if (obj[converted.name()].isnull()) {
+                    // We're a new child, so just attach as a structure member.
+                    obj.add(converted);
+                }
+                else if (obj[converted.name()].islist()) {
+                    // We're already a repeating child, so add it to the list.
+                    obj[converted.name()].add(converted);
+                }
+                else if (obj[converted.name()].isstruct()) {
+                    // This is the complex case where we see a child for the second
+                    // time and have to convert a structure member into a named list.
+                    DDF newlist = DDF(converted.name()).list();
+                    newlist.add(obj[converted.name()].remove());
+                    newlist.add(converted);
+                    obj.add(newlist);
+                }
+            }
+            child = XMLHelper::getNextSiblingElement(child);
+        }
+    }
+
+    // If we're empty, just delete.
+    if (obj.integer() == 0)
+        obj.destroy();
+    return obj;
+}
index 5602c55..cede806 100644 (file)
@@ -29,6 +29,61 @@ using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* ExtensibleAttributeFactory(DDF& in) {
+        return new ExtensibleAttribute(in);
+    }
+};
+
+ExtensibleAttribute::ExtensibleAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids)
+{
+    m_obj = Attribute::marshall();
+    m_obj.name("Extensible");
+    m_obj.addmember("_formatter").string(formatter);
+}
+
+ExtensibleAttribute::ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy())
+{
+}
+
+ExtensibleAttribute::~ExtensibleAttribute()
+{
+    m_obj.destroy();
+}
+
+DDF ExtensibleAttribute::getValues()
+{
+    return m_obj.first();
+}
+
+size_t ExtensibleAttribute::valueCount() const
+{
+    return m_obj.first().integer();
+}
+
+void ExtensibleAttribute::clearSerializedValues()
+{
+    m_serialized.clear();
+}
+
+const char* ExtensibleAttribute::getString(size_t index) const
+{
+    return m_obj.first()[static_cast<unsigned long>(index)].string();
+}
+
+const char* ExtensibleAttribute::getScope(size_t index) const
+{
+    return NULL;
+}
+
+void ExtensibleAttribute::removeValue(size_t index)
+{
+    Attribute::removeValue(index);
+    DDF vals = m_obj.first();
+    if (index < static_cast<size_t>(vals.integer()))
+        vals[static_cast<unsigned long>(index)].remove().destroy();
+}
+
 const vector<string>& ExtensibleAttribute::getSerializedValues() const
 {
     if (m_serialized.empty()) {
@@ -77,3 +132,12 @@ const vector<string>& ExtensibleAttribute::getSerializedValues() const
     }
     return Attribute::getSerializedValues();
 }
+
+DDF ExtensibleAttribute::marshall() const
+{
+    if (!isCaseSensitive())
+        m_obj.addmember("case_insensitive");
+    if (isInternal())
+        m_obj.addmember("internal");
+    return m_obj.copy();
+}
index 8a12836..1543288 100644 (file)
@@ -24,7 +24,6 @@
 #define __shibsp_extattr_h__
 
 #include <shibsp/attribute/Attribute.h>
-#include <xmltooling/exceptions.h>
 
 namespace shibsp {
 
@@ -45,65 +44,32 @@ namespace shibsp {
          * @param ids       array with primary identifier in first position, followed by any aliases
          * @param formatter template for serialization of values
          */
-        ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter) : Attribute(ids) {
-            m_obj = Attribute::marshall();
-            m_obj.name("Extensible");
-            m_obj.addmember("_formatter").string(formatter);
-        }
+        ExtensibleAttribute(const std::vector<std::string>& ids, const char* formatter);
 
         /**
          * Constructs based on a remoted ExtensibleAttribute.
          *
          * @param in    input object containing marshalled ExtensibleAttribute
          */
-        ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy()) {
-        }
+        ExtensibleAttribute(DDF& in);
 
-        virtual ~ExtensibleAttribute() {
-            m_obj.destroy();
-        }
+        virtual ~ExtensibleAttribute();
 
         /**
          * Returns the set of values in a DDF list.
          *
          * @return  a mutable list object containing the values
          */
-        DDF getValues() {
-            return m_obj.first();
-        }
-
-        size_t valueCount() const {
-            return m_obj.first().integer();
-        }
-
-        void clearSerializedValues() {
-            m_serialized.clear();
-        }
-
-        const char* getString(size_t index) const {
-            return m_obj.first()[static_cast<unsigned long>(index)].string();
-        }
-
-        const char* getScope(size_t index) const {
-            return NULL;
-        }
-
-        void removeValue(size_t index) {
-            Attribute::removeValue(index);
-            DDF vals = m_obj.first();
-            if (index < static_cast<size_t>(vals.integer()))
-                vals[static_cast<unsigned long>(index)].remove().destroy();
-        }
-
+        DDF getValues();
+
+        // Virtual function overrides.
+        size_t valueCount() const;
+        void clearSerializedValues();
+        const char* getString(size_t index) const;
+        const char* getScope(size_t index) const;
+        void removeValue(size_t index);
         const std::vector<std::string>& getSerializedValues() const;
-
-        DDF marshall() const {
-            if (!isCaseSensitive())
-                m_obj.addmember("case_insensitive");
-            if (isInternal())
-                m_obj.addmember("internal");
-            return m_obj.copy();
-        }
+        DDF marshall() const;
 
     private:
         mutable DDF m_obj;
index 3ab80f2..741d5da 100644 (file)
-/*\r
- *  Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * KeyInfoAttributeDecoder.cpp\r
- *\r
- * Decodes KeyInfo information into a SimpleAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/SimpleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/security/SecurityHelper.h>\r
-#include <xmltooling/signature/KeyInfo.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmlsignature;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        KeyInfoAttributeDecoder(const DOMElement* e);\r
-        ~KeyInfoAttributeDecoder() {\r
-            delete m_keyInfoResolver;\r
-        }\r
-\r
-        Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-\r
-    private:\r
-        void extract(const KeyInfo* k, vector<string>& dest) const {\r
-            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));\r
-            if (cred.get()) {\r
-                dest.push_back(string());\r
-                dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash);\r
-                if (dest.back().empty())\r
-                    dest.pop_back();\r
-            }\r
-        }\r
-\r
-        const KeyInfoResolver* getKeyInfoResolver() const {\r
-            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();\r
-        }\r
-\r
-        bool m_hash;\r
-        KeyInfoResolver* m_keyInfoResolver;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new KeyInfoAttributeDecoder(e);\r
-    }\r
-\r
-    static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);\r
-    static const XMLCh _hash[] =            UNICODE_LITERAL_4(h,a,s,h);\r
-    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
-};\r
-\r
-KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_hash(false), m_keyInfoResolver(NULL) {\r
-    const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;\r
-    m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
-    e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;\r
-    if (e) {\r
-        auto_ptr_char t(e->getAttributeNS(NULL, _type));\r
-        if (t.get() && *t.get())\r
-            m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);\r
-        else\r
-            throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");\r
-    }\r
-}\r
-\r
-Attribute* KeyInfoAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");\r
-\r
-    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
-        log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
-        return NULL;\r
-    }\r
-\r
-    auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));\r
-    vector<string>& dest = attr->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
-    if (saml2attr) {\r
-        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
-        v = values.begin();\r
-        stop = values.end();\r
-        if (log.isDebugEnabled()) {\r
-            auto_ptr_char n(saml2attr->getName());\r
-            log.debug(\r
-                "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
-                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                );\r
-        }\r
-    }\r
-    else {\r
-        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
-        if (saml1attr) {\r
-            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
-            v = values.begin();\r
-            stop = values.end();\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char n(saml1attr->getAttributeName());\r
-                log.debug(\r
-                    "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-            }\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    for (; v!=stop; ++v) {\r
-        const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);\r
-        if (k)\r
-            extract(k, dest);\r
-        else if ((*v)->hasChildren()) {\r
-            const list<XMLObject*>& children = (*v)->getOrderedChildren();\r
-            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {\r
-                if (k=dynamic_cast<const KeyInfo*>(*vv))\r
-                    extract(k, dest);\r
-                else\r
-                    log.warn("skipping AttributeValue without a recognizable KeyInfo");\r
-            }\r
-        }\r
-    }\r
-\r
-    return dest.empty() ? NULL : _decode(attr.release());\r
-}\r
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * KeyInfoAttributeDecoder.cpp
+ *
+ * Decodes KeyInfo information into a SimpleAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/Credential.h>
+#include <xmltooling/security/KeyInfoResolver.h>
+#include <xmltooling/security/SecurityHelper.h>
+#include <xmltooling/signature/KeyInfo.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmlsignature;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL KeyInfoAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        KeyInfoAttributeDecoder(const DOMElement* e);
+        ~KeyInfoAttributeDecoder() {
+            delete m_keyInfoResolver;
+        }
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        void extract(const KeyInfo* k, vector<string>& dest) const {
+            auto_ptr<Credential> cred (getKeyInfoResolver()->resolve(k, Credential::RESOLVE_KEYS));
+            if (cred.get()) {
+                const char* alg = m_keyInfoHashAlg.get();
+                if (!alg || !*alg)
+                    alg = "SHA1";
+                dest.push_back(string());
+                dest.back() = SecurityHelper::getDEREncoding(*cred.get(), m_hash ? alg : NULL);
+                if (dest.back().empty())
+                    dest.pop_back();
+            }
+        }
+
+        const KeyInfoResolver* getKeyInfoResolver() const {
+            return m_keyInfoResolver ? m_keyInfoResolver : XMLToolingConfig::getConfig().getKeyInfoResolver();
+        }
+
+        bool m_hash;
+        auto_ptr_char m_keyInfoHashAlg;
+        KeyInfoResolver* m_keyInfoResolver;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL KeyInfoAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new KeyInfoAttributeDecoder(e);
+    }
+
+    static const XMLCh _KeyInfoResolver[] = UNICODE_LITERAL_15(K,e,y,I,n,f,o,R,e,s,o,l,v,e,r);
+    static const XMLCh _hash[] =            UNICODE_LITERAL_4(h,a,s,h);
+    static const XMLCh keyInfoHashAlg[] =   UNICODE_LITERAL_14(k,e,y,I,n,f,o,H,a,s,h,A,l,g);
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
+};
+
+KeyInfoAttributeDecoder::KeyInfoAttributeDecoder(const DOMElement* e)
+        : AttributeDecoder(e),
+          m_hash(false),
+          m_keyInfoHashAlg(e ? e->getAttributeNS(NULL, keyInfoHashAlg) : NULL),
+          m_keyInfoResolver(NULL) {
+    const XMLCh* flag = e ? e->getAttributeNS(NULL, _hash) : NULL;
+    m_hash = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+    e = e ? XMLHelper::getFirstChildElement(e,_KeyInfoResolver) : NULL;
+    if (e) {
+        auto_ptr_char t(e->getAttributeNS(NULL, _type));
+        if (t.get() && *t.get())
+            m_keyInfoResolver = XMLToolingConfig::getConfig().KeyInfoResolverManager.newPlugin(t.get(), e);
+        else
+            throw UnknownExtensionException("<KeyInfoResolver> element found with no type attribute");
+    }
+}
+
+Attribute* KeyInfoAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.KeyInfo");
+
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+        return NULL;
+    }
+
+    auto_ptr<SimpleAttribute> attr(new SimpleAttribute(ids));
+    vector<string>& dest = attr->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding KeyInfo information (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding KeyInfo information (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by KeyInfoAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        const KeyInfo* k = dynamic_cast<const KeyInfo*>(*v);
+        if (k)
+            extract(k, dest);
+        else if ((*v)->hasChildren()) {
+            const list<XMLObject*>& children = (*v)->getOrderedChildren();
+            for (list<XMLObject*>::const_iterator vv = children.begin(); vv!=children.end(); ++vv) {
+                if (k=dynamic_cast<const KeyInfo*>(*vv))
+                    extract(k, dest);
+                else
+                    log.warn("skipping AttributeValue without a recognizable KeyInfo");
+            }
+        }
+    }
+
+    return dest.empty() ? NULL : _decode(attr.release());
+}
diff --git a/shibsp/attribute/NameIDAttribute.cpp b/shibsp/attribute/NameIDAttribute.cpp
new file mode 100644 (file)
index 0000000..978f78d
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * NameIDAttribute.cpp
+ *
+ * An Attribute whose values are derived from or mappable to a SAML NameID.
+ */
+
+#include "internal.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <xmltooling/exceptions.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* NameIDAttributeFactory(DDF& in) {
+        return new NameIDAttribute(in);
+    }
+};
+
+NameIDAttribute::NameIDAttribute(const vector<string>& ids, const char* formatter) : Attribute(ids), m_formatter(formatter)
+{
+}
+
+NameIDAttribute::NameIDAttribute(DDF& in) : Attribute(in)
+{
+    DDF val = in["_formatter"];
+    if (val.isstring())
+        m_formatter = val.string();
+    else
+        m_formatter = DEFAULT_NAMEID_FORMATTER;
+    const char* pch;
+    val = in.first().first();
+    while (val.name()) {
+        m_values.push_back(Value());
+        Value& v = m_values.back();
+        v.m_Name = val.name();
+        pch = val["Format"].string();
+        if (pch)
+            v.m_Format = pch;
+        pch = val["NameQualifier"].string();
+        if (pch)
+            v.m_NameQualifier = pch;
+        pch = val["SPNameQualifier"].string();
+        if (pch)
+            v.m_SPNameQualifier = pch;
+        pch = val["SPProvidedID"].string();
+        if (pch)
+            v.m_SPProvidedID = pch;
+        val = in.first().next();
+    }
+}
+
+NameIDAttribute::~NameIDAttribute()
+{
+}
+
+vector<NameIDAttribute::Value>& NameIDAttribute::getValues()
+{
+    return m_values;
+}
+
+const vector<NameIDAttribute::Value>& NameIDAttribute::getValues() const
+{
+    return m_values;
+}
+
+size_t NameIDAttribute::valueCount() const
+{
+    return m_values.size();
+}
+
+void NameIDAttribute::clearSerializedValues()
+{
+    m_serialized.clear();
+}
+
+const char* NameIDAttribute::getString(size_t index) const
+{
+    return m_values[index].m_Name.c_str();
+}
+
+const char* NameIDAttribute::getScope(size_t index) const
+{
+    return m_values[index].m_NameQualifier.c_str();
+}
+
+void NameIDAttribute::removeValue(size_t index)
+{
+    Attribute::removeValue(index);
+    if (index < m_values.size())
+        m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& NameIDAttribute::getSerializedValues() const
+{
+    if (m_serialized.empty()) {
+        for (vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+            // This is kind of a hack, but it's a good way to reuse some code.
+            XMLToolingException e(
+                m_formatter,
+                namedparams(
+                    5,
+                    "Name", i->m_Name.c_str(),
+                    "Format", i->m_Format.c_str(),
+                    "NameQualifier", i->m_NameQualifier.c_str(),
+                    "SPNameQualifier", i->m_SPNameQualifier.c_str(),
+                    "SPProvidedID", i->m_SPProvidedID.c_str()
+                    )
+                );
+            m_serialized.push_back(e.what());
+        }
+    }
+    return Attribute::getSerializedValues();
+}
+
+DDF NameIDAttribute::marshall() const
+{
+    DDF ddf = Attribute::marshall();
+    ddf.name("NameID");
+    ddf.addmember("_formatter").string(m_formatter.c_str());
+    DDF vlist = ddf.first();
+    for (vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+        DDF val = DDF(i->m_Name.c_str()).structure();
+        if (!i->m_Format.empty())
+            val.addmember("Format").string(i->m_Format.c_str());
+        if (!i->m_NameQualifier.empty())
+            val.addmember("NameQualifier").string(i->m_NameQualifier.c_str());
+        if (!i->m_SPNameQualifier.empty())
+            val.addmember("SPNameQualifier").string(i->m_SPNameQualifier.c_str());
+        if (!i->m_SPProvidedID.empty())
+            val.addmember("SPProvidedID").string(i->m_SPProvidedID.c_str());
+        vlist.add(val);
+    }
+    return ddf;
+}
index 1b8d247..8a0aa99 100644 (file)
@@ -24,7 +24,6 @@
 #define __shibsp_nameidattr_h__
 
 #include <shibsp/attribute/Attribute.h>
-#include <xmltooling/exceptions.h>
 
 namespace shibsp {
 
@@ -48,44 +47,16 @@ namespace shibsp {
          * @param ids       array with primary identifier in first position, followed by any aliases
          * @param formatter template for serialization of tuple
          */
-        NameIDAttribute(const std::vector<std::string>& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER)
-            : Attribute(ids), m_formatter(formatter) {
-        }
+        NameIDAttribute(const std::vector<std::string>& ids, const char* formatter=DEFAULT_NAMEID_FORMATTER);
 
         /**
          * Constructs based on a remoted NameIDAttribute.
          * 
          * @param in    input object containing marshalled NameIDAttribute
          */
-        NameIDAttribute(DDF& in) : Attribute(in) {
-            DDF val = in["_formatter"];
-            if (val.isstring())
-                m_formatter = val.string();
-            else
-                m_formatter = DEFAULT_NAMEID_FORMATTER;
-            const char* pch;
-            val = in.first().first();
-            while (val.name()) {
-                m_values.push_back(Value());
-                Value& v = m_values.back();
-                v.m_Name = val.name();
-                pch = val["Format"].string();
-                if (pch)
-                    v.m_Format = pch;
-                pch = val["NameQualifier"].string();
-                if (pch)
-                    v.m_NameQualifier = pch;
-                pch = val["SPNameQualifier"].string();
-                if (pch)
-                    v.m_SPNameQualifier = pch;
-                pch = val["SPProvidedID"].string();
-                if (pch)
-                    v.m_SPProvidedID = pch;
-                val = in.first().next();
-            }
-        }
+        NameIDAttribute(DDF& in);
         
-        virtual ~NameIDAttribute() {}
+        virtual ~NameIDAttribute();
         
         /**
          * Holds all the fields associated with a NameID.
@@ -104,81 +75,23 @@ namespace shibsp {
          * 
          * @return  a mutable vector of the values
          */
-        std::vector<Value>& getValues() {
-            return m_values;
-        }
+        std::vector<Value>& getValues();
 
         /**
          * Returns the set of values encoded as UTF-8 strings.
          * 
          * @return  an immutable vector of the values
          */
-        const std::vector<Value>& getValues() const {
-            return m_values;
-        }
-
-        size_t valueCount() const {
-            return m_values.size();
-        }
-        
-        void clearSerializedValues() {
-            m_serialized.clear();
-        }
-
-        const char* getString(size_t index) const {
-            return m_values[index].m_Name.c_str();
-        }
-
-        const char* getScope(size_t index) const {
-            return m_values[index].m_NameQualifier.c_str();
-        }
-
-        void removeValue(size_t index) {
-            Attribute::removeValue(index);
-            if (index < m_values.size())
-                m_values.erase(m_values.begin() + index);
-        }
-
-        const std::vector<std::string>& getSerializedValues() const {
-            if (m_serialized.empty()) {
-                for (std::vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
-                    // This is kind of a hack, but it's a good way to reuse some code.
-                    xmltooling::XMLToolingException e(
-                        m_formatter,
-                        xmltooling::namedparams(
-                            5,
-                            "Name", i->m_Name.c_str(),
-                            "Format", i->m_Format.c_str(),
-                            "NameQualifier", i->m_NameQualifier.c_str(),
-                            "SPNameQualifier", i->m_SPNameQualifier.c_str(),
-                            "SPProvidedID", i->m_SPProvidedID.c_str()
-                            )
-                        );
-                    m_serialized.push_back(e.what());
-                }
-            }
-            return Attribute::getSerializedValues();
-        }
-    
-        DDF marshall() const {
-            DDF ddf = Attribute::marshall();
-            ddf.name("NameID");
-            ddf.addmember("_formatter").string(m_formatter.c_str());
-            DDF vlist = ddf.first();
-            for (std::vector<Value>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
-                DDF val = DDF(i->m_Name.c_str()).structure();
-                if (!i->m_Format.empty())
-                    val.addmember("Format").string(i->m_Format.c_str());
-                if (!i->m_NameQualifier.empty())
-                    val.addmember("NameQualifier").string(i->m_NameQualifier.c_str());
-                if (!i->m_SPNameQualifier.empty())
-                    val.addmember("SPNameQualifier").string(i->m_SPNameQualifier.c_str());
-                if (!i->m_SPProvidedID.empty())
-                    val.addmember("SPProvidedID").string(i->m_SPProvidedID.c_str());
-                vlist.add(val);
-            }
-            return ddf;
-        }
+        const std::vector<Value>& getValues() const;
+
+        // Virtual function overrides.
+        size_t valueCount() const;
+        void clearSerializedValues();
+        const char* getString(size_t index) const;
+        const char* getScope(size_t index) const;
+        void removeValue(size_t index);
+        const std::vector<std::string>& getSerializedValues() const;
+        DDF marshall() const;
     
     private:
         std::vector<Value> m_values;
index 903bc33..82ff313 100644 (file)
-/*\r
- *  Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * NameIDAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into NameIDAttributes\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/NameIDAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);\r
-    static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);\r
-\r
-    class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        NameIDAttributeDecoder(const DOMElement* e)\r
-                : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {\r
-            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;\r
-            if (flag && (*flag == chLatin_t || *flag == chDigit_1))\r
-                m_defaultQualifiers = true;\r
-        }\r
-        ~NameIDAttributeDecoder() {}\r
-\r
-        shibsp::Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-\r
-    private:\r
-        void extract(\r
-            const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-            ) const;\r
-        void extract(\r
-            const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-            ) const;\r
-        auto_ptr_char m_formatter;\r
-        bool m_defaultQualifiers;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new NameIDAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-shibsp::Attribute* NameIDAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    auto_ptr<NameIDAttribute> nameid(\r
-        new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)\r
-        );\r
-    vector<NameIDAttribute::Value>& dest = nameid->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");\r
-\r
-    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
-        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
-        if (saml2attr) {\r
-            const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
-            v = values.begin();\r
-            stop = values.end();\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char n(saml2attr->getName());\r
-                log.debug(\r
-                    "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-            }\r
-        }\r
-        else {\r
-            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
-            if (saml1attr) {\r
-                const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
-                v = values.begin();\r
-                stop = values.end();\r
-                if (log.isDebugEnabled()) {\r
-                    auto_ptr_char n(saml1attr->getAttributeName());\r
-                    log.debug(\r
-                        "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
-                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                        );\r
-                }\r
-            }\r
-            else {\r
-                log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");\r
-                return NULL;\r
-            }\r
-        }\r
-\r
-        for (; v!=stop; ++v) {\r
-            const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);\r
-            if (n2)\r
-                extract(n2, dest, assertingParty, relyingParty);\r
-            else {\r
-                const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);\r
-                if (n1)\r
-                    extract(n1, dest, assertingParty, relyingParty);\r
-                else if ((*v)->hasChildren()) {\r
-                    const list<XMLObject*>& values = (*v)->getOrderedChildren();\r
-                    for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {\r
-                        if (n2=dynamic_cast<const NameIDType*>(*vv))\r
-                            extract(n2, dest, assertingParty, relyingParty);\r
-                        else if (n1=dynamic_cast<const NameIdentifier*>(*vv))\r
-                            extract(n1, dest, assertingParty, relyingParty);\r
-                        else\r
-                            log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return dest.empty() ? NULL : _decode(nameid.release());\r
-    }\r
-\r
-    const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);\r
-    if (saml2name) {\r
-        if (log.isDebugEnabled()) {\r
-            auto_ptr_char f(saml2name->getFormat());\r
-            log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
-        }\r
-        extract(saml2name, dest, assertingParty, relyingParty);\r
-    }\r
-    else {\r
-        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
-        if (saml1name) {\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char f(saml1name->getFormat());\r
-                log.debug(\r
-                    "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
-                    ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
-                    );\r
-            }\r
-            extract(saml1name, dest, assertingParty, relyingParty);\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    return dest.empty() ? NULL : _decode(nameid.release());\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
-    const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    auto_arrayptr<char> name(toUTF8(n->getName()));\r
-    if (name.get() && *name.get()) {\r
-        dest.push_back(NameIDAttribute::Value());\r
-        NameIDAttribute::Value& val = dest.back();\r
-        val.m_Name = name.get();\r
-        char* str = toUTF8(n->getFormat());\r
-        if (str) {\r
-            val.m_Format = str;\r
-            delete[] str;\r
-        }\r
-\r
-        str = toUTF8(n->getNameQualifier());\r
-        if (str && *str)\r
-            val.m_NameQualifier = str;\r
-        else if (m_defaultQualifiers && assertingParty)\r
-            val.m_NameQualifier = assertingParty;\r
-        delete[] str;\r
-\r
-        str = toUTF8(n->getSPNameQualifier());\r
-        if (str && *str)\r
-            val.m_SPNameQualifier = str;\r
-        else if (m_defaultQualifiers && relyingParty)\r
-            val.m_SPNameQualifier = relyingParty;\r
-        delete[] str;\r
-\r
-        str = toUTF8(n->getSPProvidedID());\r
-        if (str) {\r
-            val.m_SPProvidedID = str;\r
-            delete[] str;\r
-        }\r
-    }\r
-}\r
-\r
-void NameIDAttributeDecoder::extract(\r
-    const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    auto_arrayptr<char> name(toUTF8(n->getName()));\r
-    if (name.get() && *name.get()) {\r
-        dest.push_back(NameIDAttribute::Value());\r
-        NameIDAttribute::Value& val = dest.back();\r
-        val.m_Name = name.get();\r
-        char* str = toUTF8(n->getFormat());\r
-        if (str) {\r
-            val.m_Format = str;\r
-            delete[] str;\r
-        }\r
-\r
-        str = toUTF8(n->getNameQualifier());\r
-        if (str && *str)\r
-            val.m_NameQualifier = str;\r
-        else if (m_defaultQualifiers && assertingParty)\r
-            val.m_NameQualifier = assertingParty;\r
-        delete[] str;\r
-\r
-        if (m_defaultQualifiers && relyingParty)\r
-            val.m_SPNameQualifier = relyingParty;\r
-    }\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * NameIDAttributeDecoder.cpp
+ *
+ * Decodes SAML into NameIDAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/NameIDAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    static const XMLCh formatter[] = UNICODE_LITERAL_9(f,o,r,m,a,t,t,e,r);
+    static const XMLCh defaultQualifiers[] = UNICODE_LITERAL_17(d,e,f,a,u,l,t,Q,u,a,l,i,f,i,e,r,s);
+
+    class SHIBSP_DLLLOCAL NameIDAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        NameIDAttributeDecoder(const DOMElement* e)
+                : AttributeDecoder(e), m_formatter(e ? e->getAttributeNS(NULL, formatter) : NULL), m_defaultQualifiers(false) {
+            const XMLCh* flag = e ? e->getAttributeNS(NULL, defaultQualifiers) : NULL;
+            if (flag && (*flag == chLatin_t || *flag == chDigit_1))
+                m_defaultQualifiers = true;
+        }
+        ~NameIDAttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        void extract(
+            const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+            ) const;
+        void extract(
+            const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+            ) const;
+        auto_ptr_char m_formatter;
+        bool m_defaultQualifiers;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL NameIDAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new NameIDAttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* NameIDAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_ptr<NameIDAttribute> nameid(
+        new NameIDAttribute(ids, (m_formatter.get() && *m_formatter.get()) ? m_formatter.get() : DEFAULT_NAMEID_FORMATTER)
+        );
+    vector<NameIDAttribute::Value>& dest = nameid->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.NameID");
+
+    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+        if (saml2attr) {
+            const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml2attr->getName());
+                log.debug(
+                    "decoding NameIDAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+            if (saml1attr) {
+                const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+                v = values.begin();
+                stop = values.end();
+                if (log.isDebugEnabled()) {
+                    auto_ptr_char n(saml1attr->getAttributeName());
+                    log.debug(
+                        "decoding NameIDAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                        ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                        );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+                return NULL;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            const NameIDType* n2 = dynamic_cast<const NameIDType*>(*v);
+            if (n2)
+                extract(n2, dest, assertingParty, relyingParty);
+            else {
+                const NameIdentifier* n1=dynamic_cast<const NameIdentifier*>(*v);
+                if (n1)
+                    extract(n1, dest, assertingParty, relyingParty);
+                else if ((*v)->hasChildren()) {
+                    const list<XMLObject*>& values = (*v)->getOrderedChildren();
+                    for (list<XMLObject*>::const_iterator vv = values.begin(); vv!=values.end(); ++vv) {
+                        if (n2=dynamic_cast<const NameIDType*>(*vv))
+                            extract(n2, dest, assertingParty, relyingParty);
+                        else if (n1=dynamic_cast<const NameIdentifier*>(*vv))
+                            extract(n1, dest, assertingParty, relyingParty);
+                        else
+                            log.warn("skipping AttributeValue without a recognizable NameID/NameIdentifier");
+                    }
+                }
+            }
+        }
+
+        return dest.empty() ? NULL : _decode(nameid.release());
+    }
+
+    const NameIDType* saml2name = dynamic_cast<const NameIDType*>(xmlObject);
+    if (saml2name) {
+        if (log.isDebugEnabled()) {
+            auto_ptr_char f(saml2name->getFormat());
+            log.debug("decoding NameIDAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+        }
+        extract(saml2name, dest, assertingParty, relyingParty);
+    }
+    else {
+        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+        if (saml1name) {
+            if (log.isDebugEnabled()) {
+                auto_ptr_char f(saml1name->getFormat());
+                log.debug(
+                    "decoding NameIDAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"
+                    );
+            }
+            extract(saml1name, dest, assertingParty, relyingParty);
+        }
+        else {
+            log.warn("XMLObject type not recognized by NameIDAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    return dest.empty() ? NULL : _decode(nameid.release());
+}
+
+void NameIDAttributeDecoder::extract(
+    const NameIDType* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_arrayptr<char> name(toUTF8(n->getName()));
+    if (name.get() && *name.get()) {
+        dest.push_back(NameIDAttribute::Value());
+        NameIDAttribute::Value& val = dest.back();
+        val.m_Name = name.get();
+        char* str = toUTF8(n->getFormat());
+        if (str) {
+            val.m_Format = str;
+            delete[] str;
+        }
+
+        str = toUTF8(n->getNameQualifier());
+        if (str && *str)
+            val.m_NameQualifier = str;
+        else if (m_defaultQualifiers && assertingParty)
+            val.m_NameQualifier = assertingParty;
+        delete[] str;
+
+        str = toUTF8(n->getSPNameQualifier());
+        if (str && *str)
+            val.m_SPNameQualifier = str;
+        else if (m_defaultQualifiers && relyingParty)
+            val.m_SPNameQualifier = relyingParty;
+        delete[] str;
+
+        str = toUTF8(n->getSPProvidedID());
+        if (str) {
+            val.m_SPProvidedID = str;
+            delete[] str;
+        }
+    }
+}
+
+void NameIDAttributeDecoder::extract(
+    const NameIdentifier* n, vector<NameIDAttribute::Value>& dest, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    auto_arrayptr<char> name(toUTF8(n->getName()));
+    if (name.get() && *name.get()) {
+        dest.push_back(NameIDAttribute::Value());
+        NameIDAttribute::Value& val = dest.back();
+        val.m_Name = name.get();
+        char* str = toUTF8(n->getFormat());
+        if (str) {
+            val.m_Format = str;
+            delete[] str;
+        }
+
+        str = toUTF8(n->getNameQualifier());
+        if (str && *str)
+            val.m_NameQualifier = str;
+        else if (m_defaultQualifiers && assertingParty)
+            val.m_NameQualifier = assertingParty;
+        delete[] str;
+
+        if (m_defaultQualifiers && relyingParty)
+            val.m_SPNameQualifier = relyingParty;
+    }
+}
diff --git a/shibsp/attribute/ScopedAttribute.cpp b/shibsp/attribute/ScopedAttribute.cpp
new file mode 100644 (file)
index 0000000..567d8cf
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * ScopedAttribute.cpp
+ *
+ * An Attribute whose values are relations of a value and a scope.
+ */
+
+#include "internal.h"
+#include "attribute/ScopedAttribute.h"
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* ScopedAttributeFactory(DDF& in) {
+        return new ScopedAttribute(in);
+    }
+};
+
+ScopedAttribute::ScopedAttribute(const vector<string>& ids, char delimeter) : Attribute(ids), m_delimeter(delimeter)
+{
+}
+
+ScopedAttribute::ScopedAttribute(DDF& in) : Attribute(in), m_delimeter('@')
+{
+    DDF val = in["_delimeter"];
+    if (val.isint())
+        m_delimeter = static_cast<char>(val.integer());
+    val = in.first().first();
+    while (val.name() && val.string()) {
+        m_values.push_back(make_pair(string(val.name()), string(val.string())));
+        val = in.first().next();
+    }
+}
+
+ScopedAttribute::~ScopedAttribute()
+{
+}
+
+vector< pair<string,string> >& ScopedAttribute::getValues()
+{
+    return m_values;
+}
+
+const vector< pair<string,string> >& ScopedAttribute::getValues() const
+{
+    return m_values;
+}
+
+size_t ScopedAttribute::valueCount() const
+{
+    return m_values.size();
+}
+
+void ScopedAttribute::clearSerializedValues()
+{
+    m_serialized.clear();
+}
+
+const char* ScopedAttribute::getString(size_t index) const
+{
+    return m_values[index].first.c_str();
+}
+
+const char* ScopedAttribute::getScope(size_t index) const
+{
+    return m_values[index].second.c_str();
+}
+
+void ScopedAttribute::removeValue(size_t index)
+{
+    Attribute::removeValue(index);
+    if (index < m_values.size())
+        m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& ScopedAttribute::getSerializedValues() const
+{
+    if (m_serialized.empty()) {
+        for (vector< pair<string,string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+            m_serialized.push_back(i->first + m_delimeter + i->second);
+    }
+    return Attribute::getSerializedValues();
+}
+
+DDF ScopedAttribute::marshall() const
+{
+    DDF ddf = Attribute::marshall();
+    ddf.name("Scoped");
+    if (m_delimeter != '@')
+        ddf.addmember("_delimeter").integer(m_delimeter);
+    DDF vlist = ddf.first();
+    for (vector< pair<string,string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+        DDF val = DDF(i->first.c_str()).string(i->second.c_str());
+        vlist.add(val);
+    }
+    return ddf;
+}
index a8acac5..808d6f3 100644 (file)
@@ -51,27 +51,16 @@ namespace shibsp {
          * @param ids   array with primary identifier in first position, followed by any aliases
          * @param delimeter value/scope delimeter when serializing
          */
-        ScopedAttribute(const std::vector<std::string>& ids, char delimeter='@')
-            : Attribute(ids), m_delimeter(delimeter) {
-        }
+        ScopedAttribute(const std::vector<std::string>& ids, char delimeter='@');
 
         /**
          * Constructs based on a remoted ScopedAttribute.
          * 
          * @param in    input object containing marshalled ScopedAttribute
          */
-        ScopedAttribute(DDF& in) : Attribute(in), m_delimeter('@') {
-            DDF val = in["_delimeter"];
-            if (val.isint())
-                m_delimeter = static_cast<char>(val.integer());
-            val = in.first().first();
-            while (val.name() && val.string()) {
-                m_values.push_back(std::make_pair(std::string(val.name()), std::string(val.string())));
-                val = in.first().next();
-            }
-        }
+        ScopedAttribute(DDF& in);
         
-        virtual ~ScopedAttribute() {}
+        virtual ~ScopedAttribute();
 
         /**
          * Returns the set of values encoded as UTF-8 strings.
@@ -80,9 +69,7 @@ namespace shibsp {
          * 
          * @return  a mutable vector of the values
          */
-        std::vector< std::pair<std::string,std::string> >& getValues() {
-            return m_values;
-        }
+        std::vector< std::pair<std::string,std::string> >& getValues();
 
         /**
          * Returns the set of values encoded as UTF-8 strings.
@@ -91,52 +78,16 @@ namespace shibsp {
          * 
          * @return  an immutable vector of the values
          */
-        const std::vector< std::pair<std::string,std::string> >& getValues() const {
-            return m_values;
-        }
-
-        size_t valueCount() const {
-            return m_values.size();
-        }
-        
-        void clearSerializedValues() {
-            m_serialized.clear();
-        }
-        
-        const char* getString(size_t index) const {
-            return m_values[index].first.c_str();
-        }
-
-        const char* getScope(size_t index) const {
-            return m_values[index].second.c_str();
-        }
-
-        void removeValue(size_t index) {
-            Attribute::removeValue(index);
-            if (index < m_values.size())
-                m_values.erase(m_values.begin() + index);
-        }
-
-        const std::vector<std::string>& getSerializedValues() const {
-            if (m_serialized.empty()) {
-                for (std::vector< std::pair<std::string,std::string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
-                    m_serialized.push_back(i->first + m_delimeter + i->second);
-            }
-            return Attribute::getSerializedValues();
-        }
-
-        DDF marshall() const {
-            DDF ddf = Attribute::marshall();
-            ddf.name("Scoped");
-            if (m_delimeter != '@')
-                ddf.addmember("_delimeter").integer(m_delimeter);
-            DDF vlist = ddf.first();
-            for (std::vector< std::pair<std::string,std::string> >::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
-                DDF val = DDF(i->first.c_str()).string(i->second.c_str());
-                vlist.add(val);
-            }
-            return ddf;
-        }
+        const std::vector< std::pair<std::string,std::string> >& getValues() const;
+
+        // Virtual function overrides.
+        size_t valueCount() const;
+        void clearSerializedValues();
+        const char* getString(size_t index) const;
+        const char* getScope(size_t index) const;
+        void removeValue(size_t index);
+        const std::vector<std::string>& getSerializedValues() const;
+        DDF marshall() const;
     
     private:
         char m_delimeter;
index c3054c8..424ee7c 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * ScopedAttributeDecoder.cpp
  *
- * Decodes SAML into ScopedAttributes
+ * Decodes SAML into ScopedAttributes.
  */
 
 #include "internal.h"
@@ -35,15 +35,15 @@ using namespace std;
 
 namespace shibsp {
     static const XMLCh Scope[] =            UNICODE_LITERAL_5(S,c,o,p,e);
-    static const XMLCh scopeDelimeter[] =   UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,e,t,e,r);
+    static const XMLCh scopeDelimiter[] =   UNICODE_LITERAL_14(s,c,o,p,e,D,e,l,i,m,i,t,e,r);
 
     class SHIBSP_DLLLOCAL ScopedAttributeDecoder : virtual public AttributeDecoder
     {
     public:
-        ScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimeter('@') {
-            if (e && e->hasAttributeNS(NULL,scopeDelimeter)) {
-                auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimeter));
-                m_delimeter = *(d.get());
+        ScopedAttributeDecoder(const DOMElement* e) : AttributeDecoder(e), m_delimiter('@') {
+            if (e && e->hasAttributeNS(NULL,scopeDelimiter)) {
+                auto_ptr_char d(e->getAttributeNS(NULL,scopeDelimiter));
+                m_delimiter = *(d.get());
             }
         }
         ~ScopedAttributeDecoder() {}
@@ -53,7 +53,7 @@ namespace shibsp {
             ) const;
 
     private:
-        char m_delimeter;
+        char m_delimiter;
     };
 
     AttributeDecoder* SHIBSP_DLLLOCAL ScopedAttributeDecoderFactory(const DOMElement* const & e)
@@ -70,7 +70,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
     char* scope;
     const XMLCh* xmlscope;
     xmltooling::QName scopeqname(NULL,Scope);
-    auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimeter));
+    auto_ptr<ScopedAttribute> scoped(new ScopedAttribute(ids, m_delimiter));
     vector< pair<string,string> >& dest = scoped->getValues();
     vector<XMLObject*>::const_iterator v,stop;
 
@@ -122,7 +122,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
                         delete[] scope;
                     }
                     else {
-                        scope = strchr(val, m_delimeter);
+                        scope = strchr(val, m_delimiter);
                         if (scope) {
                             *scope++ = 0;
                             if (*scope)
@@ -174,8 +174,8 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
         }
     }
 
-    if (val && *val && *val!=m_delimeter) {
-        scope = strchr(val, m_delimeter);
+    if (val && *val && *val!=m_delimiter) {
+        scope = strchr(val, m_delimiter);
         if (scope) {
             *scope++ = 0;
             if (*scope)
@@ -184,7 +184,7 @@ shibsp::Attribute* ScopedAttributeDecoder::decode(
                 log.warn("ignoring NameID with no scope");
         }
         else {
-            log.warn("ignoring NameID with no scope delimiter (%c)", m_delimeter);
+            log.warn("ignoring NameID with no scope delimiter (%c)", m_delimiter);
         }
     }
     else {
diff --git a/shibsp/attribute/SimpleAttribute.cpp b/shibsp/attribute/SimpleAttribute.cpp
new file mode 100644 (file)
index 0000000..11af5c8
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * SimpleAttribute.cpp
+ *
+ * An Attribute whose values are simple strings.
+ */
+
+#include "internal.h"
+#include "attribute/SimpleAttribute.h"
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* SimpleAttributeFactory(DDF& in) {
+        return new SimpleAttribute(in);
+    }
+};
+
+SimpleAttribute::SimpleAttribute(const vector<string>& ids) : Attribute(ids)
+{
+}
+
+SimpleAttribute::SimpleAttribute(DDF& in) : Attribute(in)
+{
+    DDF val = in.first().first();
+    while (val.string()) {
+        m_serialized.push_back(val.string());
+        val = in.first().next();
+    }
+}
+
+SimpleAttribute::~SimpleAttribute()
+{
+}
+
+vector<string>& SimpleAttribute::getValues()
+{
+    return m_serialized;
+}
+
+void SimpleAttribute::clearSerializedValues()
+{
+    // Do nothing, since our values are already serialized.
+}
+
+DDF SimpleAttribute::marshall() const
+{
+    DDF ddf = Attribute::marshall();
+    DDF vlist = ddf.first();
+    for (vector<string>::const_iterator i=m_serialized.begin(); i!=m_serialized.end(); ++i)
+        vlist.add(DDF(NULL).string(i->c_str()));
+    return ddf;
+}
index 39f869c..8402159 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,22 +38,16 @@ namespace shibsp {
          * 
          * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        SimpleAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
+        SimpleAttribute(const std::vector<std::string>& ids);
 
         /**
          * Constructs based on a remoted SimpleAttribute.
          * 
          * @param in    input object containing marshalled SimpleAttribute
          */
-        SimpleAttribute(DDF& in) : Attribute(in) {
-            DDF val = in.first().first();
-            while (val.string()) {
-                m_serialized.push_back(val.string());
-                val = in.first().next();
-            }
-        }
+        SimpleAttribute(DDF& in);
         
-        virtual ~SimpleAttribute() {}
+        virtual ~SimpleAttribute();
 
         /**
          * Returns the set of values encoded as UTF-8 strings.
@@ -63,21 +57,11 @@ namespace shibsp {
          * 
          * @return  a mutable vector of the values
          */
-        std::vector<std::string>& getValues() {
-            return m_serialized;
-        }
+        std::vector<std::string>& getValues();
         
-        void clearSerializedValues() {
-            // Do nothing, since our values are already serialized.
-        }
-        
-        DDF marshall() const {
-            DDF ddf = Attribute::marshall();
-            DDF vlist = ddf.first();
-            for (std::vector<std::string>::const_iterator i=m_serialized.begin(); i!=m_serialized.end(); ++i)
-                vlist.add(DDF(NULL).string(i->c_str()));
-            return ddf;
-        }
+        // Virtual function overrides.
+        void clearSerializedValues();
+        DDF marshall() const;
     };
 
 };
index f2a9d6f..c19fc6b 100644 (file)
-/*\r
- *  Copyright 2001-2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * StringAttributeDecoder.cpp\r
- *\r
- * Decodes SAML into SimpleAttributes\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/SimpleAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml1;\r
-using namespace opensaml::saml2;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
-        ~StringAttributeDecoder() {}\r
-\r
-        shibsp::Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new StringAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-shibsp::Attribute* StringAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    char* val;\r
-    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));\r
-    vector<string>& dest = simple->getValues();\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");\r
-\r
-    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {\r
-        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);\r
-        if (saml2attr) {\r
-            const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
-            v = values.begin();\r
-            stop = values.end();\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char n(saml2attr->getName());\r
-                log.debug(\r
-                    "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-            }\r
-        }\r
-        else {\r
-            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);\r
-            if (saml1attr) {\r
-                const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
-                v = values.begin();\r
-                stop = values.end();\r
-                if (log.isDebugEnabled()) {\r
-                    auto_ptr_char n(saml1attr->getAttributeName());\r
-                log.debug(\r
-                    "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-                }\r
-            }\r
-            else {\r
-                log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
-                return NULL;\r
-            }\r
-        }\r
-\r
-        for (; v!=stop; ++v) {\r
-            if (!(*v)->hasChildren()) {\r
-                val = toUTF8((*v)->getTextContent());\r
-                if (val && *val)\r
-                    dest.push_back(val);\r
-                else\r
-                    log.warn("skipping empty AttributeValue");\r
-                delete[] val;\r
-            }\r
-            else {\r
-                log.warn("skipping complex AttributeValue");\r
-            }\r
-        }\r
-\r
-        return dest.empty() ? NULL : _decode(simple.release());\r
-    }\r
-\r
-    const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);\r
-    if (saml2name) {\r
-        if (log.isDebugEnabled()) {\r
-            auto_ptr_char f(saml2name->getFormat());\r
-            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");\r
-        }\r
-        val = toUTF8(saml2name->getName());\r
-    }\r
-    else {\r
-        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);\r
-        if (saml1name) {\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char f(saml1name->getFormat());\r
-                log.debug(\r
-                    "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",\r
-                    ids.front().c_str(), f.get() ? f.get() : "unspecified"\r
-                    );\r
-            }\r
-            val = toUTF8(saml1name->getName());\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    if (val && *val)\r
-        dest.push_back(val);\r
-    else\r
-        log.warn("ignoring empty NameID");\r
-    delete[] val;\r
-    return dest.empty() ? NULL : _decode(simple.release());\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * StringAttributeDecoder.cpp
+ *
+ * Decodes SAML into SimpleAttributes
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/SimpleAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+
+using namespace shibsp;
+using namespace opensaml::saml1;
+using namespace opensaml::saml2;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL StringAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        StringAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+        ~StringAttributeDecoder() {}
+
+        shibsp::Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL StringAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new StringAttributeDecoder(e);
+    }
+};
+
+shibsp::Attribute* StringAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    char* val;
+    auto_ptr<SimpleAttribute> simple(new SimpleAttribute(ids));
+    vector<string>& dest = simple->getValues();
+    vector<XMLObject*>::const_iterator v,stop;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.String");
+
+    if (xmlObject && XMLString::equals(opensaml::saml1::Attribute::LOCAL_NAME,xmlObject->getElementQName().getLocalPart())) {
+        const opensaml::saml2::Attribute* saml2attr = dynamic_cast<const opensaml::saml2::Attribute*>(xmlObject);
+        if (saml2attr) {
+            const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml2attr->getName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            const opensaml::saml1::Attribute* saml1attr = dynamic_cast<const opensaml::saml1::Attribute*>(xmlObject);
+            if (saml1attr) {
+                const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+                v = values.begin();
+                stop = values.end();
+                if (log.isDebugEnabled()) {
+                    auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+                }
+            }
+            else {
+                log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+                return NULL;
+            }
+        }
+
+        for (; v!=stop; ++v) {
+            if (!(*v)->hasChildren()) {
+                val = toUTF8((*v)->getTextContent());
+                if (val && *val)
+                    dest.push_back(val);
+                else
+                    log.warn("skipping empty AttributeValue");
+                delete[] val;
+            }
+            else {
+                log.warn("skipping complex AttributeValue");
+            }
+        }
+
+        return dest.empty() ? NULL : _decode(simple.release());
+    }
+
+    const NameID* saml2name = dynamic_cast<const NameID*>(xmlObject);
+    if (saml2name) {
+        if (log.isDebugEnabled()) {
+            auto_ptr_char f(saml2name->getFormat());
+            log.debug("decoding SimpleAttribute (%s) from SAML 2 NameID with Format (%s)", ids.front().c_str(), f.get() ? f.get() : "unspecified");
+        }
+        val = toUTF8(saml2name->getName());
+    }
+    else {
+        const NameIdentifier* saml1name = dynamic_cast<const NameIdentifier*>(xmlObject);
+        if (saml1name) {
+            if (log.isDebugEnabled()) {
+                auto_ptr_char f(saml1name->getFormat());
+                log.debug(
+                    "decoding SimpleAttribute (%s) from SAML 1 NameIdentifier with Format (%s)",
+                    ids.front().c_str(), f.get() ? f.get() : "unspecified"
+                    );
+            }
+            val = toUTF8(saml1name->getName());
+        }
+        else {
+            log.warn("XMLObject type not recognized by StringAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    if (val && *val)
+        dest.push_back(val);
+    else
+        log.warn("ignoring empty NameID");
+    delete[] val;
+    return dest.empty() ? NULL : _decode(simple.release());
+}
diff --git a/shibsp/attribute/XMLAttribute.cpp b/shibsp/attribute/XMLAttribute.cpp
new file mode 100644 (file)
index 0000000..38bc13d
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * XMLAttribute.cpp
+ *
+ * An Attribute whose values are serialized XML.
+ */
+
+#include "internal.h"
+#include "attribute/XMLAttribute.h"
+
+#include <xercesc/util/Base64.hpp>
+
+#ifndef SHIBSP_LITE
+# include <xsec/framework/XSECDefs.hpp>
+#endif
+
+using namespace shibsp;
+using namespace std;
+
+namespace shibsp {
+    SHIBSP_DLLLOCAL Attribute* XMLAttributeFactory(DDF& in) {
+        return new XMLAttribute(in);
+    }
+};
+
+XMLAttribute::XMLAttribute(const vector<string>& ids) : Attribute(ids)
+{
+}
+
+XMLAttribute::XMLAttribute(DDF& in) : Attribute(in)
+{
+    DDF val = in.first().first();
+    while (val.string()) {
+        m_values.push_back(val.string());
+        val = in.first().next();
+    }
+}
+
+XMLAttribute::~XMLAttribute()
+{
+}
+
+vector<string>& XMLAttribute::getValues()
+{
+    return m_values;
+}
+
+const vector<string>& XMLAttribute::getValues() const
+{
+    return m_values;
+}
+
+size_t XMLAttribute::valueCount() const
+{
+    return m_values.size();
+}
+
+void XMLAttribute::clearSerializedValues()
+{
+    m_serialized.clear();
+}
+
+const char* XMLAttribute::getString(size_t index) const
+{
+    return m_values[index].c_str();
+}
+
+void XMLAttribute::removeValue(size_t index)
+{
+    Attribute::removeValue(index);
+    if (index < m_values.size())
+        m_values.erase(m_values.begin() + index);
+}
+
+const vector<string>& XMLAttribute::getSerializedValues() const
+{
+    xsecsize_t len;
+    XMLByte *pos, *pos2;
+    if (m_serialized.empty()) {
+        for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i) {
+            XMLByte* enc = Base64::encode(reinterpret_cast<const XMLByte*>(i->data()), i->size(), &len);
+            if (enc) {
+                for (pos=enc, pos2=enc; *pos2; pos2++)
+                    if (isgraph(*pos2))
+                        *pos++=*pos2;
+                *pos=0;
+                m_serialized.push_back(reinterpret_cast<char*>(enc));
+#ifdef SHIBSP_XERCESC_HAS_XMLBYTE_RELEASE
+                XMLString::release(&enc);
+#else
+                XMLString::release((char**)&enc);
+#endif
+            }
+        }
+    }
+    return Attribute::getSerializedValues();
+}
+
+DDF XMLAttribute::marshall() const
+{
+    DDF ddf = Attribute::marshall();
+    ddf.name("XML");
+    DDF vlist = ddf.first();
+    for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
+        vlist.add(DDF(NULL).string(i->c_str()));
+    return ddf;
+}
index 3c9a4f6..8f9f0a1 100644 (file)
@@ -38,69 +38,38 @@ namespace shibsp {
          *
          * @param ids   array with primary identifier in first position, followed by any aliases
          */
-        XMLAttribute(const std::vector<std::string>& ids) : Attribute(ids) {}
+        XMLAttribute(const std::vector<std::string>& ids);
 
         /**
          * Constructs based on a remoted XMLAttribute.
          *
          * @param in    input object containing marshalled XMLAttribute
          */
-        XMLAttribute(DDF& in) : Attribute(in) {
-            DDF val = in.first().first();
-            while (val.string()) {
-                m_values.push_back(val.string());
-                val = in.first().next();
-            }
-        }
+        XMLAttribute(DDF& in);
 
-        virtual ~XMLAttribute() {}
+        virtual ~XMLAttribute();
 
         /**
          * Returns the set of values encoded as XML.
          *
          * @return  a mutable vector of the values
          */
-        std::vector<std::string>& getValues() {
-            return m_values;
-        }
+        std::vector<std::string>& getValues();
 
         /**
          * Returns the set of values encoded as XML.
          *
          * @return  an immutable vector of the values
          */
-        const std::vector<std::string>& getValues() const {
-            return m_values;
-        }
-
-        size_t valueCount() const {
-            return m_values.size();
-        }
-
-        void clearSerializedValues() {
-            m_serialized.clear();
-        }
-
-        const char* getString(size_t index) const {
-            return m_values[index].c_str();
-        }
-
-        void removeValue(size_t index) {
-            Attribute::removeValue(index);
-            if (index < m_values.size())
-                m_values.erase(m_values.begin() + index);
-        }
+        const std::vector<std::string>& getValues() const;
 
+        // Virtual function overrides.
+        size_t valueCount() const;
+        void clearSerializedValues();
+        const char* getString(size_t index) const;
+        void removeValue(size_t index);
         const std::vector<std::string>& getSerializedValues() const;
-
-        DDF marshall() const {
-            DDF ddf = Attribute::marshall();
-            ddf.name("XML");
-            DDF vlist = ddf.first();
-            for (std::vector<std::string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
-                vlist.add(DDF(NULL).string(i->c_str()));
-            return ddf;
-        }
+        DDF marshall() const;
 
     private:
         std::vector<std::string> m_values;
index 2d59528..4c99938 100644 (file)
-/*\r
- *  Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLAttributeDecoder.cpp\r
- *\r
- * Decodes arbitrary XML into an XMLAttribute.\r
- */\r
-\r
-#include "internal.h"\r
-#include "attribute/AttributeDecoder.h"\r
-#include "attribute/XMLAttribute.h"\r
-\r
-#include <saml/saml1/core/Assertions.h>\r
-#include <saml/saml2/core/Assertions.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder\r
-    {\r
-    public:\r
-        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}\r
-        ~XMLAttributeDecoder() {}\r
-\r
-        Attribute* decode(\r
-            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL\r
-            ) const;\r
-\r
-    private:\r
-        DDF convert(DOMElement* e, bool nameit=true) const;\r
-        auto_ptr_char m_formatter;\r
-        map<pair<xstring,xstring>,string> m_tagMap;\r
-    };\r
-\r
-    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)\r
-    {\r
-        return new XMLAttributeDecoder(e);\r
-    }\r
-};\r
-\r
-\r
-Attribute* XMLAttributeDecoder::decode(\r
-    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty\r
-    ) const\r
-{\r
-    if (!xmlObject)\r
-        return NULL;\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");\r
-\r
-    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));\r
-    vector<string>& dest = attr->getValues();\r
-\r
-    // Handle any non-Attribute object directly.\r
-    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {\r
-        DOMElement* e = xmlObject->getDOM();\r
-        if (e) {\r
-            if (log.isDebugEnabled()) {\r
-                log.debug(\r
-                    "decoding XMLAttribute (%s) from XMLObject (%s)",\r
-                    ids.front().c_str(),\r
-                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()\r
-                    );\r
-            }\r
-            dest.push_back(string());\r
-            XMLHelper::serialize(e, dest.back());\r
-        }\r
-        else {\r
-            log.warn("skipping XMLObject without a backing DOM");\r
-        }\r
-        return dest.empty() ? NULL : _decode(attr.release());\r
-    }\r
-\r
-    vector<XMLObject*>::const_iterator v,stop;\r
-\r
-    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);\r
-    if (saml2attr) {\r
-        const vector<XMLObject*>& values = saml2attr->getAttributeValues();\r
-        v = values.begin();\r
-        stop = values.end();\r
-        if (log.isDebugEnabled()) {\r
-            auto_ptr_char n(saml2attr->getName());\r
-            log.debug(\r
-                "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",\r
-                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                );\r
-        }\r
-    }\r
-    else {\r
-        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);\r
-        if (saml1attr) {\r
-            const vector<XMLObject*>& values = saml1attr->getAttributeValues();\r
-            v = values.begin();\r
-            stop = values.end();\r
-            if (log.isDebugEnabled()) {\r
-                auto_ptr_char n(saml1attr->getAttributeName());\r
-                log.debug(\r
-                    "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",\r
-                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()\r
-                    );\r
-            }\r
-        }\r
-        else {\r
-            log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");\r
-            return NULL;\r
-        }\r
-    }\r
-\r
-    for (; v!=stop; ++v) {\r
-        DOMElement* e = (*v)->getDOM();\r
-        if (e) {\r
-            dest.push_back(string());\r
-            XMLHelper::serialize(e, dest.back());\r
-        }\r
-        else\r
-            log.warn("skipping AttributeValue without a backing DOM");\r
-    }\r
-\r
-    return dest.empty() ? NULL : _decode(attr.release());\r
-}\r
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * XMLAttributeDecoder.cpp
+ *
+ * Decodes arbitrary XML into an XMLAttribute.
+ */
+
+#include "internal.h"
+#include "attribute/AttributeDecoder.h"
+#include "attribute/XMLAttribute.h"
+
+#include <saml/saml1/core/Assertions.h>
+#include <saml/saml2/core/Assertions.h>
+#include <xmltooling/util/XMLHelper.h>
+
+using namespace shibsp;
+using namespace opensaml;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+    class SHIBSP_DLLLOCAL XMLAttributeDecoder : virtual public AttributeDecoder
+    {
+    public:
+        XMLAttributeDecoder(const DOMElement* e) : AttributeDecoder(e) {}
+        ~XMLAttributeDecoder() {}
+
+        Attribute* decode(
+            const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty=NULL, const char* relyingParty=NULL
+            ) const;
+
+    private:
+        DDF convert(DOMElement* e, bool nameit=true) const;
+        auto_ptr_char m_formatter;
+        map<pair<xstring,xstring>,string> m_tagMap;
+    };
+
+    AttributeDecoder* SHIBSP_DLLLOCAL XMLAttributeDecoderFactory(const DOMElement* const & e)
+    {
+        return new XMLAttributeDecoder(e);
+    }
+};
+
+
+Attribute* XMLAttributeDecoder::decode(
+    const vector<string>& ids, const XMLObject* xmlObject, const char* assertingParty, const char* relyingParty
+    ) const
+{
+    if (!xmlObject)
+        return NULL;
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".AttributeDecoder.XML");
+
+    auto_ptr<XMLAttribute> attr(new XMLAttribute(ids));
+    vector<string>& dest = attr->getValues();
+
+    // Handle any non-Attribute object directly.
+    if (!xmlObject || !XMLString::equals(saml1::Attribute::LOCAL_NAME, xmlObject->getElementQName().getLocalPart())) {
+        DOMElement* e = xmlObject->getDOM();
+        if (e) {
+            if (log.isDebugEnabled()) {
+                log.debug(
+                    "decoding XMLAttribute (%s) from XMLObject (%s)",
+                    ids.front().c_str(),
+                    (xmlObject->getSchemaType() ? xmlObject->getSchemaType()->toString() : xmlObject->getElementQName().toString()).c_str()
+                    );
+            }
+            dest.push_back(string());
+            XMLHelper::serialize(e, dest.back());
+        }
+        else {
+            log.warn("skipping XMLObject without a backing DOM");
+        }
+        return dest.empty() ? NULL : _decode(attr.release());
+    }
+
+    vector<XMLObject*>::const_iterator v,stop;
+
+    const saml2::Attribute* saml2attr = dynamic_cast<const saml2::Attribute*>(xmlObject);
+    if (saml2attr) {
+        const vector<XMLObject*>& values = saml2attr->getAttributeValues();
+        v = values.begin();
+        stop = values.end();
+        if (log.isDebugEnabled()) {
+            auto_ptr_char n(saml2attr->getName());
+            log.debug(
+                "decoding XMLAttribute (%s) from SAML 2 Attribute (%s) with %lu value(s)",
+                ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                );
+        }
+    }
+    else {
+        const saml1::Attribute* saml1attr = dynamic_cast<const saml1::Attribute*>(xmlObject);
+        if (saml1attr) {
+            const vector<XMLObject*>& values = saml1attr->getAttributeValues();
+            v = values.begin();
+            stop = values.end();
+            if (log.isDebugEnabled()) {
+                auto_ptr_char n(saml1attr->getAttributeName());
+                log.debug(
+                    "decoding XMLAttribute (%s) from SAML 1 Attribute (%s) with %lu value(s)",
+                    ids.front().c_str(), n.get() ? n.get() : "unnamed", values.size()
+                    );
+            }
+        }
+        else {
+            log.warn("XMLObject type not recognized by XMLAttributeDecoder, no values returned");
+            return NULL;
+        }
+    }
+
+    for (; v!=stop; ++v) {
+        DOMElement* e = (*v)->getDOM();
+        if (e) {
+            dest.push_back(string());
+            XMLHelper::serialize(e, dest.back());
+        }
+        else
+            log.warn("skipping AttributeValue without a backing DOM");
+    }
+
+    return dest.empty() ? NULL : _decode(attr.release());
+}
index 75521a3..2a249e4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef __shibsp_attrfilt_h__
 #define __shibsp_attrfilt_h__
 
-#include <shibsp/attribute/filtering/FilteringContext.h>
+#include <shibsp/base.h>
 
+#include <vector>
 #include <xmltooling/Lockable.h>
 
 namespace shibsp {
 
+    class SHIBSP_API Attribute;
+    class SHIBSP_API FilteringContext;
+
     /**
      * Engine for filtering attribute values.
      */
@@ -36,9 +40,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(AttributeFilter);
     protected:
-        AttributeFilter() {}
+        AttributeFilter();
     public:
-        virtual ~AttributeFilter() {}
+        virtual ~AttributeFilter();
 
         /**
          * Filters values out of a set of attributes.
index 6c66f57..888a324 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +27,8 @@
 
 namespace shibsp {
 
+    class SHIBSP_API Attribute;
+
     class SHIBSP_API BasicFilteringContext : public FilteringContext
     {
     public:
@@ -45,39 +47,19 @@ namespace shibsp {
             const opensaml::saml2md::RoleDescriptor* role=NULL,
             const XMLCh* authncontext_class=NULL,
             const XMLCh* authncontext_decl=NULL
-            ) : m_app(app), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl) {
-            if (role)
-                m_issuer = dynamic_cast<opensaml::saml2md::EntityDescriptor*>(role->getParent())->getEntityID();
-            for (std::vector<Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a)
-                m_attributes.insert(std::multimap<std::string,Attribute*>::value_type((*a)->getId(), *a));
-        }
+            );
 
-        virtual ~BasicFilteringContext() {}
+        virtual ~BasicFilteringContext();
 
-        const Application& getApplication() const {
-            return m_app;
-        }
-        const XMLCh* getAuthnContextClassRef() const {
-            return m_class;
-        }
-        const XMLCh* getAuthnContextDeclRef() const {
-            return m_decl;
-        }
-        const XMLCh* getAttributeRequester() const {
-            return m_app.getXMLString("entityID").second;
-        }
-        const XMLCh* getAttributeIssuer() const {
-            return m_issuer;
-        }
-        const opensaml::saml2md::RoleDescriptor* getAttributeRequesterMetadata() const {
-            return NULL;
-        }
-        const opensaml::saml2md::RoleDescriptor* getAttributeIssuerMetadata() const {
-            return m_role;
-        }
-        const std::multimap<std::string,Attribute*>& getAttributes() const {
-            return m_attributes;
-        }
+        // Virtual function overrides.
+        const Application& getApplication() const;
+        const XMLCh* getAuthnContextClassRef() const;
+        const XMLCh* getAuthnContextDeclRef() const;
+        const XMLCh* getAttributeRequester() const;
+        const XMLCh* getAttributeIssuer() const;
+        const opensaml::saml2md::RoleDescriptor* getAttributeRequesterMetadata() const;
+        const opensaml::saml2md::RoleDescriptor* getAttributeIssuerMetadata() const;
+        const std::multimap<std::string,Attribute*>& getAttributes() const;
 
     private:
         const Application& m_app;
index 2fff8ae..f658643 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef __shibsp_filtpolctx_h__
 #define __shibsp_filtpolctx_h__
 
-#include <shibsp/attribute/filtering/MatchFunctor.h>
+#include <shibsp/base.h>
 
 #include <map>
 #include <string>
 
 namespace shibsp {
 
+    class SHIBSP_API MatchFunctor;
+
     /**
      * Context for lookup of instantiated MatchFunctor objects.
      */
@@ -42,10 +44,9 @@ namespace shibsp {
          * 
          * @param functors  reference to a map of id/functor pairs
          */
-        FilterPolicyContext(std::multimap<std::string,MatchFunctor*>& functors) : m_functors(functors) {
-        }
+        FilterPolicyContext(std::multimap<std::string,MatchFunctor*>& functors);
 
-        virtual ~FilterPolicyContext() {}
+        virtual ~FilterPolicyContext();
 
         /**
          * Gets a mutable map to store id/functor pairs.
@@ -54,9 +55,7 @@ namespace shibsp {
          *
          * @return  reference to a mutable map containing available MatchFunctors 
          */
-        std::multimap<std::string,MatchFunctor*>& getMatchFunctors() const {
-            return m_functors;
-        }
+        std::multimap<std::string,MatchFunctor*>& getMatchFunctors() const;
     
     private:
         std::multimap<std::string,MatchFunctor*>& m_functors;
index c4e3032..422a725 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <shibsp/base.h>
 
-#include <saml/saml2/metadata/Metadata.h>
+#include <map>
+#include <string>
+
+namespace opensaml {
+    namespace saml2md {
+        class SAML_API RoleDescriptor;
+    };
+};
 
 namespace shibsp {
 
@@ -39,9 +46,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(FilteringContext);
     protected:
-        FilteringContext() {}
+        FilteringContext();
     public:
-        virtual ~FilteringContext() {}
+        virtual ~FilteringContext();
 
         /**
          * Gets the Application doing the filtering.
index 6018414..a802d3d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -37,9 +37,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(MatchFunctor);
     protected:
-        MatchFunctor() {}
+        MatchFunctor();
     public:
-        virtual ~MatchFunctor() {}
+        virtual ~MatchFunctor();
 
         /**
          * Evaluates this matching criteria. This evaluation is used when a filtering engine determines policy
index 35cea2c..828071d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 #include "internal.h"
 #include "exceptions.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
index a782f78..55bbd14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +22,7 @@
 
 #include "internal.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 using namespace shibsp;
 
index ad21399..dc67e1f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -38,3 +38,11 @@ void SHIBSP_API shibsp::registerAttributeFilters()
     conf.AttributeFilterManager.registerFactory(XML_ATTRIBUTE_FILTER, XMLAttributeFilterFactory);
     conf.AttributeFilterManager.registerFactory(CHAINING_ATTRIBUTE_FILTER, ChainingAttributeFilterFactory);
 }
+
+AttributeFilter::AttributeFilter()
+{
+}
+
+AttributeFilter::~AttributeFilter()
+{
+}
index 6825fe3..9701023 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,9 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
 
 using namespace opensaml::saml2md;
 
index f342f61..b421a11 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 #include <xercesc/util/regx/RegularExpression.hpp>
 
index 563e762..e4cb12d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 namespace shibsp {
 
index e774a7a..8c37255 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 /**
  * AttributeRequesterInEntityGroupFunctor.cpp
  * 
- * A match function that evaluates to true if the attribute requester is found in metadata and is a member\r
+ * A match function that evaluates to true if the attribute requester is found in metadata and is a member
  * of the given entity group.
  */
 
@@ -25,6 +25,9 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
+
+#include <saml/saml2/metadata/Metadata.h>
 
 using namespace opensaml::saml2md;
 
@@ -33,7 +36,7 @@ namespace shibsp {
     static const XMLCh groupID[] = UNICODE_LITERAL_7(g,r,o,u,p,I,D);
 
     /**
-     * A match function that evaluates to true if the attribute requester is found in metadata and is a member\r
+     * A match function that evaluates to true if the attribute requester is found in metadata and is a member
      * of the given entity group.
      */
     class SHIBSP_DLLLOCAL AttributeRequesterInEntityGroupFunctor : public MatchFunctor
index 1bbdc23..171a898 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 #include <xercesc/util/regx/RegularExpression.hpp>
 
index 5eecf7d..82cb30f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 namespace shibsp {
 
index b7899b3..5f57d71 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 #include "metadata/MetadataExt.h"
 
+#include <saml/saml2/metadata/Metadata.h>
 #include <xercesc/util/regx/RegularExpression.hpp>
 
 using namespace opensaml::saml2md;
index c3e58e8..3b33ac1 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 #include <xercesc/util/regx/RegularExpression.hpp>
 
index 14a1bb1..9a1cdfc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 using namespace shibsp;
 using namespace std;
index 5fc4fa0..ac4952b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 #include <xercesc/util/regx/RegularExpression.hpp>
 
index 707f318..7721fe8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 using namespace shibsp;
 using namespace std;
index b66bbbd..d7e6665 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 #include <xercesc/util/regx/RegularExpression.hpp>
 
index 3c8393e..f52843a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 namespace shibsp {
 
diff --git a/shibsp/attribute/filtering/impl/BasicFilteringContext.cpp b/shibsp/attribute/filtering/impl/BasicFilteringContext.cpp
new file mode 100644 (file)
index 0000000..67ba166
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ *  Copyright 2001-2009 Internet2
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * BasicFilteringContext.cpp
+ * 
+ * A trivial FilteringContext implementation.
+ */
+
+#include "internal.h"
+#include "Application.h"
+#include "attribute/Attribute.h"
+#include "attribute/filtering/BasicFilteringContext.h"
+
+#include <saml/saml2/metadata/Metadata.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace std;
+
+FilteringContext::FilteringContext()
+{
+}
+
+FilteringContext::~FilteringContext()
+{
+}
+
+BasicFilteringContext::BasicFilteringContext(
+    const Application& app,
+    const vector<Attribute*>& attributes,
+    const RoleDescriptor* role,
+    const XMLCh* authncontext_class,
+    const XMLCh* authncontext_decl
+    ) : m_app(app), m_role(role), m_issuer(NULL), m_class(authncontext_class), m_decl(authncontext_decl)
+{
+    if (role)
+        m_issuer = dynamic_cast<EntityDescriptor*>(role->getParent())->getEntityID();
+    for (vector<Attribute*>::const_iterator a = attributes.begin(); a != attributes.end(); ++a)
+        m_attributes.insert(multimap<string,Attribute*>::value_type((*a)->getId(), *a));
+}
+
+BasicFilteringContext::~BasicFilteringContext()
+{
+}
+
+const Application& BasicFilteringContext::getApplication() const
+{
+    return m_app;
+}
+
+const XMLCh* BasicFilteringContext::getAuthnContextClassRef() const
+{
+    return m_class;
+}
+
+const XMLCh* BasicFilteringContext::getAuthnContextDeclRef() const
+{
+    return m_decl;
+}
+
+const XMLCh* BasicFilteringContext::getAttributeRequester() const
+{
+    return m_app.getXMLString("entityID").second;
+}
+
+const XMLCh* BasicFilteringContext::getAttributeIssuer() const
+{
+    return m_issuer;
+}
+
+const RoleDescriptor* BasicFilteringContext::getAttributeRequesterMetadata() const
+{
+    return NULL;
+}
+
+const RoleDescriptor* BasicFilteringContext::getAttributeIssuerMetadata() const
+{
+    return m_role;
+}
+
+const multimap<string,Attribute*>& BasicFilteringContext::getAttributes() const
+{
+    return m_attributes;
+}
index 1ba0ec6..a2e7e45 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
  */
 
 #include "internal.h"
+#include "attribute/filtering/FilterPolicyContext.h"
 #include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
@@ -125,3 +126,24 @@ void SHIBSP_API shibsp::registerMatchFunctors()
     REGISTER_FACTORY(AttributeRequesterInEntityGroup);
     REGISTER_FACTORY(AttributeScopeMatchesShibMDScope);
 }
+
+MatchFunctor::MatchFunctor()
+{
+}
+
+MatchFunctor::~MatchFunctor()
+{
+}
+
+FilterPolicyContext::FilterPolicyContext(multimap<string,MatchFunctor*>& functors) : m_functors(functors)
+{
+}
+
+FilterPolicyContext::~FilterPolicyContext()
+{
+}
+
+multimap<string,MatchFunctor*>& FilterPolicyContext::getMatchFunctors() const
+{
+    return m_functors;
+}
index 9a22474..a0f07b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 #include "internal.h"
 #include "exceptions.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
index 91d1106..f1630c3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
 #include "attribute/Attribute.h"
 #include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 
 using namespace shibsp;
 using namespace std;
index 2649f42..7b260c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
 #include "internal.h"
 #include "exceptions.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
 #include <xercesc/util/XMLUniDefs.hpp>
index 32fab83..d266096 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "attribute/Attribute.h"
 #include "attribute/filtering/AttributeFilter.h"
+#include "attribute/filtering/FilteringContext.h"
 #include "attribute/filtering/FilterPolicyContext.h"
+#include "attribute/filtering/MatchFunctor.h"
 #include "util/SPConstants.h"
 
 #include <xmltooling/util/NDC.h>
index 63644ca..9e4f217 100644 (file)
 #define __shibsp_extractor_h__
 
 #include <shibsp/base.h>
+
+#include <string>
+#include <vector>
 #include <xmltooling/Lockable.h>
-#include <saml/saml2/metadata/Metadata.h>
+
+namespace xmltooling {
+    class XMLTOOL_API XMLObject;
+};
+
+namespace opensaml {
+    namespace saml2md {
+        class SAML_API RoleDescriptor;
+    };
+};
 
 namespace shibsp {
 
@@ -39,9 +51,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(AttributeExtractor);
     protected:
-        AttributeExtractor() {}
+        AttributeExtractor();
     public:
-        virtual ~AttributeExtractor() {}
+        virtual ~AttributeExtractor();
 
         /**
          * Extracts the attributes found in an XMLObject.
index 524dde8..bcf0232 100644 (file)
 
 #include <shibsp/base.h>
 
-#include <saml/Assertion.h>
-#include <saml/saml2/metadata/Metadata.h>
+#include <string>
+#include <vector>
 #include <xmltooling/Lockable.h>
 
+namespace opensaml {
+    class SAML_API Assertion;
+    namespace saml2 {
+        class SAML_API NameID;
+    };
+    namespace saml2md {
+        class SAML_API EntityDescriptor;
+    };
+};
+
 namespace shibsp {
 
     class SHIBSP_API Application;
@@ -48,9 +58,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(AttributeResolver);
     protected:
-        AttributeResolver() {}
+        AttributeResolver();
     public:
-        virtual ~AttributeResolver() {}
+        virtual ~AttributeResolver();
 
         /**
          * Creates a ResolutionContext based on session bootstrap material.
index 760246a..6eab48a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include <shibsp/base.h>
 
-#include <saml/Assertion.h>
+#include <vector>
+
+namespace opensaml {
+    class SAML_API Assertion;
+};
 
 namespace shibsp {
 
@@ -38,9 +42,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(ResolutionContext);
     protected:
-        ResolutionContext() {}
+        ResolutionContext();
     public:
-        virtual ~ResolutionContext() {}
+        virtual ~ResolutionContext();
         
         /**
          * Returns the set of Attributes resolved and added to the context.
index 523cdc3..d46fdff 100644 (file)
@@ -88,6 +88,14 @@ void SHIBSP_API shibsp::registerAttributeExtractors()
     SPConfig::getConfig().AttributeExtractorManager.registerFactory(CHAINING_ATTRIBUTE_EXTRACTOR, ChainingExtractorFactory);
 }
 
+AttributeExtractor::AttributeExtractor()
+{
+}
+
+AttributeExtractor::~AttributeExtractor()
+{
+}
+
 ChainingAttributeExtractor::ChainingAttributeExtractor(const DOMElement* e)
 {
     SPConfig& conf = SPConfig::getConfig();
index d0b63f1..4dd7702 100644 (file)
@@ -27,6 +27,7 @@
 #include "attribute/resolver/AttributeResolver.h"
 #include "attribute/resolver/ResolutionContext.h"
 
+#include <saml/Assertion.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/util/XMLHelper.h>
 
@@ -149,6 +150,22 @@ void SHIBSP_API shibsp::registerAttributeResolvers()
     SPConfig::getConfig().AttributeResolverManager.registerFactory(CHAINING_ATTRIBUTE_RESOLVER, ChainingResolverFactory);
 }
 
+ResolutionContext::ResolutionContext()
+{
+}
+
+ResolutionContext::~ResolutionContext()
+{
+}
+
+AttributeResolver::AttributeResolver()
+{
+}
+
+AttributeResolver::~AttributeResolver()
+{
+}
+
 ChainingAttributeResolver::ChainingAttributeResolver(const DOMElement* e)
 {
     SPConfig& conf = SPConfig::getConfig();
index d44311e..f98f2a2 100644 (file)
 #include "util/SPConstants.h"
 
 #include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <xmltooling/security/CredentialResolver.h>
+#include <xmltooling/util/DateTime.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 
@@ -165,29 +168,29 @@ void DelegationExtractor::extractAttributes(
                         val.addmember("DelegationInstant").string(temp.get());
                     }
 
-                    auto_arrayptr<char> name(toUTF8(n->getName()));\r
-                    if (name.get() && *name.get()) {\r
-                        val.addmember("Name").string(name.get());\r
-                        char* str = toUTF8(n->getFormat());\r
-                        if (str && *str)\r
-                            val.addmember("Format").string(str);\r
-                        delete[] str;\r
-\r
-                        str = toUTF8(n->getNameQualifier());\r
-                        if (str && *str)\r
-                            val.addmember("NameQualifier").string(str);\r
-                        delete[] str;\r
-\r
-                        str = toUTF8(n->getSPNameQualifier());\r
-                        if (str && *str)\r
-                            val.addmember("SPNameQualifier").string(str);\r
-                        delete[] str;\r
-\r
-                        str = toUTF8(n->getSPProvidedID());\r
-                        if (str && *str)\r
-                            val.addmember("SPProvidedID").string(str);\r
-                        delete[] str;\r
-                    }\r
+                    auto_arrayptr<char> name(toUTF8(n->getName()));
+                    if (name.get() && *name.get()) {
+                        val.addmember("Name").string(name.get());
+                        char* str = toUTF8(n->getFormat());
+                        if (str && *str)
+                            val.addmember("Format").string(str);
+                        delete[] str;
+
+                        str = toUTF8(n->getNameQualifier());
+                        if (str && *str)
+                            val.addmember("NameQualifier").string(str);
+                        delete[] str;
+
+                        str = toUTF8(n->getSPNameQualifier());
+                        if (str && *str)
+                            val.addmember("SPNameQualifier").string(str);
+                        delete[] str;
+
+                        str = toUTF8(n->getSPProvidedID());
+                        if (str && *str)
+                            val.addmember("SPProvidedID").string(str);
+                        delete[] str;
+                    }
 
                     if (n != (*d)->getNameID())
                         delete n;
index d730b35..0cb4142 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "Application.h"
 #include "attribute/AttributeDecoder.h"
 #include "attribute/SimpleAttribute.h"
@@ -28,6 +29,8 @@
 
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/security/Credential.h>
 #include <xmltooling/security/SecurityHelper.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
@@ -72,6 +75,7 @@ namespace shibsp {
         }
 
     private:
+        auto_ptr_char m_hashAlg;
         vector<string> m_hashId;
         vector<string> m_signingId;
         vector<string> m_encryptionId;
@@ -88,10 +92,11 @@ namespace shibsp {
 
     static const XMLCh encryptionId[] = UNICODE_LITERAL_12(e,n,c,r,y,p,t,i,o,n,I,d);
     static const XMLCh hashId[] =       UNICODE_LITERAL_6(h,a,s,h,I,d);
+    static const XMLCh hashAlg[] =      UNICODE_LITERAL_7(h,a,s,h,A,l,g);
     static const XMLCh signingId[] =    UNICODE_LITERAL_9(s,i,g,n,i,n,g,I,d);
 };
 
-KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e)
+KeyDescriptorExtractor::KeyDescriptorExtractor(const DOMElement* e) : m_hashAlg(e ? e->getAttributeNS(NULL, hashAlg) : NULL)
 {
     if (e) {
         const XMLCh* a = e->getAttributeNS(NULL, hashId);
@@ -129,12 +134,15 @@ void KeyDescriptorExtractor::extractAttributes(
         mcc.setUsage(Credential::SIGNING_CREDENTIAL);
         if (application.getMetadataProvider()->resolve(creds, &mcc)) {
             if (!m_hashId.empty()) {
+                const char* alg = m_hashAlg.get();
+                if (!alg || !*alg)
+                    alg = "SHA1";
                 auto_ptr<SimpleAttribute> attr(new SimpleAttribute(m_hashId));
                 vector<string>& vals = attr->getValues();
                 for (vector<const Credential*>::const_iterator c = creds.begin(); c != creds.end(); ++c) {
                     if (vals.empty() || !vals.back().empty())
                         vals.push_back(string());
-                    vals.back() = SecurityHelper::getDEREncoding(*(*c), true);
+                    vals.back() = SecurityHelper::getDEREncoding(*(*c), alg);
                 }
                 if (vals.back().empty())
                     vals.pop_back();
index ceff508..2c9c8fc 100644 (file)
 #include "attribute/resolver/ResolutionContext.h"
 #include "binding/SOAPClient.h"
 #include "metadata/MetadataProviderCriteria.h"
+#include "security/SecurityPolicy.h"
 #include "util/SPConstants.h"
 
 #include <saml/exceptions.h>
-#include <saml/binding/SecurityPolicy.h>
 #include <saml/saml1/binding/SAML1SOAPClient.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml1/core/Protocols.h>
 #include <saml/saml2/binding/SAML2SOAPClient.h>
 #include <saml/saml2/core/Protocols.h>
 #include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLHelper.h>
@@ -239,7 +240,7 @@ QueryResolver::QueryResolver(const DOMElement* e) : m_log(Category::getInstance(
                     obj.release();
                 }
             }
-            else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1P_NS, AttributeDesignator::LOCAL_NAME)) {
+            else if (XMLHelper::isNodeNamed(child, samlconstants::SAML1_NS, AttributeDesignator::LOCAL_NAME)) {
                 auto_ptr<XMLObject> obj(AttributeDesignatorBuilder::buildOneFromElement(child));
                 AttributeDesignator* down = dynamic_cast<AttributeDesignator*>(obj.get());
                 if (down) {
index abd1cad..c4d3336 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCache.h"
 #include "attribute/resolver/ResolutionContext.h"
 #include "binding/SOAPClient.h"
 #include "metadata/MetadataProviderCriteria.h"
+#include "security/SecurityPolicy.h"
 #include "util/SPConstants.h"
 
 #include <saml/exceptions.h>
 #include <saml/SAMLConfig.h>
-#include <saml/binding/SecurityPolicy.h>
 #include <saml/saml2/binding/SAML2SOAPClient.h>
 #include <saml/saml2/core/Protocols.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/TrustEngine.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
index c27df80..e77133a 100644 (file)
  */
 
 #include "internal.h"
+#include "exceptions.h"
 #include "Application.h"
 #include "ServiceProvider.h"
+#include "attribute/Attribute.h"
 #include "attribute/AttributeDecoder.h"
 #include "attribute/filtering/AttributeFilter.h"
 #include "attribute/filtering/BasicFilteringContext.h"
 #include "attribute/resolver/AttributeExtractor.h"
+#include "remoting/ddf.h"
 #include "security/SecurityPolicy.h"
 #include "util/SPConstants.h"
 
 #include <saml/SAMLConfig.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/core/Assertions.h>
+#include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/saml2/metadata/ObservableMetadataProvider.h>
+#include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/security/TrustEngine.h>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 
index 7f89680..95427f6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -33,8 +33,8 @@ namespace shibsp {
      */
     class SHIBSP_API ArtifactResolver : public opensaml::MessageDecoder::ArtifactResolver {
     public:
-        ArtifactResolver() {}
-        virtual ~ArtifactResolver() {}
+        ArtifactResolver();
+        virtual ~ArtifactResolver();
 
         opensaml::saml1p::Response* resolve(
             const std::vector<opensaml::SAMLArtifact*>& artifacts,
index eedebc0..f5b3ce3 100644 (file)
 #ifndef __shibsp_soap11client_h__
 #define __shibsp_soap11client_h__
 
-#include <shibsp/security/SecurityPolicy.h>
+#include <shibsp/base.h>
+
 #include <saml/binding/SOAPClient.h>
-#include <xmltooling/security/CredentialResolver.h>
 
 namespace shibsp {
 
     class SHIBSP_API PropertySet;
+    class SHIBSP_API SecurityPolicy;
 
     /**
      * Specialized SOAPClient for SP environment.
@@ -44,10 +45,7 @@ namespace shibsp {
          */
         SOAPClient(SecurityPolicy& policy);
         
-        virtual ~SOAPClient() {
-            if (m_credResolver)
-                m_credResolver->unlock();
-        }
+        virtual ~SOAPClient();
 
         /**
          * Override handles message signing for SAML payloads.
index 52e68fc..3e18aff 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 
 #include "internal.h"
 #include "Application.h"
-#include "exceptions.h"
 #include "binding/ArtifactResolver.h"
 #include "binding/SOAPClient.h"
 #include "security/SecurityPolicy.h"
 
+#include <saml/exceptions.h>
 #include <saml/saml1/core/Protocols.h>
 #include <saml/saml1/binding/SAML1SOAPClient.h>
 #include <saml/saml2/core/Protocols.h>
 #include <saml/saml2/binding/SAML2Artifact.h>
 #include <saml/saml2/binding/SAML2SOAPClient.h>
+#include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 #include <saml/util/SAMLConstants.h>
 
@@ -44,6 +45,14 @@ using namespace opensaml;
 using namespace xmltooling;
 using namespace std;
 
+ArtifactResolver::ArtifactResolver()
+{
+}
+
+ArtifactResolver::~ArtifactResolver()
+{
+}
+
 saml1p::Response* ArtifactResolver::resolve(
     const vector<SAMLArtifact*>& artifacts,
     const IDPSSODescriptor& idpDescriptor,
index cc5c6dc..e12f4f0 100644 (file)
 
 #include "internal.h"
 #include "Application.h"
-#include "exceptions.h"
 #include "ServiceProvider.h"
 #include "binding/SOAPClient.h"
+#include "security/SecurityPolicy.h"
 
+#include <saml/exceptions.h>
 #include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+#include <saml/signature/ContentReference.h>
+#include <xmltooling/security/Credential.h>
+#include <xmltooling/signature/Signature.h>
 #include <xmltooling/soap/SOAP.h>
 #include <xmltooling/soap/HTTPSOAPTransport.h>
 #include <xmltooling/util/NDC.h>
@@ -42,6 +47,12 @@ SOAPClient::SOAPClient(SecurityPolicy& policy)
 {
 }
 
+SOAPClient::~SOAPClient()
+{
+    if (m_credResolver)
+        m_credResolver->unlock();
+}
+
 void SOAPClient::send(const soap11::Envelope& env, const char* from, MetadataCredentialCriteria& to, const char* endpoint)
 {
     // Check for message signing requirements.   
index a12e720..c56197c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 /**
  * @file shibsp/exceptions.h
  * 
- * Exception classes
+ * Exception classes.
  */
  
 #ifndef __shibsp_exceptions_h__
 #define __shibsp_exceptions_h__
 
 #include <shibsp/base.h>
-#ifndef SHIBSP_LITE
-# include <saml/exceptions.h>
-#else
-# include <xmltooling/exceptions.h>
-#endif
+#include <xmltooling/exceptions.h>
 
 namespace shibsp {
     
index 20a480b..fcc5927 100644 (file)
 #include <shibsp/remoting/ddf.h>
 #include <shibsp/util/DOMPropertySet.h>
 
+#include <map>
+#include <string>
+#include <xmltooling/logging.h>
+
 #ifndef SHIBSP_LITE
-# include <saml/binding/MessageEncoder.h>
-# include <saml/saml2/core/Protocols.h>
+namespace opensaml {
+    class SAML_API MessageEncoder;
+    namespace saml2md {
+        class SAML_API RoleDescriptor;
+    };
+    namespace saml2p {
+        class SAML_API StatusResponseType;
+    };
+};
 #endif
-#include <xmltooling/logging.h>
-#include <xmltooling/XMLObject.h>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
+
+namespace xmltooling {
+    class XMLTOOL_API HTTPRequest;
+    class XMLTOOL_API HTTPResponse;
+    class XMLTOOL_API XMLObject;
+};
 
 namespace shibsp {
 
@@ -213,7 +226,7 @@ namespace shibsp {
         xmltooling::auto_ptr_char m_configNS;
 
     public:
-        virtual ~AbstractHandler() {}
+        virtual ~AbstractHandler();
 
     private:
         std::pair<std::string,const char*> getPostCookieNameProps(const Application& app, const char* relayState) const;
index 752e86c..4354e97 100644 (file)
 
 #include <shibsp/handler/AbstractHandler.h>
 #include <shibsp/handler/RemotedHandler.h>
+
 #ifndef SHIBSP_LITE
-# include <saml/binding/MessageDecoder.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/metadata/Metadata.h>
+namespace opensaml {
+    class SAML_API Assertion;
+    class SAML_API MessageDecoder;
+    namespace saml1 {
+        class SAML_API NameIdentifier;
+    };
+    namespace saml2 {
+        class SAML_API NameID;
+    };
+    namespace saml2md {
+        class SAML_API SPSSODescriptor;
+    };
+};
 #endif
-#include <xmltooling/unicode.h>
 
 namespace shibsp {
 
@@ -57,11 +67,19 @@ namespace shibsp {
         /**
          * Constructor
          * 
-         * @param e     root of DOM configuration
-         * @param appId ID of application that "owns" the handler
-         * @param log   a logging object to use
+         * @param e         root of DOM configuration
+         * @param appId     ID of application that "owns" the handler
+         * @param log       a logging object to use
+         * @param filter    optional filter controls what child elements to include as nested PropertySets
+         * @param remapper  optional map of property rename rules for legacy property support
          */
-        AssertionConsumerService(const xercesc::DOMElement* e, const char* appId, xmltooling::logging::Category& log);
+        AssertionConsumerService(
+            const xercesc::DOMElement* e,
+            const char* appId,
+            xmltooling::logging::Category& log,
+            xercesc::DOMNodeFilter* filter=NULL,
+            const std::map<std::string,std::string>* remapper=NULL
+            );
 
         /**
          * Enforce address checking requirements.
@@ -154,9 +172,7 @@ namespace shibsp {
             ) const;
 
     public:
-        const char* getType() const {
-            return "AssertionConsumerService";
-        }
+        const char* getType() const;
 
 #endif
     private:
@@ -185,7 +201,6 @@ namespace shibsp {
 #if defined (_MSC_VER)
     #pragma warning( pop )
 #endif
-
 };
 
 #endif /* __shibsp_acshandler_h__ */
index a73b1ff..f397e27 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 /**
  * @file shibsp/handler/Handler.h
  * 
- * Pluggable runtime functionality that implement protocols and services 
+ * Pluggable runtime functionality that implement protocols and services.
  */
 
 #ifndef __shibsp_handler_h__
 #define __shibsp_handler_h__
 
 #include <shibsp/util/PropertySet.h>
+
 #ifndef SHIBSP_LITE
-# include <saml/saml2/metadata/Metadata.h>
+namespace opensaml {
+    namespace saml2md {
+        class SAML_API SPSSODescriptor;
+    };
+};
 #endif
 
 namespace shibsp {
@@ -39,9 +44,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(Handler);
     protected:
-        Handler() {}
+        Handler();
     public:
-        virtual ~Handler() {}
+        virtual ~Handler();
 
         /**
          * Executes handler functionality as an incoming request.
@@ -72,9 +77,7 @@ namespace shibsp {
          *
          * @return  a Handler type
          */
-        virtual const char* getType() const {
-            return getString("type").second;
-        }
+        virtual const char* getType() const;
 #endif
     };
     
index 7026563..7040500 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -23,7 +23,6 @@
 #ifndef __shibsp_logout_h__
 #define __shibsp_logout_h__
 
-#include <shibsp/SPRequest.h>
 #include <shibsp/handler/RemotedHandler.h>
 
 namespace shibsp {
@@ -39,7 +38,7 @@ namespace shibsp {
     class SHIBSP_API LogoutHandler : public RemotedHandler
     {
     public:
-        virtual ~LogoutHandler() {}
+        virtual ~LogoutHandler();
 
         /**
          * The base method will iteratively attempt front-channel notification
@@ -69,7 +68,7 @@ namespace shibsp {
         void receive(DDF& in, std::ostream& out);
 
     protected:
-        LogoutHandler() : m_initiator(true) {}
+        LogoutHandler();
         
         /** Flag indicating whether the subclass is acting as a LogoutInitiator. */
         bool m_initiator;
@@ -107,6 +106,7 @@ namespace shibsp {
             ) const;
 
         /**
+         * @deprecated
          * Sends a response template to the user agent informing it of the results of a logout attempt.
          *
          * @param application   the Application to use in determining the logout template
@@ -122,6 +122,21 @@ namespace shibsp {
             bool local=true,
             const char* status=NULL
             ) const;
+
+        /**
+         * Sends a response template to the user agent informing it of the results of a logout attempt.
+         *
+         * @param application   the Application to use in determining the logout template
+         * @param request       the HTTP client request to supply to the template
+         * @param response      the HTTP response to use
+         * @param type          designates the prefix of logout template name to use
+         */
+        std::pair<bool,long> sendLogoutPage(
+            const Application& application,
+            const xmltooling::HTTPRequest& request,
+            xmltooling::HTTPResponse& response,
+            const char* type
+            ) const;
     };
 
 #if defined (_MSC_VER)
index 37c6e53..d7bdd8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef __shibsp_remhandler_h__
 #define __shibsp_remhandler_h__
 
-#include <shibsp/SPRequest.h>
 #include <shibsp/handler/Handler.h>
 #include <shibsp/remoting/ListenerService.h>
 
+namespace xmltooling {
+    class XMLTOOL_API HTTPRequest;
+    class XMLTOOL_API HTTPResponse;
+};
+
 namespace shibsp {
 
     /**
@@ -38,7 +42,7 @@ namespace shibsp {
         virtual ~RemotedHandler();
 
     protected:
-        RemotedHandler() {}
+        RemotedHandler();
 
         /**
          * Establishes message remoting using the supplied address.
index ab19446..67530d4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -35,11 +35,15 @@ namespace shibsp {
      */
     class SHIBSP_API SessionInitiator : public virtual Handler
     {
+        friend void SHIBSP_API registerSessionInitiators();
     protected:
-        SessionInitiator() {}
+        /** Property remapper for configuration compatibility. */
+        static std::map<std::string,std::string> m_remapper;
+
+        SessionInitiator();
 
     public:
-        virtual ~SessionInitiator() {}
+        virtual ~SessionInitiator();
 
         /**
          * Executes an incoming request.
@@ -57,9 +61,7 @@ namespace shibsp {
         std::pair<bool,long> run(SPRequest& request, bool isHandler=true) const;
 
 #ifndef SHIBSP_LITE
-        const char* getType() const {
-            return "SessionInitiator";
-        }
+        const char* getType() const;
 #endif
     };
     
index e42ef5b..ca7e3c2 100644 (file)
-/*
- *  Copyright 2001-2009 Internet2
- *
- * Licensed 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.
- */
-
-/**
- * AbstractHandler.cpp
- *
- * Base class for handlers based on a DOMPropertySet.
- */
-
-#include "internal.h"
-#include "Application.h"
-#include "exceptions.h"
-#include "ServiceProvider.h"
-#include "SPRequest.h"
-#include "handler/AbstractHandler.h"
-#include "handler/LogoutHandler.h"
-#include "remoting/ListenerService.h"
-#include "util/CGIParser.h"
-#include "util/SPConstants.h"
-#include "util/TemplateParameters.h"
-
-#include <vector>
-#include <fstream>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/PathResolver.h>
-#include <xmltooling/util/URLEncoder.h>
-
-
-#ifndef SHIBSP_LITE
-# include <saml/saml1/core/Protocols.h>
-# include <saml/saml2/core/Protocols.h>
-# include <saml/saml2/metadata/Metadata.h>
-# include <saml/saml2/metadata/MetadataCredentialCriteria.h>
-# include <saml/util/SAMLConstants.h>
-# include <saml/SAMLConfig.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <xmltooling/util/StorageService.h>
-using namespace opensaml::saml2md;
-#else
-# include "lite/SAMLConstants.h"
-#endif
-
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/util/URLEncoder.h>
-
-using namespace shibsp;
-using namespace samlconstants;
-using namespace opensaml;
-using namespace xmltooling;
-using namespace xercesc;
-using namespace std;
-
-namespace shibsp {
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory MetadataGeneratorFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory StatusHandlerFactory;
-    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SessionHandlerFactory;
-
-    void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {
-        static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-        int r;
-        unsigned char b1,b2;
-        buf.erase();
-        for (unsigned int i=0; i<len; i+=4) {
-            r = rand();
-            b1 = (0x00FF & r);
-            b2 = (0xFF00 & r)  >> 8;
-            buf += (DIGITS[(0xF0 & b1) >> 4 ]);
-            buf += (DIGITS[0x0F & b1]);
-            buf += (DIGITS[(0xF0 & b2) >> 4 ]);
-            buf += (DIGITS[0x0F & b2]);
-        }
-    }
-};
-
-void SHIBSP_API shibsp::registerHandlers()
-{
-    SPConfig& conf=SPConfig::getConfig();
-
-    conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);
-    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory);
-
-    conf.ArtifactResolutionServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2ArtifactResolutionFactory);
-
-    conf.HandlerManager.registerFactory(SAML20_BINDING_URI, AssertionLookupFactory);
-    conf.HandlerManager.registerFactory(METADATA_GENERATOR_HANDLER, MetadataGeneratorFactory);
-    conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);
-    conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);
-
-    conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);
-    conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);
-    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);
-    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);
-    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);
-    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2LogoutFactory);
-    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2LogoutFactory);
-
-    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2NameIDMgmtFactory);
-    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2NameIDMgmtFactory);
-    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2NameIDMgmtFactory);
-    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2NameIDMgmtFactory);
-    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2NameIDMgmtFactory);
-}
-
-AbstractHandler::AbstractHandler(
-    const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
-    ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {
-    load(e,NULL,filter,remapper);
-}
-
-#ifndef SHIBSP_LITE
-
-void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleDescriptor* role) const
-{
-    const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);
-    if (r2) {
-        const saml2p::Status* status = r2->getStatus();
-        if (status) {
-            const saml2p::StatusCode* sc = status->getStatusCode();
-            const XMLCh* code = sc ? sc->getValue() : NULL;
-            if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
-                FatalProfileException ex("SAML response contained an error.");
-                annotateException(&ex, role, status);   // throws it
-            }
-        }
-    }
-
-    const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);
-    if (r1) {
-        const saml1p::Status* status = r1->getStatus();
-        if (status) {
-            const saml1p::StatusCode* sc = status->getStatusCode();
-            const xmltooling::QName* code = sc ? sc->getValue() : NULL;
-            if (code && *code != saml1p::StatusCode::SUCCESS) {
-                FatalProfileException ex("SAML response contained an error.");
-                ex.addProperty("statusCode", code->toString().c_str());
-                if (sc->getStatusCode()) {
-                    code = sc->getStatusCode()->getValue();
-                    if (code)
-                        ex.addProperty("statusCode2", code->toString().c_str());
-                }
-                if (status->getStatusMessage()) {
-                    auto_ptr_char msg(status->getStatusMessage()->getMessage());
-                    if (msg.get() && *msg.get())
-                        ex.addProperty("statusMessage", msg.get());
-                }
-                ex.raise();
-            }
-        }
-    }
-}
-
-void AbstractHandler::fillStatus(saml2p::StatusResponseType& response, const XMLCh* code, const XMLCh* subcode, const char* msg) const
-{
-    saml2p::Status* status = saml2p::StatusBuilder::buildStatus();
-    saml2p::StatusCode* scode = saml2p::StatusCodeBuilder::buildStatusCode();
-    status->setStatusCode(scode);
-    scode->setValue(code);
-    if (subcode) {
-        saml2p::StatusCode* ssubcode = saml2p::StatusCodeBuilder::buildStatusCode();
-        scode->setStatusCode(ssubcode);
-        ssubcode->setValue(subcode);
-    }
-    if (msg) {
-        pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());
-        auto_ptr_XMLCh widemsg((flag.first && flag.second) ? msg : "Error processing request.");
-        saml2p::StatusMessage* sm = saml2p::StatusMessageBuilder::buildStatusMessage();
-        status->setStatusMessage(sm);
-        sm->setMessage(widemsg.get());
-    }
-    response.setStatus(status);
-}
-
-long AbstractHandler::sendMessage(
-    const MessageEncoder& encoder,
-    XMLObject* msg,
-    const char* relayState,
-    const char* destination,
-    const saml2md::RoleDescriptor* role,
-    const Application& application,
-    HTTPResponse& httpResponse,
-    bool signIfPossible
-    ) const
-{
-    const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : NULL;
-    const PropertySet* relyingParty = application.getRelyingParty(entity);
-    pair<bool,const char*> flag = signIfPossible ? make_pair(true,(const char*)"true") : relyingParty->getString("signing");
-    if (role && flag.first &&
-        (!strcmp(flag.second, "true") ||
-            (encoder.isUserAgentPresent() && !strcmp(flag.second, "front")) ||
-            (!encoder.isUserAgentPresent() && !strcmp(flag.second, "back")))) {
-        CredentialResolver* credResolver=application.getCredentialResolver();
-        if (credResolver) {
-            Locker credLocker(credResolver);
-            const Credential* cred = NULL;
-            pair<bool,const char*> keyName = relyingParty->getString("keyName");
-            pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signingAlg");
-            if (role) {
-                MetadataCredentialCriteria mcc(*role);
-                mcc.setUsage(Credential::SIGNING_CREDENTIAL);
-                if (keyName.first)
-                    mcc.getKeyNames().insert(keyName.second);
-                if (sigalg.first)
-                    mcc.setXMLAlgorithm(sigalg.second);
-                cred = credResolver->resolve(&mcc);
-            }
-            else {
-                CredentialCriteria cc;
-                cc.setUsage(Credential::SIGNING_CREDENTIAL);
-                if (keyName.first)
-                    cc.getKeyNames().insert(keyName.second);
-                if (sigalg.first)
-                    cc.setXMLAlgorithm(sigalg.second);
-                cred = credResolver->resolve(&cc);
-            }
-            if (cred) {
-                // Signed request.
-                return encoder.encode(
-                    httpResponse,
-                    msg,
-                    destination,
-                    entity,
-                    relayState,
-                    &application,
-                    cred,
-                    sigalg.second,
-                    relyingParty->getXMLString("digestAlg").second
-                    );
-            }
-            else {
-                m_log.warn("no signing credential resolved, leaving message unsigned");
-            }
-        }
-        else {
-            m_log.warn("no credential resolver installed, leaving message unsigned");
-        }
-    }
-
-    // Unsigned request.
-    return encoder.encode(httpResponse, msg, destination, entity, relayState, &application);
-}
-
-#endif
-
-void AbstractHandler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const
-{
-    if (relayState.empty())
-        return;
-
-    // No setting means just pass it by value.
-    pair<bool,const char*> mech=getString("relayState");
-    if (!mech.first || !mech.second || !*mech.second)
-        return;
-
-    if (!strcmp(mech.second, "cookie")) {
-        // Here we store the state in a cookie and send a fixed
-        // value so we can recognize it on the way back.
-        if (relayState.find("cookie:") != 0) {
-            const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
-            pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibstate_");
-            string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;
-            // Generate a random key for the cookie name instead of the fixed name.
-            string rsKey;
-            generateRandomHex(rsKey,5);
-            shib_cookie.first = "_shibstate_" + rsKey;
-            response.setCookie(shib_cookie.first.c_str(),stateval.c_str());
-            relayState = "cookie:" + rsKey;
-        }
-    }
-    else if (strstr(mech.second,"ss:")==mech.second) {
-        if (relayState.find("ss:") != 0) {
-            mech.second+=3;
-            if (*mech.second) {
-                if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
-                    StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
-                    if (storage) {
-                        string rsKey;
-                        generateRandomHex(rsKey,5);
-                        if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))
-                            throw IOException("Attempted to insert duplicate storage key.");
-                        relayState = string(mech.second-3) + ':' + rsKey;
-                    }
-                    else {
-                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", mech.second);
-                        relayState.erase();
-                    }
-#endif
-                }
-                else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
-                    DDF out,in = DDF("set::RelayState").structure();
-                    in.addmember("id").string(mech.second);
-                    in.addmember("value").unsafe_string(relayState.c_str());
-                    DDFJanitor jin(in),jout(out);
-                    out = application.getServiceProvider().getListenerService()->send(in);
-                    if (!out.isstring())
-                        throw IOException("StorageService-backed RelayState mechanism did not return a state key.");
-                    relayState = string(mech.second-3) + ':' + out.string();
-                }
-            }
-        }
-    }
-    else
-        throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));
-}
-
-void AbstractHandler::recoverRelayState(
-    const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear
-    ) const
-{
-    SPConfig& conf = SPConfig::getConfig();
-
-    // Look for StorageService-backed state of the form "ss:SSID:key".
-    const char* state = relayState.c_str();
-    if (strstr(state,"ss:")==state) {
-        state += 3;
-        const char* key = strchr(state,':');
-        if (key) {
-            string ssid = relayState.substr(3, key - state);
-            key++;
-            if (!ssid.empty() && *key) {
-                if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
-                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
-                    if (storage) {
-                        ssid = key;
-                        if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {
-                            if (clear)
-                                storage->deleteString("RelayState",ssid.c_str());
-                            return;
-                        }
-                        else
-                            relayState.erase();
-                    }
-                    else {
-                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());
-                        relayState.erase();
-                    }
-#endif
-                }
-                else if (conf.isEnabled(SPConfig::InProcess)) {
-                    DDF out,in = DDF("get::RelayState").structure();
-                    in.addmember("id").string(ssid.c_str());
-                    in.addmember("key").string(key);
-                    in.addmember("clear").integer(clear ? 1 : 0);
-                    DDFJanitor jin(in),jout(out);
-                    out = application.getServiceProvider().getListenerService()->send(in);
-                    if (!out.isstring()) {
-                        m_log.error("StorageService-backed RelayState mechanism did not return a state value.");
-                        relayState.erase();
-                    }
-                    else {
-                        relayState = out.string();
-                        return;
-                    }
-                }
-            }
-        }
-    }
-
-    // Look for cookie-backed state of the form "cookie:key".
-    if (strstr(state,"cookie:")==state) {
-        state += 7;
-        if (*state) {
-            // Pull the value from the "relay state" cookie.
-            pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
-            relay_cookie.first = string("_shibstate_") + state;
-            state = request.getCookie(relay_cookie.first.c_str());
-            if (state && *state) {
-                // URL-decode the value.
-                char* rscopy=strdup(state);
-                XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
-                relayState = rscopy;
-                free(rscopy);
-
-                if (clear) {
-                    string exp(relay_cookie.second);
-                    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
-                    response.setCookie(relay_cookie.first.c_str(), exp.c_str());
-                }
-                return;
-            }
-        }
-
-        relayState.erase();
-    }
-
-    // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).
-    if (relayState.empty() || relayState == "default" || relayState == "cookie") {
-        pair<bool,const char*> homeURL=application.getString("homeURL");
-        if (homeURL.first)
-            relayState=homeURL.second;
-        else {
-            // Compute a URL to the root of the site.
-            int port = request.getPort();
-            const char* scheme = request.getScheme();
-            relayState = string(scheme) + "://" + request.getHostname();
-            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
-                ostringstream portstr;
-                portstr << port;
-                relayState += ":" + portstr.str();
-            }
-            relayState += '/';
-        }
-    }
-}
-
-void AbstractHandler::preservePostData(
-    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
-    ) const
-{
-#ifdef HAVE_STRCASECMP
-    if (strcasecmp(request.getMethod(), "POST")) return;
-#else
-    if (stricmp(request.getMethod(), "POST")) return;
-#endif
-
-    // No specs mean no save.
-    const PropertySet* props=application.getPropertySet("Sessions");
-    pair<bool,const char*> mech = props->getString("postData");
-    if (!mech.first) {
-        m_log.info("postData property not supplied, form data will not be preserved across SSO");
-        return;
-    }
-
-    DDF postData = getPostData(application, request);
-    if (postData.isnull())
-        return;
-
-    if (strstr(mech.second,"ss:") == mech.second) {
-        mech.second+=3;
-        if (!*mech.second) {
-            postData.destroy();
-            throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3));
-        }
-
-        string postkey;
-        if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
-            DDFJanitor postjan(postData);
-#ifndef SHIBSP_LITE
-            StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
-            if (storage) {
-                // Use a random key
-                string rsKey;
-                SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
-                rsKey = SAMLArtifact::toHex(rsKey);
-                ostringstream out;
-                out << postData;
-                if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))
-                    throw IOException("Attempted to insert duplicate storage key.");
-                postkey = string(mech.second-3) + ':' + rsKey;
-            }
-            else {
-                m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second);
-            }
-#endif
-        }
-        else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
-            DDF out,in = DDF("set::PostData").structure();
-            DDFJanitor jin(in),jout(out);
-            in.addmember("id").string(mech.second);
-            in.add(postData);
-            out = application.getServiceProvider().getListenerService()->send(in);
-            if (!out.isstring())
-                throw IOException("StorageService-backed PostData mechanism did not return a state key.");
-            postkey = string(mech.second-3) + ':' + out.string();
-        }
-
-        // Set a cookie with key info.
-        pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
-        postkey += shib_cookie.second;
-        response.setCookie(shib_cookie.first.c_str(), postkey.c_str());
-    }
-    else {
-        postData.destroy();
-        throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second));
-    }
-}
-
-DDF AbstractHandler::recoverPostData(
-    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
-    ) const
-{
-    // First we need the post recovery cookie.
-    pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
-    const char* cookie = request.getCookie(shib_cookie.first.c_str());
-    if (!cookie || !*cookie)
-        return DDF();
-
-    // Clear the cookie.
-    string exp(shib_cookie.second);
-    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
-    response.setCookie(shib_cookie.first.c_str(), exp.c_str());
-
-    // Look for StorageService-backed state of the form "ss:SSID:key".
-    const char* state = cookie;
-    if (strstr(state, "ss:") == state) {
-        state += 3;
-        const char* key = strchr(state, ':');
-        if (key) {
-            string ssid = string(cookie).substr(3, key - state);
-            key++;
-            if (!ssid.empty() && *key) {
-                SPConfig& conf = SPConfig::getConfig();
-                if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
-                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
-                    if (storage) {
-                        if (storage->readString("PostData", key, &ssid) > 0) {
-                            storage->deleteString("PostData", key);
-                            istringstream inret(ssid);
-                            DDF ret;
-                            inret >> ret;
-                            return ret;
-                        }
-                        else {
-                            m_log.error("failed to recover form post data using key (%s)", key);
-                        }
-                    }
-                    else {
-                        m_log.error("storage-backed PostData with invalid StorageService ID (%s)", ssid.c_str());
-                    }
-#endif
-                }
-                else if (conf.isEnabled(SPConfig::InProcess)) {
-                    DDF in = DDF("get::PostData").structure();
-                    DDFJanitor jin(in);
-                    in.addmember("id").string(ssid.c_str());
-                    in.addmember("key").string(key);
-                    DDF out = application.getServiceProvider().getListenerService()->send(in);
-                    if (out.islist())
-                        return out;
-                    out.destroy();
-                    m_log.error("storageService-backed PostData mechanism did not return preserved data.");
-                }
-            }
-        }
-    }
-    return DDF();
-}
-
-long AbstractHandler::sendPostResponse(
-    const Application& application, HTTPResponse& httpResponse, const char* url, DDF& postData
-    ) const
-{
-    const PropertySet* props=application.getPropertySet("Sessions");
-    pair<bool,const char*> postTemplate = props->getString("postTemplate");
-    if (!postTemplate.first)
-        throw ConfigurationException("Missing postTemplate property, unable to recreate form post.");
-
-    string fname(postTemplate.second);
-    ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
-    if (!infile)
-        throw ConfigurationException("Unable to access HTML template ($1).", params(1, fname.c_str()));
-    TemplateParameters respParam;
-    respParam.m_map["action"] = url;
-
-    // Load the parameters into objects for the template.
-    multimap<string,string>& collection = respParam.m_collectionMap["PostedData"];
-    DDF param = postData.first();
-    while (param.isstring()) {
-        collection.insert(pair<const string,string>(param.name(), (param.string() ? param.string() : "")));
-        param = postData.next();
-    }
-
-    stringstream str;
-    XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam);
-
-    pair<bool,bool> postExpire = props->getBool("postExpire");
-
-    httpResponse.setContentType("text/html");
-    if (!postExpire.first || postExpire.second) {
-        httpResponse.setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
-        httpResponse.setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
-        httpResponse.setResponseHeader("Pragma", "no-cache");
-    }
-    return httpResponse.sendResponse(str);
-}
-
-pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const
-{
-    // Decorates the name of the cookie with the relay state key, if any.
-    // Doing so gives a better assurance that the recovered data really
-    // belongs to the relayed request.
-    pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");
-    if (strstr(relayState, "cookie:") == relayState) {
-        shib_cookie.first = string("_shibpost_") + (relayState + 7);
-    }
-    else if (strstr(relayState, "ss:") == relayState) {
-        const char* pch = strchr(relayState + 3, ':');
-        if (pch)
-            shib_cookie.first = string("_shibpost_") + (pch + 1);
-    }
-    return shib_cookie;
-}
-
-DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const
-{
-    string contentType = request.getContentType();
-    if (contentType.compare("application/x-www-form-urlencoded") == 0) {
-        const PropertySet* props=application.getPropertySet("Sessions");
-        pair<bool,unsigned int> plimit = props->getUnsignedInt("postLimit");
-        if (!plimit.first)
-            plimit.second = 1024 * 1024;
-        if (plimit.second == 0 || request.getContentLength() <= plimit.second) {
-            CGIParser cgi(request);
-            pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);
-            if (params.first == params.second)
-                return DDF();
-            DDF child;
-            DDF ret = DDF("parameters").list();
-            for (; params.first != params.second; ++params.first) {
-                if (!params.first->first.empty()) {
-                    child = DDF(params.first->first.c_str()).unsafe_string(params.first->second);
-                    ret.add(child);
-                }
-            }
-            return ret;
-        }
-        else {
-            m_log.warn("POST limit exceeded, ignoring %d bytes of posted data", request.getContentLength());
-        }
-    }
-    else {
-        m_log.info("ignoring POST data with non-standard encoding (%s)", contentType.c_str());
-    }
-    return DDF();
-}
+/*\r
+ *  Copyright 2001-2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * AbstractHandler.cpp\r
+ *\r
+ * Base class for handlers based on a DOMPropertySet.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "Application.h"\r
+#include "ServiceProvider.h"\r
+#include "SPRequest.h"\r
+#include "handler/AbstractHandler.h"\r
+#include "handler/LogoutHandler.h"\r
+#include "remoting/ListenerService.h"\r
+#include "util/CGIParser.h"\r
+#include "util/SPConstants.h"\r
+#include "util/TemplateParameters.h"\r
+\r
+#include <vector>\r
+#include <fstream>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/PathResolver.h>\r
+#include <xmltooling/util/URLEncoder.h>\r
+\r
+\r
+#ifndef SHIBSP_LITE\r
+# include <saml/exceptions.h>\r
+# include <saml/SAMLConfig.h>\r
+# include <saml/binding/SAMLArtifact.h>\r
+# include <saml/saml1/core/Protocols.h>\r
+# include <saml/saml2/core/Protocols.h>\r
+# include <saml/saml2/metadata/Metadata.h>\r
+# include <saml/saml2/metadata/MetadataCredentialCriteria.h>\r
+# include <saml/util/SAMLConstants.h>\r
+# include <xmltooling/security/Credential.h>\r
+# include <xmltooling/security/CredentialResolver.h>\r
+# include <xmltooling/util/StorageService.h>\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+#else\r
+# include "lite/SAMLConstants.h"\r
+#endif\r
+\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/util/URLEncoder.h>\r
+\r
+using namespace shibsp;\r
+using namespace samlconstants;\r
+using namespace xmltooling;\r
+using namespace xercesc;\r
+using namespace std;\r
+\r
+namespace shibsp {\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML1ConsumerFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ConsumerFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2ArtifactResolutionFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory ChainingLogoutInitiatorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory LocalLogoutInitiatorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutInitiatorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2LogoutFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SAML2NameIDMgmtFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory AssertionLookupFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory MetadataGeneratorFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory StatusHandlerFactory;\r
+    SHIBSP_DLLLOCAL PluginManager< Handler,string,pair<const DOMElement*,const char*> >::Factory SessionHandlerFactory;\r
+\r
+    void SHIBSP_DLLLOCAL generateRandomHex(std::string& buf, unsigned int len) {\r
+        static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\r
+        int r;\r
+        unsigned char b1,b2;\r
+        buf.erase();\r
+        for (unsigned int i=0; i<len; i+=4) {\r
+            r = rand();\r
+            b1 = (0x00FF & r);\r
+            b2 = (0xFF00 & r)  >> 8;\r
+            buf += (DIGITS[(0xF0 & b1) >> 4 ]);\r
+            buf += (DIGITS[0x0F & b1]);\r
+            buf += (DIGITS[(0xF0 & b2) >> 4 ]);\r
+            buf += (DIGITS[0x0F & b2]);\r
+        }\r
+    }\r
+};\r
+\r
+void SHIBSP_API shibsp::registerHandlers()\r
+{\r
+    SPConfig& conf=SPConfig::getConfig();\r
+\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);\r
+    conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory);\r
+\r
+    conf.ArtifactResolutionServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2ArtifactResolutionFactory);\r
+\r
+    conf.HandlerManager.registerFactory(SAML20_BINDING_URI, AssertionLookupFactory);\r
+    conf.HandlerManager.registerFactory(METADATA_GENERATOR_HANDLER, MetadataGeneratorFactory);\r
+    conf.HandlerManager.registerFactory(STATUS_HANDLER, StatusHandlerFactory);\r
+    conf.HandlerManager.registerFactory(SESSION_HANDLER, SessionHandlerFactory);\r
+\r
+    conf.LogoutInitiatorManager.registerFactory(CHAINING_LOGOUT_INITIATOR, ChainingLogoutInitiatorFactory);\r
+    conf.LogoutInitiatorManager.registerFactory(LOCAL_LOGOUT_INITIATOR, LocalLogoutInitiatorFactory);\r
+    conf.LogoutInitiatorManager.registerFactory(SAML2_LOGOUT_INITIATOR, SAML2LogoutInitiatorFactory);\r
+    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2LogoutFactory);\r
+    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2LogoutFactory);\r
+    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2LogoutFactory);\r
+    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2LogoutFactory);\r
+    conf.SingleLogoutServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2LogoutFactory);\r
+\r
+    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_SOAP, SAML2NameIDMgmtFactory);\r
+    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_REDIRECT, SAML2NameIDMgmtFactory);\r
+    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2NameIDMgmtFactory);\r
+    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2NameIDMgmtFactory);\r
+    conf.ManageNameIDServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2NameIDMgmtFactory);\r
+}\r
+\r
+Handler::Handler()\r
+{\r
+}\r
+\r
+Handler::~Handler()\r
+{\r
+}\r
+\r
+AbstractHandler::AbstractHandler(\r
+    const DOMElement* e, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper\r
+    ) : m_log(log), m_configNS(shibspconstants::SHIB2SPCONFIG_NS) {\r
+    load(e,NULL,filter,remapper);\r
+}\r
+\r
+AbstractHandler::~AbstractHandler()\r
+{\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+\r
+const char* Handler::getType() const\r
+{\r
+    return getString("type").second;\r
+}\r
+\r
+void AbstractHandler::checkError(const XMLObject* response, const saml2md::RoleDescriptor* role) const\r
+{\r
+    const saml2p::StatusResponseType* r2 = dynamic_cast<const saml2p::StatusResponseType*>(response);\r
+    if (r2) {\r
+        const saml2p::Status* status = r2->getStatus();\r
+        if (status) {\r
+            const saml2p::StatusCode* sc = status->getStatusCode();\r
+            const XMLCh* code = sc ? sc->getValue() : NULL;\r
+            if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {\r
+                FatalProfileException ex("SAML response contained an error.");\r
+                annotateException(&ex, role, status);   // throws it\r
+            }\r
+        }\r
+    }\r
+\r
+    const saml1p::Response* r1 = dynamic_cast<const saml1p::Response*>(response);\r
+    if (r1) {\r
+        const saml1p::Status* status = r1->getStatus();\r
+        if (status) {\r
+            const saml1p::StatusCode* sc = status->getStatusCode();\r
+            const xmltooling::QName* code = sc ? sc->getValue() : NULL;\r
+            if (code && *code != saml1p::StatusCode::SUCCESS) {\r
+                FatalProfileException ex("SAML response contained an error.");\r
+                ex.addProperty("statusCode", code->toString().c_str());\r
+                if (sc->getStatusCode()) {\r
+                    code = sc->getStatusCode()->getValue();\r
+                    if (code)\r
+                        ex.addProperty("statusCode2", code->toString().c_str());\r
+                }\r
+                if (status->getStatusMessage()) {\r
+                    auto_ptr_char msg(status->getStatusMessage()->getMessage());\r
+                    if (msg.get() && *msg.get())\r
+                        ex.addProperty("statusMessage", msg.get());\r
+                }\r
+                ex.raise();\r
+            }\r
+        }\r
+    }\r
+}\r
+\r
+void AbstractHandler::fillStatus(saml2p::StatusResponseType& response, const XMLCh* code, const XMLCh* subcode, const char* msg) const\r
+{\r
+    saml2p::Status* status = saml2p::StatusBuilder::buildStatus();\r
+    saml2p::StatusCode* scode = saml2p::StatusCodeBuilder::buildStatusCode();\r
+    status->setStatusCode(scode);\r
+    scode->setValue(code);\r
+    if (subcode) {\r
+        saml2p::StatusCode* ssubcode = saml2p::StatusCodeBuilder::buildStatusCode();\r
+        scode->setStatusCode(ssubcode);\r
+        ssubcode->setValue(subcode);\r
+    }\r
+    if (msg) {\r
+        pair<bool,bool> flag = getBool("detailedErrors", m_configNS.get());\r
+        auto_ptr_XMLCh widemsg((flag.first && flag.second) ? msg : "Error processing request.");\r
+        saml2p::StatusMessage* sm = saml2p::StatusMessageBuilder::buildStatusMessage();\r
+        status->setStatusMessage(sm);\r
+        sm->setMessage(widemsg.get());\r
+    }\r
+    response.setStatus(status);\r
+}\r
+\r
+long AbstractHandler::sendMessage(\r
+    const MessageEncoder& encoder,\r
+    XMLObject* msg,\r
+    const char* relayState,\r
+    const char* destination,\r
+    const saml2md::RoleDescriptor* role,\r
+    const Application& application,\r
+    HTTPResponse& httpResponse,\r
+    bool signIfPossible\r
+    ) const\r
+{\r
+    const EntityDescriptor* entity = role ? dynamic_cast<const EntityDescriptor*>(role->getParent()) : NULL;\r
+    const PropertySet* relyingParty = application.getRelyingParty(entity);\r
+    pair<bool,const char*> flag = signIfPossible ? make_pair(true,(const char*)"true") : relyingParty->getString("signing");\r
+    if (role && flag.first &&\r
+        (!strcmp(flag.second, "true") ||\r
+            (encoder.isUserAgentPresent() && !strcmp(flag.second, "front")) ||\r
+            (!encoder.isUserAgentPresent() && !strcmp(flag.second, "back")))) {\r
+        CredentialResolver* credResolver=application.getCredentialResolver();\r
+        if (credResolver) {\r
+            Locker credLocker(credResolver);\r
+            const Credential* cred = NULL;\r
+            pair<bool,const char*> keyName = relyingParty->getString("keyName");\r
+            pair<bool,const XMLCh*> sigalg = relyingParty->getXMLString("signingAlg");\r
+            if (role) {\r
+                MetadataCredentialCriteria mcc(*role);\r
+                mcc.setUsage(Credential::SIGNING_CREDENTIAL);\r
+                if (keyName.first)\r
+                    mcc.getKeyNames().insert(keyName.second);\r
+                if (sigalg.first)\r
+                    mcc.setXMLAlgorithm(sigalg.second);\r
+                cred = credResolver->resolve(&mcc);\r
+            }\r
+            else {\r
+                CredentialCriteria cc;\r
+                cc.setUsage(Credential::SIGNING_CREDENTIAL);\r
+                if (keyName.first)\r
+                    cc.getKeyNames().insert(keyName.second);\r
+                if (sigalg.first)\r
+                    cc.setXMLAlgorithm(sigalg.second);\r
+                cred = credResolver->resolve(&cc);\r
+            }\r
+            if (cred) {\r
+                // Signed request.\r
+                return encoder.encode(\r
+                    httpResponse,\r
+                    msg,\r
+                    destination,\r
+                    entity,\r
+                    relayState,\r
+                    &application,\r
+                    cred,\r
+                    sigalg.second,\r
+                    relyingParty->getXMLString("digestAlg").second\r
+                    );\r
+            }\r
+            else {\r
+                m_log.warn("no signing credential resolved, leaving message unsigned");\r
+            }\r
+        }\r
+        else {\r
+            m_log.warn("no credential resolver installed, leaving message unsigned");\r
+        }\r
+    }\r
+\r
+    // Unsigned request.\r
+    return encoder.encode(httpResponse, msg, destination, entity, relayState, &application);\r
+}\r
+\r
+#endif\r
+\r
+void AbstractHandler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const\r
+{\r
+    if (relayState.empty())\r
+        return;\r
+\r
+    // No setting means just pass it by value.\r
+    pair<bool,const char*> mech=getString("relayState");\r
+    if (!mech.first || !mech.second || !*mech.second)\r
+        return;\r
+\r
+    if (!strcmp(mech.second, "cookie")) {\r
+        // Here we store the state in a cookie and send a fixed\r
+        // value so we can recognize it on the way back.\r
+        if (relayState.find("cookie:") != 0) {\r
+            const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();\r
+            pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibstate_");\r
+            string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;\r
+            // Generate a random key for the cookie name instead of the fixed name.\r
+            string rsKey;\r
+            generateRandomHex(rsKey,5);\r
+            shib_cookie.first = "_shibstate_" + rsKey;\r
+            response.setCookie(shib_cookie.first.c_str(),stateval.c_str());\r
+            relayState = "cookie:" + rsKey;\r
+        }\r
+    }\r
+    else if (strstr(mech.second,"ss:")==mech.second) {\r
+        if (relayState.find("ss:") != 0) {\r
+            mech.second+=3;\r
+            if (*mech.second) {\r
+                if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+                    StorageService* storage = application.getServiceProvider().getStorageService(mech.second);\r
+                    if (storage) {\r
+                        string rsKey;\r
+                        generateRandomHex(rsKey,5);\r
+                        if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))\r
+                            throw IOException("Attempted to insert duplicate storage key.");\r
+                        relayState = string(mech.second-3) + ':' + rsKey;\r
+                    }\r
+                    else {\r
+                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", mech.second);\r
+                        relayState.erase();\r
+                    }\r
+#endif\r
+                }\r
+                else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+                    DDF out,in = DDF("set::RelayState").structure();\r
+                    in.addmember("id").string(mech.second);\r
+                    in.addmember("value").unsafe_string(relayState.c_str());\r
+                    DDFJanitor jin(in),jout(out);\r
+                    out = application.getServiceProvider().getListenerService()->send(in);\r
+                    if (!out.isstring())\r
+                        throw IOException("StorageService-backed RelayState mechanism did not return a state key.");\r
+                    relayState = string(mech.second-3) + ':' + out.string();\r
+                }\r
+            }\r
+        }\r
+    }\r
+    else\r
+        throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));\r
+}\r
+\r
+void AbstractHandler::recoverRelayState(\r
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear\r
+    ) const\r
+{\r
+    SPConfig& conf = SPConfig::getConfig();\r
+\r
+    // Look for StorageService-backed state of the form "ss:SSID:key".\r
+    const char* state = relayState.c_str();\r
+    if (strstr(state,"ss:")==state) {\r
+        state += 3;\r
+        const char* key = strchr(state,':');\r
+        if (key) {\r
+            string ssid = relayState.substr(3, key - state);\r
+            key++;\r
+            if (!ssid.empty() && *key) {\r
+                if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());\r
+                    if (storage) {\r
+                        ssid = key;\r
+                        if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {\r
+                            if (clear)\r
+                                storage->deleteString("RelayState",ssid.c_str());\r
+                            return;\r
+                        }\r
+                        else\r
+                            relayState.erase();\r
+                    }\r
+                    else {\r
+                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());\r
+                        relayState.erase();\r
+                    }\r
+#endif\r
+                }\r
+                else if (conf.isEnabled(SPConfig::InProcess)) {\r
+                    DDF out,in = DDF("get::RelayState").structure();\r
+                    in.addmember("id").string(ssid.c_str());\r
+                    in.addmember("key").string(key);\r
+                    in.addmember("clear").integer(clear ? 1 : 0);\r
+                    DDFJanitor jin(in),jout(out);\r
+                    out = application.getServiceProvider().getListenerService()->send(in);\r
+                    if (!out.isstring()) {\r
+                        m_log.error("StorageService-backed RelayState mechanism did not return a state value.");\r
+                        relayState.erase();\r
+                    }\r
+                    else {\r
+                        relayState = out.string();\r
+                        return;\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    // Look for cookie-backed state of the form "cookie:key".\r
+    if (strstr(state,"cookie:")==state) {\r
+        state += 7;\r
+        if (*state) {\r
+            // Pull the value from the "relay state" cookie.\r
+            pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");\r
+            relay_cookie.first = string("_shibstate_") + state;\r
+            state = request.getCookie(relay_cookie.first.c_str());\r
+            if (state && *state) {\r
+                // URL-decode the value.\r
+                char* rscopy=strdup(state);\r
+                XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);\r
+                relayState = rscopy;\r
+                free(rscopy);\r
+\r
+                if (clear) {\r
+                    string exp(relay_cookie.second);\r
+                    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";\r
+                    response.setCookie(relay_cookie.first.c_str(), exp.c_str());\r
+                }\r
+                return;\r
+            }\r
+        }\r
+\r
+        relayState.erase();\r
+    }\r
+\r
+    // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).\r
+    if (relayState.empty() || relayState == "default" || relayState == "cookie") {\r
+        pair<bool,const char*> homeURL=application.getString("homeURL");\r
+        if (homeURL.first)\r
+            relayState=homeURL.second;\r
+        else {\r
+            // Compute a URL to the root of the site.\r
+            int port = request.getPort();\r
+            const char* scheme = request.getScheme();\r
+            relayState = string(scheme) + "://" + request.getHostname();\r
+            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {\r
+                ostringstream portstr;\r
+                portstr << port;\r
+                relayState += ":" + portstr.str();\r
+            }\r
+            relayState += '/';\r
+        }\r
+    }\r
+}\r
+\r
+void AbstractHandler::preservePostData(\r
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState\r
+    ) const\r
+{\r
+#ifdef HAVE_STRCASECMP\r
+    if (strcasecmp(request.getMethod(), "POST")) return;\r
+#else\r
+    if (stricmp(request.getMethod(), "POST")) return;\r
+#endif\r
+\r
+    // No specs mean no save.\r
+    const PropertySet* props=application.getPropertySet("Sessions");\r
+    pair<bool,const char*> mech = props->getString("postData");\r
+    if (!mech.first) {\r
+        m_log.info("postData property not supplied, form data will not be preserved across SSO");\r
+        return;\r
+    }\r
+\r
+    DDF postData = getPostData(application, request);\r
+    if (postData.isnull())\r
+        return;\r
+\r
+    if (strstr(mech.second,"ss:") == mech.second) {\r
+        mech.second+=3;\r
+        if (!*mech.second) {\r
+            postData.destroy();\r
+            throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3));\r
+        }\r
+\r
+        string postkey;\r
+        if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {\r
+            DDFJanitor postjan(postData);\r
+#ifndef SHIBSP_LITE\r
+            StorageService* storage = application.getServiceProvider().getStorageService(mech.second);\r
+            if (storage) {\r
+                // Use a random key\r
+                string rsKey;\r
+                SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+                rsKey = SAMLArtifact::toHex(rsKey);\r
+                ostringstream out;\r
+                out << postData;\r
+                if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600))\r
+                    throw IOException("Attempted to insert duplicate storage key.");\r
+                postkey = string(mech.second-3) + ':' + rsKey;\r
+            }\r
+            else {\r
+                m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second);\r
+            }\r
+#endif\r
+        }\r
+        else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+            DDF out,in = DDF("set::PostData").structure();\r
+            DDFJanitor jin(in),jout(out);\r
+            in.addmember("id").string(mech.second);\r
+            in.add(postData);\r
+            out = application.getServiceProvider().getListenerService()->send(in);\r
+            if (!out.isstring())\r
+                throw IOException("StorageService-backed PostData mechanism did not return a state key.");\r
+            postkey = string(mech.second-3) + ':' + out.string();\r
+        }\r
+\r
+        // Set a cookie with key info.\r
+        pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);\r
+        postkey += shib_cookie.second;\r
+        response.setCookie(shib_cookie.first.c_str(), postkey.c_str());\r
+    }\r
+    else {\r
+        postData.destroy();\r
+        throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second));\r
+    }\r
+}\r
+\r
+DDF AbstractHandler::recoverPostData(\r
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState\r
+    ) const\r
+{\r
+    // First we need the post recovery cookie.\r
+    pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);\r
+    const char* cookie = request.getCookie(shib_cookie.first.c_str());\r
+    if (!cookie || !*cookie)\r
+        return DDF();\r
+\r
+    // Clear the cookie.\r
+    string exp(shib_cookie.second);\r
+    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";\r
+    response.setCookie(shib_cookie.first.c_str(), exp.c_str());\r
+\r
+    // Look for StorageService-backed state of the form "ss:SSID:key".\r
+    const char* state = cookie;\r
+    if (strstr(state, "ss:") == state) {\r
+        state += 3;\r
+        const char* key = strchr(state, ':');\r
+        if (key) {\r
+            string ssid = string(cookie).substr(3, key - state);\r
+            key++;\r
+            if (!ssid.empty() && *key) {\r
+                SPConfig& conf = SPConfig::getConfig();\r
+                if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());\r
+                    if (storage) {\r
+                        if (storage->readString("PostData", key, &ssid) > 0) {\r
+                            storage->deleteString("PostData", key);\r
+                            istringstream inret(ssid);\r
+                            DDF ret;\r
+                            inret >> ret;\r
+                            return ret;\r
+                        }\r
+                        else {\r
+                            m_log.error("failed to recover form post data using key (%s)", key);\r
+                        }\r
+                    }\r
+                    else {\r
+                        m_log.error("storage-backed PostData with invalid StorageService ID (%s)", ssid.c_str());\r
+                    }\r
+#endif\r
+                }\r
+                else if (conf.isEnabled(SPConfig::InProcess)) {\r
+                    DDF in = DDF("get::PostData").structure();\r
+                    DDFJanitor jin(in);\r
+                    in.addmember("id").string(ssid.c_str());\r
+                    in.addmember("key").string(key);\r
+                    DDF out = application.getServiceProvider().getListenerService()->send(in);\r
+                    if (out.islist())\r
+                        return out;\r
+                    out.destroy();\r
+                    m_log.error("storageService-backed PostData mechanism did not return preserved data.");\r
+                }\r
+            }\r
+        }\r
+    }\r
+    return DDF();\r
+}\r
+\r
+long AbstractHandler::sendPostResponse(\r
+    const Application& application, HTTPResponse& httpResponse, const char* url, DDF& postData\r
+    ) const\r
+{\r
+    HTTPResponse::sanitizeURL(url);\r
+\r
+    const PropertySet* props=application.getPropertySet("Sessions");\r
+    pair<bool,const char*> postTemplate = props->getString("postTemplate");\r
+    if (!postTemplate.first)\r
+        throw ConfigurationException("Missing postTemplate property, unable to recreate form post.");\r
+\r
+    string fname(postTemplate.second);\r
+    ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());\r
+    if (!infile)\r
+        throw ConfigurationException("Unable to access HTML template ($1).", params(1, fname.c_str()));\r
+    TemplateParameters respParam;\r
+    respParam.m_map["action"] = url;\r
+\r
+    // Load the parameters into objects for the template.\r
+    multimap<string,string>& collection = respParam.m_collectionMap["PostedData"];\r
+    DDF param = postData.first();\r
+    while (!param.isnull()) {\r
+        collection.insert(pair<const string,string>(param.name(), (param.string() ? param.string() : "")));\r
+        param = postData.next();\r
+    }\r
+\r
+    stringstream str;\r
+    XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, respParam);\r
+\r
+    pair<bool,bool> postExpire = props->getBool("postExpire");\r
+\r
+    httpResponse.setContentType("text/html");\r
+    if (!postExpire.first || postExpire.second) {\r
+        httpResponse.setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");\r
+        httpResponse.setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");\r
+        httpResponse.setResponseHeader("Pragma", "no-cache");\r
+    }\r
+    return httpResponse.sendResponse(str);\r
+}\r
+\r
+pair<string,const char*> AbstractHandler::getPostCookieNameProps(const Application& app, const char* relayState) const\r
+{\r
+    // Decorates the name of the cookie with the relay state key, if any.\r
+    // Doing so gives a better assurance that the recovered data really\r
+    // belongs to the relayed request.\r
+    pair<string,const char*> shib_cookie=app.getCookieNameProps("_shibpost_");\r
+    if (strstr(relayState, "cookie:") == relayState) {\r
+        shib_cookie.first = string("_shibpost_") + (relayState + 7);\r
+    }\r
+    else if (strstr(relayState, "ss:") == relayState) {\r
+        const char* pch = strchr(relayState + 3, ':');\r
+        if (pch)\r
+            shib_cookie.first = string("_shibpost_") + (pch + 1);\r
+    }\r
+    return shib_cookie;\r
+}\r
+\r
+DDF AbstractHandler::getPostData(const Application& application, const HTTPRequest& request) const\r
+{\r
+    string contentType = request.getContentType();\r
+    if (contentType.compare("application/x-www-form-urlencoded") == 0) {\r
+        const PropertySet* props=application.getPropertySet("Sessions");\r
+        pair<bool,unsigned int> plimit = props->getUnsignedInt("postLimit");\r
+        if (!plimit.first)\r
+            plimit.second = 1024 * 1024;\r
+        if (plimit.second == 0 || request.getContentLength() <= plimit.second) {\r
+            CGIParser cgi(request);\r
+            pair<CGIParser::walker,CGIParser::walker> params = cgi.getParameters(NULL);\r
+            if (params.first == params.second)\r
+                return DDF("parameters").list();\r
+            DDF child;\r
+            DDF ret = DDF("parameters").list();\r
+            for (; params.first != params.second; ++params.first) {\r
+                if (!params.first->first.empty()) {\r
+                    child = DDF(params.first->first.c_str()).unsafe_string(params.first->second);\r
+                    ret.add(child);\r
+                }\r
+            }\r
+            return ret;\r
+        }\r
+        else {\r
+            m_log.warn("POST limit exceeded, ignoring %d bytes of posted data", request.getContentLength());\r
+        }\r
+    }\r
+    else {\r
+        m_log.info("ignoring POST data with non-standard encoding (%s)", contentType.c_str());\r
+    }\r
+    return DDF();\r
+}\r
index 52f747b..f88ba99 100644 (file)
  */
 
 #include "internal.h"
-#include "Application.h"
 #include "exceptions.h"
+#include "Application.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AssertionConsumerService.h"
 #include "util/SPConstants.h"
 
 # include "attribute/resolver/ResolutionContext.h"
 # include "metadata/MetadataProviderCriteria.h"
 # include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml1/core/Assertions.h>
+# include <saml/saml2/metadata/Metadata.h>
 # include <saml/util/CommonDomainCookie.h>
 using namespace samlconstants;
 using opensaml::saml2md::MetadataProvider;
@@ -56,8 +59,9 @@ using namespace opensaml;
 using namespace xmltooling;
 using namespace std;
 
-AssertionConsumerService::AssertionConsumerService(const DOMElement* e, const char* appId, Category& log)
-    : AbstractHandler(e, log)
+AssertionConsumerService::AssertionConsumerService(
+    const DOMElement* e, const char* appId, Category& log, DOMNodeFilter* filter, const map<string,string>* remapper
+    ) : AbstractHandler(e, log, filter, remapper)
 #ifndef SHIBSP_LITE
         ,m_decoder(NULL), m_role(samlconstants::SAML20MD_NS, opensaml::saml2md::IDPSSODescriptor::LOCAL_NAME)
 #endif
@@ -223,6 +227,11 @@ void AssertionConsumerService::checkAddress(const Application& application, cons
 
 #ifndef SHIBSP_LITE
 
+const char* AssertionConsumerService::getType() const
+{
+    return "AssertionConsumerService";
+}
+
 void AssertionConsumerService::generateMetadata(SPSSODescriptor& role, const char* handlerURL) const
 {
     const char* loc = getString("Location").second;
index adeb711..d842763 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include "internal.h"
-#include "Application.h"
 #include "exceptions.h"
+#include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCacheEx.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
 #include "util/SPConstants.h"
 
+#ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
+# include <saml/Assertion.h>
+# include <xmltooling/util/XMLHelper.h>
+using namespace opensaml;
+#endif
+
 using namespace shibspconstants;
 using namespace shibsp;
-using namespace opensaml;
 using namespace xmltooling;
 using namespace std;
 
index 6850bec..47345c7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCache.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/LogoutHandler.h"
 
@@ -102,16 +103,15 @@ pair<bool,long> LocalLogoutInitiator::run(SPRequest& request, bool isHandler) co
     if (!session_id.empty()) {
         // Do back channel notification.
         vector<string> sessions(1, session_id);
-        if (!notifyBackChannel(app, request.getRequestURL(), sessions, true)) {
-            app.getServiceProvider().getSessionCache()->remove(app, request, &request);
-            return sendLogoutPage(app, request, request, true, "Partial logout failure.");
-        }
-        request.getServiceProvider().getSessionCache()->remove(app, request, &request);
+        bool result = notifyBackChannel(app, request.getRequestURL(), sessions, true);
+        app.getServiceProvider().getSessionCache()->remove(app, request, &request);
+        if (!result)
+            return sendLogoutPage(app, request, request, "partial");
     }
 
     // Route back to return location specified, or use the local template.
     const char* dest = request.getParameter("return");
     if (dest)
         return make_pair(true, request.sendRedirect(dest));
-    return sendLogoutPage(app, request, request, true, "Logout was successful.");
+    return sendLogoutPage(app, request, request, "local");
 }
index dfa43ed..5d6b087 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCache.h"
+#include "SPRequest.h"
 #include "handler/LogoutHandler.h"
 #include "util/TemplateParameters.h"
 
@@ -37,33 +38,46 @@ using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
+LogoutHandler::LogoutHandler() : m_initiator(true)
+{
+}
+
+LogoutHandler::~LogoutHandler()
+{
+}
+
 pair<bool,long> LogoutHandler::sendLogoutPage(
     const Application& application, const HTTPRequest& request, HTTPResponse& response, bool local, const char* status
     ) const
 {
+    return sendLogoutPage(application, request, response, local ? "local" : "global");
+}
+
+pair<bool,long> LogoutHandler::sendLogoutPage(
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* type
+    ) const
+{
+    string tname = string(type) + "Logout";
     const PropertySet* props = application.getPropertySet("Errors");
-    pair<bool,const char*> prop = props ? props->getString(local ? "localLogout" : "globalLogout") : pair<bool,const char*>(false,NULL);
-    if (prop.first) {
-        response.setContentType("text/html");
-        response.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
-        response.setResponseHeader("Cache-Control","private,no-store,no-cache");
-        string fname(prop.second);
-        ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
-        if (!infile)
-            throw ConfigurationException("Unable to access $1 HTML template.", params(1,local ? "localLogout" : "globalLogout"));
-        TemplateParameters tp;
-        tp.m_request = &request;
-        tp.setPropertySet(props);
-        if (status)
-            tp.m_map["logoutStatus"] = status;
-        stringstream str;
-        XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp);
-        return make_pair(true,response.sendResponse(str));
+    pair<bool,const char*> prop = props ? props->getString(tname.c_str()) : pair<bool,const char*>(false,NULL);
+    if (!prop.first) {
+        tname += ".html";
+        prop.second = tname.c_str();
     }
-    prop = application.getString("homeURL");
-    if (!prop.first)
-        prop.second = "/";
-    return make_pair(true,response.sendRedirect(prop.second));
+    response.setContentType("text/html");
+    response.setResponseHeader("Expires","01-Jan-1997 12:00:00 GMT");
+    response.setResponseHeader("Cache-Control","private,no-store,no-cache");
+    string fname(prop.second);
+    ifstream infile(XMLToolingConfig::getConfig().getPathResolver()->resolve(fname, PathResolver::XMLTOOLING_CFG_FILE).c_str());
+    if (!infile)
+        throw ConfigurationException("Unable to access $1 HTML template.", params(1,prop.second));
+    TemplateParameters tp;
+    tp.m_request = &request;
+    tp.setPropertySet(props);
+    tp.m_map["logoutStatus"] = "Logout completed successfully.";  // Backward compatibility.
+    stringstream str;
+    XMLToolingConfig::getConfig().getTemplateEngine()->run(infile, str, tp);
+    return make_pair(true,response.sendResponse(str));
 }
 
 pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
index 2a847cb..c89e8ce 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "Application.h"
 #include "exceptions.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
 
 #ifndef SHIBSP_LITE
 # include "metadata/MetadataProviderCriteria.h"
+# include <saml/exceptions.h>
+# include <saml/SAMLConfig.h>
+# include <saml/signature/ContentReference.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
+# include <xmltooling/XMLToolingConfig.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/security/CredentialCriteria.h>
+# include <xmltooling/signature/Signature.h>
+# include <xmltooling/util/ParserPool.h>
 # include <xmltooling/util/PathResolver.h>
+# include <xercesc/framework/LocalFileInputSource.hpp>
+# include <xercesc/framework/Wrapper4InputSource.hpp>
 #endif
 
-#include <xercesc/framework/LocalFileInputSource.hpp>
-#include <xercesc/framework/Wrapper4InputSource.hpp>
 
 using namespace shibsp;
 #ifndef SHIBSP_LITE
@@ -250,6 +261,9 @@ pair<bool,long> MetadataGenerator::processMessage(
         entity = EntityDescriptorBuilder::buildEntityDescriptor();
     }
 
+    if (!entity->getID())
+        entity->setID(SAMLConfig::getConfig().generateIdentifier());
+
     auto_ptr<EntityDescriptor> wrapper(entity);
     pair<bool,unsigned int> cache = getUnsignedInt("cacheDuration");
     if (cache.first) {
index 2ee35a1..93f21df 100644 (file)
@@ -24,6 +24,7 @@
 #include "Application.h"
 #include "exceptions.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/RemotedHandler.h"
 
 #include <algorithm>
@@ -227,6 +228,10 @@ void RemotedHandler::setAddress(const char* address)
     }
 }
 
+RemotedHandler::RemotedHandler()
+{
+}
+
 RemotedHandler::~RemotedHandler()
 {
     SPConfig& conf = SPConfig::getConfig();
index 239d7d2..88ab9c0 100644 (file)
 #include "handler/AssertionConsumerService.h"
 
 #ifndef SHIBSP_LITE
-# include "exceptions.h"
 # include "Application.h"
 # include "ServiceProvider.h"
 # include "SessionCache.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
+# include <saml/binding/SecurityPolicy.h>
+# include <saml/binding/SecurityPolicyRule.h>
 # include <saml/saml1/core/Assertions.h>
 # include <saml/saml1/core/Protocols.h>
 # include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/io/HTTPRequest.h>
+# include <xmltooling/util/DateTime.h>
 using namespace opensaml::saml1;
 using namespace opensaml::saml1p;
 using namespace opensaml;
index 6b98392..6e609a3 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  */
 
 #include "internal.h"
-#include "Application.h"
 #include "exceptions.h"
+#include "Application.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
 #include "util/SPConstants.h"
 
 #ifndef SHIBSP_LITE
 # include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/binding/ArtifactMap.h>
 # include <saml/binding/MessageEncoder.h>
@@ -41,6 +43,7 @@
 using namespace opensaml::saml2md;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2;
+using namespace opensaml;
 using namespace samlconstants;
 #endif
 
@@ -48,7 +51,6 @@ using namespace samlconstants;
 
 using namespace shibspconstants;
 using namespace shibsp;
-using namespace opensaml;
 using namespace soap11;
 using namespace xmltooling;
 using namespace std;
index 532c0ac..1c7af13 100644 (file)
 #include "handler/AssertionConsumerService.h"
 
 #ifndef SHIBSP_LITE
-# include "exceptions.h"
 # include "Application.h"
 # include "ServiceProvider.h"
 # include "SessionCache.h"
 # include "attribute/resolver/ResolutionContext.h"
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
+# include <saml/binding/SecurityPolicyRule.h>
 # include <saml/saml2/core/Protocols.h>
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 # include <saml/saml2/profile/SAML2AssertionPolicy.h>
+# include <xmltooling/XMLToolingConfig.h>
+# include <xmltooling/io/HTTPRequest.h>
+# include <xmltooling/util/DateTime.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
index 9a2e71a..d6931ce 100644 (file)
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "Application.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/LogoutHandler.h"
 #include "util/SPConstants.h"
 # include "metadata/MetadataProviderCriteria.h"
 # include "util/TemplateParameters.h"
 # include <fstream>
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
 # include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 # include <xmltooling/util/URLEncoder.h>
 using namespace opensaml::saml2;
@@ -531,11 +534,18 @@ pair<bool,long> SAML2Logout::doRequest(const Application& application, const HTT
         // If relay state is set, recover the original return URL.
         if (!relayState.empty())
             recoverRelayState(application, request, response, relayState);
+
+        // Check for partial logout.
+        const StatusCode* sc = logoutResponse->getStatus() ? logoutResponse->getStatus()->getStatusCode() : NULL;
+        sc = sc ? sc->getStatusCode() : NULL;
+        if (sc && XMLString::equals(sc->getValue(), StatusCode::PARTIAL_LOGOUT))
+            return sendLogoutPage(application, request, response, "partial");
+
         if (!relayState.empty())
             return make_pair(true, response.sendRedirect(relayState.c_str()));
 
-        // Return template for completion of global logout, or redirect to homeURL.
-        return sendLogoutPage(application, request, response, false, "Global logout completed.");
+        // Return template for completion of logout.
+        return sendLogoutPage(application, request, response, "global");
     }
 
     FatalProfileException ex("Incoming message was not a samlp:LogoutRequest or samlp:LogoutResponse.");
index 249eb8f..24b8bfa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "Application.h"
 #include "ServiceProvider.h"
 #include "SessionCache.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/LogoutHandler.h"
 
 #ifndef SHIBSP_LITE
 # include "binding/SOAPClient.h"
 # include "metadata/MetadataProviderCriteria.h"
+# include "security/SecurityPolicy.h"
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
 # include <saml/saml2/binding/SAML2SOAPClient.h>
 # include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/signature/ContentReference.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/signature/Signature.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
@@ -282,7 +289,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
     if (!notifyBackChannel(application, httpRequest.getRequestURL(), sessions, false)) {
         session->unlock();
         application.getServiceProvider().getSessionCache()->remove(application, httpRequest, &httpResponse);
-        return sendLogoutPage(application, httpRequest, httpResponse, true, "Partial logout failure.");
+        return sendLogoutPage(application, httpRequest, httpResponse, "partial");
     }
 
 #ifndef SHIBSP_LITE
@@ -317,7 +324,7 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
             }
         }
         if (!ep || !encoder) {
-            m_log.warn("no compatible front channel SingleLogoutService, trying back channel...");
+            m_log.debug("no compatible front channel SingleLogoutService, trying back channel...");
             shibsp::SecurityPolicy policy(application);
             shibsp::SOAPClient soaper(policy);
             MetadataCredentialCriteria mcc(*role);
@@ -346,27 +353,32 @@ pair<bool,long> SAML2LogoutInitiator::doRequest(
                 }
             }
 
+            // No answer at all?
             if (!logoutResponse) {
-                ret = sendLogoutPage(
-                    application, httpRequest, httpResponse, false,
-                    endpoints.empty() ?
-                        "Identity provider does not support SAML 2 Single Logout protocol." :
-                            "Identity provider did not respond to logout request."
-                    );
+                if (endpoints.empty())
+                    m_log.info("IdP doesn't support single logout protocol over a compatible binding");
+                else
+                    m_log.warn("IdP didn't respond to logout request");
+                ret = sendLogoutPage(application, httpRequest, httpResponse, "partial");
             }
-            else if (!logoutResponse->getStatus() || !logoutResponse->getStatus()->getStatusCode() ||
-                   !XMLString::equals(logoutResponse->getStatus()->getStatusCode()->getValue(), saml2p::StatusCode::SUCCESS)) {
-                delete logoutResponse;
-                ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Identity provider returned a SAML error in response to logout request.");
+
+            // Check the status, looking for non-success or a partial logout code.
+            const StatusCode* sc = logoutResponse->getStatus() ? logoutResponse->getStatus()->getStatusCode() : NULL;
+            bool partial = (!sc || !XMLString::equals(sc->getValue(), StatusCode::SUCCESS));
+            if (!partial) {
+                // Success, but still need to check for partial.
+                partial = XMLString::equals(sc->getStatusCode()->getValue(), StatusCode::PARTIAL_LOGOUT);
             }
+            delete logoutResponse;
+            if (partial)
+                ret = sendLogoutPage(application, httpRequest, httpResponse, "partial");
             else {
-                delete logoutResponse;
                 const char* returnloc = httpRequest.getParameter("return");
                 if (returnloc) {
                     ret.second = httpResponse.sendRedirect(returnloc);
                     ret.first = true;
                 }
-                ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Logout completed successfully.");
+                ret = sendLogoutPage(application, httpRequest, httpResponse, "global");
             }
 
             if (session) {
index 3af13a5..e285ebb 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #include "exceptions.h"
 #include "Application.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
 #include "util/SPConstants.h"
 # include "security/SecurityPolicy.h"
 # include "util/TemplateParameters.h"
 # include <fstream>
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
 # include <saml/saml2/core/Protocols.h>
 # include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
 # include <xmltooling/util/URLEncoder.h>
 using namespace opensaml::saml2;
index ae14e44..87a3750 100644 (file)
 # include <saml/saml2/metadata/EndpointManager.h>
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/MetadataCredentialCriteria.h>
+# include <saml/util/SAMLConstants.h>
 using namespace opensaml::saml2;
 using namespace opensaml::saml2p;
 using namespace opensaml::saml2md;
 #else
+# include "lite/SAMLConstants.h"
 #include <xercesc/util/XMLUniDefs.hpp>
 #endif
 
@@ -90,6 +92,8 @@ namespace shibsp {
             bool forceAuthn,
             const char* authnContextClassRef,
             const char* authnContextComparison,
+            const char* NameIDFormat,
+            const char* SPNameQualifier,
             string& relayState
             ) const;
 
@@ -119,7 +123,7 @@ namespace shibsp {
 };
 
 SAML2SessionInitiator::SAML2SessionInitiator(const DOMElement* e, const char* appId)
-    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2")), m_appId(appId),
+    : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.SAML2"), NULL, &m_remapper), m_appId(appId),
         m_paosNS(samlconstants::PAOS_NS), m_ecpNS(samlconstants::SAML20ECP_NS), m_paosBinding(samlconstants::SAML20_BINDING_PAOS)
 {
     static const XMLCh ECP[] = UNICODE_LITERAL_3(E,C,P);
@@ -233,8 +237,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
     string postData;
     const Handler* ACS=NULL;
     const char* option;
-    pair<bool,const char*> acClass;
-    pair<bool,const char*> acComp;
+    pair<bool,const char*> acClass, acComp, nidFormat, spQual;
     bool isPassive=false,forceAuthn=false;
     const Application& app=request.getApplication();
 
@@ -246,7 +249,7 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         if (option) {
             ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
             else if (ECP && !XMLString::equals(ACS->getString("Binding").second, samlconstants::SAML20_BINDING_PAOS)) {
                 request.log(SPRequest::SPWarn, "acsIndex in request referenced a non-PAOS ACS, using default ACS location");
                 ACS = NULL;
@@ -289,6 +292,16 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
             acComp.first = true;
         else
             acComp = getString("authnContextComparison");
+
+        if (nidFormat.second = request.getParameter("NameIDFormat"))
+            nidFormat.first = true;
+        else
+            nidFormat = getString("NameIDFormat");
+
+        if (spQual.second = request.getParameter("SPNameQualifier"))
+            spQual.first = true;
+        else
+            spQual = getString("SPNameQualifier");
     }
     else {
         // We're running as a "virtual handler" from within the filter.
@@ -313,6 +326,12 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         acComp = settings->getString("authnContextComparison");
         if (!acComp.first)
             acComp = getString("authnContextComparison");
+        nidFormat = settings->getString("NameIDFormat");
+        if (!nidFormat.first)
+            nidFormat = getString("NameIDFormat");
+        spQual = settings->getString("SPNameQualifier");
+        if (!spQual.first)
+            spQual = getString("SPNameQualifier");
     }
 
     if (ECP)
@@ -328,11 +347,11 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
             ACS = handlers.front();
         }
         else {
-            pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+            pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
             if (index.first) {
                 ACS = app.getAssertionConsumerServiceByIndex(index.second);
                 if (!ACS)
-                    request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+                    request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
             }
             if (!ACS)
                 ACS = app.getDefaultAssertionConsumerService();
@@ -345,14 +364,14 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         if (ACSbinding.first) {
             pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
             if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
-                m_log.info("configured or requested ACS has non-SAML 2.0 binding");
-                return make_pair(false,0L);
+                m_log.error("configured or requested ACS has non-SAML 2.0 binding");
+                throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
             }
             else if (strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST) &&
                      strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_ARTIFACT) &&
                      strcmp(ACSbinding.second, samlconstants::SAML20_BINDING_HTTP_POST_SIMPLESIGN)) {
-                m_log.info("configured or requested ACS has non-SAML 2.0 binding");
-                return make_pair(false,0L);
+                m_log.error("configured or requested ACS has non-SAML 2.0 binding");
+                throw ConfigurationException("Configured or requested ACS has non-SAML 2.0 binding ($1).", params(1, ACSbinding.second));
             }
         }
     }
@@ -397,6 +416,8 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
                 isPassive, forceAuthn,
                 acClass.first ? acClass.second : NULL,
                 acComp.first ? acComp.second : NULL,
+                nidFormat.first ? nidFormat.second : NULL,
+                spQual.first ? spQual.second : NULL,
                 target
                 );
         }
@@ -423,6 +444,8 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
             isPassive, forceAuthn,
             acClass.first ? acClass.second : NULL,
             acComp.first ? acComp.second : NULL,
+            nidFormat.first ? nidFormat.second : NULL,
+            spQual.first ? spQual.second : NULL,
             target
             );
     }
@@ -441,6 +464,10 @@ pair<bool,long> SAML2SessionInitiator::run(SPRequest& request, string& entityID,
         in.addmember("authnContextClassRef").string(acClass.second);
     if (acComp.first)
         in.addmember("authnContextComparison").string(acComp.second);
+    if (nidFormat.first)
+        in.addmember("NameIDFormat").string(nidFormat.second);
+    if (spQual.first)
+        in.addmember("SPNameQualifier").string(spQual.second);
     if (acsByIndex.first && acsByIndex.second) {
         if (ACS) {
             // Determine index to use.
@@ -531,6 +558,7 @@ void SAML2SessionInitiator::receive(DDF& in, ostream& out)
         in["acsLocation"].string(), bind.get(),
         in["isPassive"].integer()==1, in["forceAuthn"].integer()==1,
         in["authnContextClassRef"].string(), in["authnContextComparison"].string(),
+        in["NameIDFormat"].string(), in["SPNameQualifier"].string(),
         relayState
         );
     if (!ret.isstruct())
@@ -564,6 +592,8 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
     bool forceAuthn,
     const char* authnContextClassRef,
     const char* authnContextComparison,
+    const char* NameIDFormat,
+    const char* SPNameQualifier,
     string& relayState
     ) const
 {
@@ -659,6 +689,14 @@ pair<bool,long> SAML2SessionInitiator::doRequest(
         req->setNameIDPolicy(namepol);
         namepol->AllowCreate(true);
     }
+    if (NameIDFormat && *NameIDFormat) {
+        auto_ptr_XMLCh wideform(NameIDFormat);
+        req->getNameIDPolicy()->setFormat(wideform.get());
+    }
+    if (SPNameQualifier && *SPNameQualifier) {
+        auto_ptr_XMLCh widequal(SPNameQualifier);
+        req->getNameIDPolicy()->setSPNameQualifier(widequal.get());
+    }
     if (authnContextClassRef || authnContextComparison) {
         RequestedAuthnContext* reqContext = req->getRequestedAuthnContext();
         if (!reqContext) {
index 5ff0878..1c0a7e3 100644 (file)
@@ -37,6 +37,8 @@ using namespace xmltooling;
 using namespace std;
 
 #ifndef SHIBSP_LITE
+# include <saml/saml2/metadata/Metadata.h>
+# include <saml/saml2/metadata/MetadataProvider.h>
 using namespace opensaml::saml2md;
 #endif
 
@@ -122,6 +124,7 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
     const char* option;
     bool isPassive=false;
     const Application& app=request.getApplication();
+    pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
 
     if (isHandler) {
         option = request.getParameter("SAMLDS");
@@ -140,6 +143,10 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
         option = request.getParameter("isPassive");
         if (option)
             isPassive = !strcmp(option,"true");
+
+        option = request.getParameter("discoveryURL");
+        if (option)
+            discoveryURL.second = option;
     }
     else {
         // We're running as a "virtual handler" from within the filter.
@@ -148,9 +155,12 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
         target=request.getRequestURL();
         pair<bool,bool> passopt = getBool("isPassive");
         isPassive = passopt.first && passopt.second;
+        discoveryURL = request.getRequestSettings().first->getString("discoveryURL");
     }
 
-    m_log.debug("sending request to SAMLDS (%s)", m_url);
+    if (!discoveryURL.first)
+        discoveryURL.second = m_url;
+    m_log.debug("sending request to SAMLDS (%s)", discoveryURL.second);
 
     // Compute the return URL. We start with a self-referential link.
     string returnURL=request.getHandlerURL(target.c_str());
@@ -212,7 +222,7 @@ pair<bool,long> SAMLDSSessionInitiator::run(SPRequest& request, string& entityID
         returnURL = returnURL + "&target=" + urlenc->encode(target.c_str());;
     }
 
-    string req=string(m_url) + (strchr(m_url,'?') ? '&' : '?') + "entityID=" + urlenc->encode(app.getString("entityID").second) +
+    string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "entityID=" + urlenc->encode(app.getString("entityID").second) +
         "&return=" + urlenc->encode(returnURL.c_str());
     if (m_returnParam)
         req = req + "&returnIDParam=" + m_returnParam;
index acc194e..b02e7d0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -39,6 +39,8 @@ namespace shibsp {
     SHIBSP_DLLLOCAL PluginManager< SessionInitiator,string,pair<const DOMElement*,const char*> >::Factory CookieSessionInitiatorFactory;
 };
 
+map<string,string> SessionInitiator::m_remapper;
+
 void SHIBSP_API shibsp::registerSessionInitiators()
 {
     SPConfig& conf=SPConfig::getConfig();
@@ -50,7 +52,24 @@ void SHIBSP_API shibsp::registerSessionInitiators()
     conf.SessionInitiatorManager.registerFactory(TRANSFORM_SESSION_INITIATOR, TransformSessionInitiatorFactory);
     conf.SessionInitiatorManager.registerFactory(FORM_SESSION_INITIATOR, FormSessionInitiatorFactory);
     conf.SessionInitiatorManager.registerFactory(COOKIE_SESSION_INITIATOR, CookieSessionInitiatorFactory);
+
+    SessionInitiator::m_remapper["defaultACSIndex"] = "acsIndex";
+}
+
+SessionInitiator::SessionInitiator()
+{
+}
+
+SessionInitiator::~SessionInitiator()
+{
+}
+
+#ifndef SHIBSP_LITE
+const char* SessionInitiator::getType() const
+{
+    return "SessionInitiator";
 }
+#endif
 
 pair<bool,long> SessionInitiator::run(SPRequest& request, bool isHandler) const
 {
index c9de163..7bdc6cd 100644 (file)
@@ -34,6 +34,9 @@
 # include "metadata/MetadataProviderCriteria.h"
 # include <saml/saml2/metadata/Metadata.h>
 # include <saml/saml2/metadata/EndpointManager.h>
+# include <saml/util/SAMLConstants.h>
+#else
+# include "lite/SAMLConstants.h"
 #endif
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
@@ -55,7 +58,7 @@ namespace shibsp {
     {
     public:
         Shib1SessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.Shib1")), m_appId(appId) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.Shib1"), NULL, &m_remapper), m_appId(appId) {
             // If Location isn't set, defer address registration until the setParent call.
             pair<bool,const char*> loc = getString("Location");
             if (loc.first) {
@@ -124,7 +127,7 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
         if (option) {
             ACS = app.getAssertionConsumerServiceByIndex(atoi(option));
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
         }
 
         option = request.getParameter("target");
@@ -143,11 +146,11 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
 
     // Since we're not passing by index, we need to fully compute the return URL.
     if (!ACS) {
-        pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+        pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
         if (index.first) {
             ACS = app.getAssertionConsumerServiceByIndex(index.second);
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
         }
         if (!ACS)
             ACS = app.getDefaultAssertionConsumerService();
@@ -158,13 +161,13 @@ pair<bool,long> Shib1SessionInitiator::run(SPRequest& request, string& entityID,
     if (ACSbinding.first) {
         pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
         if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
-            m_log.info("configured or requested ACS has non-SAML 1.x binding");
-            return make_pair(false,0L);
+            m_log.error("configured or requested ACS has non-SAML 1.x binding");
+            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
         }
         else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
                  strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
-            m_log.info("configured or requested ACS has non-SAML 1.x binding");
-            return make_pair(false,0L);
+            m_log.error("configured or requested ACS has non-SAML 1.x binding");
+            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
         }
     }
 
index b9e066d..64cca9a 100644 (file)
@@ -24,6 +24,7 @@
 #include "Application.h"
 #include "exceptions.h"
 #include "ServiceProvider.h"
+#include "SPRequest.h"
 #include "handler/AbstractHandler.h"
 #include "handler/RemotedHandler.h"
 #include "util/CGIParser.h"
@@ -33,6 +34,9 @@ using namespace shibsp;
 # include "SessionCache.h"
 # include "metadata/MetadataProviderCriteria.h"
 # include <saml/version.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/security/Credential.h>
+# include <xmltooling/security/CredentialCriteria.h>
 using namespace opensaml::saml2md;
 using namespace opensaml;
 using namespace xmlsignature;
index f0e075d..aeeedf1 100644 (file)
 #include "handler/AbstractHandler.h"
 #include "handler/SessionInitiator.h"
 
+#ifndef SHIBSP_LITE
+# include <saml/util/SAMLConstants.h>
+#else
+# include "lite/SAMLConstants.h"
+#endif
+
 #include <ctime>
 #include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/util/URLEncoder.h>
@@ -47,7 +53,7 @@ namespace shibsp {
     {
     public:
         WAYFSessionInitiator(const DOMElement* e, const char* appId)
-                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.WAYF")), m_url(NULL) {
+                : AbstractHandler(e, Category::getInstance(SHIBSP_LOGCAT".SessionInitiator.WAYF"), NULL, &m_remapper), m_url(NULL) {
             pair<bool,const char*> url = getString("URL");
             if (!url.first)
                 throw ConfigurationException("WAYF SessionInitiator requires a URL property.");
@@ -84,33 +90,39 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     const char* option;
     const Handler* ACS=NULL;
     const Application& app=request.getApplication();
+    pair<bool,const char*> discoveryURL = pair<bool,const char*>(true, m_url);
 
     if (isHandler) {
         option=request.getParameter("acsIndex");
         if (option) {
             ACS=app.getAssertionConsumerServiceByIndex(atoi(option));
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex specified in request, using acsIndex property");
         }
 
         option = request.getParameter("target");
         if (option)
             target = option;
         recoverRelayState(request.getApplication(), request, request, target, false);
+
+        option = request.getParameter("discoveryURL");
+        if (option)
+            discoveryURL.second = option;
     }
     else {
         // We're running as a "virtual handler" from within the filter.
         // The target resource is the current one and everything else is defaulted.
         target=request.getRequestURL();
+        discoveryURL = request.getRequestSettings().first->getString("discoveryURL");
     }
     
     // Since we're not passing by index, we need to fully compute the return URL.
     if (!ACS) {
-        pair<bool,unsigned int> index = getUnsignedInt("defaultACSIndex");
+        pair<bool,unsigned int> index = getUnsignedInt("acsIndex");
         if (index.first) {
             ACS = app.getAssertionConsumerServiceByIndex(index.second);
             if (!ACS)
-                request.log(SPRequest::SPWarn, "invalid defaultACSIndex, using default ACS location");
+                request.log(SPRequest::SPWarn, "invalid acsIndex property, using default ACS location");
         }
         if (!ACS)
             ACS = app.getDefaultAssertionConsumerService();
@@ -121,17 +133,19 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     if (ACSbinding.first) {
         pair<bool,const char*> compatibleBindings = getString("compatibleBindings");
         if (compatibleBindings.first && strstr(compatibleBindings.second, ACSbinding.second) == NULL) {
-            m_log.info("configured or requested ACS has non-SAML 1.x binding");
-            return make_pair(false,0L);
+            m_log.error("configured or requested ACS has non-SAML 1.x binding");
+            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
         }
         else if (strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_POST) &&
                  strcmp(ACSbinding.second, samlconstants::SAML1_PROFILE_BROWSER_ARTIFACT)) {
-            m_log.info("configured or requested ACS has non-SAML 1.x binding");
-            return make_pair(false,0L);
+            m_log.error("configured or requested ACS has non-SAML 1.x binding");
+            throw ConfigurationException("Configured or requested ACS has non-SAML 1.x binding ($1).", params(1, ACSbinding.second));
         }
     }
 
-    m_log.debug("sending request to WAYF (%s)", m_url);
+    if (!discoveryURL.first)
+        discoveryURL.second = m_url;
+    m_log.debug("sending request to WAYF (%s)", discoveryURL.second);
 
     // Compute the ACS URL. We add the ACS location to the base handlerURL.
     string ACSloc=request.getHandlerURL(target.c_str());
@@ -156,7 +170,7 @@ pair<bool,long> WAYFSessionInitiator::run(SPRequest& request, string& entityID,
     char timebuf[16];
     sprintf(timebuf,"%lu",time(NULL));
     const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
-    string req=string(m_url) + (strchr(m_url,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
+    string req=string(discoveryURL.second) + (strchr(discoveryURL.second,'?') ? '&' : '?') + "shire=" + urlenc->encode(ACSloc.c_str()) +
         "&time=" + timebuf + "&target=" + urlenc->encode(target.c_str()) +
         "&providerId=" + urlenc->encode(app.getString("entityID").second);
 
index 8b73906..6feafda 100644 (file)
-/*\r
- *  Copyright 2009 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * ChainingAccessControl.cpp\r
- *\r
- * Access control plugin that combines other plugins.\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
-    class ChainingAccessControl : public AccessControl\r
-    {\r
-    public:\r
-        ChainingAccessControl(const DOMElement* e);\r
-\r
-        ~ChainingAccessControl() {\r
-            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
-        }\r
-\r
-        Lockable* lock() {\r
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));\r
-            return this;\r
-        }\r
-        void unlock() {\r
-            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));\r
-        }\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        enum operator_t { OP_AND, OP_OR } m_op;\r
-        vector<AccessControl*> m_ac;\r
-    };\r
-\r
-    AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)\r
-    {\r
-        return new ChainingAccessControl(e);\r
-    }\r
-\r
-    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
-    static const XMLCh _operator[] =        UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);\r
-    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);\r
-    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
-    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
-\r
-    extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);\r
-}\r
-\r
-void SHIBSP_API shibsp::registerAccessControls()\r
-{\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);\r
-    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);\r
-    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);\r
-}\r
-\r
-ChainingAccessControl::ChainingAccessControl(const DOMElement* e)\r
-{\r
-    const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;\r
-    if (XMLString::equals(op, AND))\r
-        m_op=OP_AND;\r
-    else if (XMLString::equals(op, OR))\r
-        m_op=OP_OR;\r
-    else\r
-        throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");\r
-\r
-    try {\r
-        e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;\r
-        while (e) {\r
-            auto_ptr_char type(e->getAttributeNS(NULL, _type));\r
-            if (type.get() && *type.get()) {\r
-                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());\r
-                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));\r
-            }\r
-            e = XMLHelper::getNextSiblingElement(e, _AccessControl);\r
-        }\r
-    }\r
-    catch (exception&) {\r
-        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());\r
-        throw;\r
-    }\r
-    if (m_ac.empty())\r
-        throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");\r
-}\r
-\r
-AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    switch (m_op) {\r
-        case OP_AND:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
-                if ((*i)->authorized(request, session) != shib_acl_true)\r
-                    return shib_acl_false;\r
-            }\r
-            return shib_acl_true;\r
-        }\r
-\r
-        case OP_OR:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {\r
-                if ((*i)->authorized(request,session) == shib_acl_true)\r
-                    return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-    }\r
-    request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");\r
-    return shib_acl_false;\r
-}\r
+/*
+ *  Copyright 2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * ChainingAccessControl.cpp
+ *
+ * Access control plugin that combines other plugins.
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+    class ChainingAccessControl : public AccessControl
+    {
+    public:
+        ChainingAccessControl(const DOMElement* e);
+
+        ~ChainingAccessControl() {
+            for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+        }
+
+        Lockable* lock() {
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<Lockable*,Lockable>(&Lockable::lock));
+            return this;
+        }
+        void unlock() {
+            for_each(m_ac.begin(), m_ac.end(), mem_fun<void,Lockable>(&Lockable::unlock));
+        }
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        enum operator_t { OP_AND, OP_OR } m_op;
+        vector<AccessControl*> m_ac;
+    };
+
+    AccessControl* SHIBSP_DLLLOCAL ChainingAccessControlFactory(const DOMElement* const & e)
+    {
+        return new ChainingAccessControl(e);
+    }
+
+    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+    static const XMLCh _operator[] =        UNICODE_LITERAL_8(o,p,e,r,a,t,o,r);
+    static const XMLCh _type[] =            UNICODE_LITERAL_4(t,y,p,e);
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);
+
+    extern AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e);
+}
+
+void SHIBSP_API shibsp::registerAccessControls()
+{
+    SPConfig& conf=SPConfig::getConfig();
+    conf.AccessControlManager.registerFactory(CHAINING_ACCESS_CONTROL, ChainingAccessControlFactory);
+    conf.AccessControlManager.registerFactory(XML_ACCESS_CONTROL, XMLAccessControlFactory);
+    conf.AccessControlManager.registerFactory("edu.internet2.middleware.shibboleth.sp.provider.XMLAccessControl", XMLAccessControlFactory);
+}
+
+AccessControl::AccessControl()
+{
+}
+
+AccessControl::~AccessControl()
+{
+}
+
+ChainingAccessControl::ChainingAccessControl(const DOMElement* e)
+{
+    const XMLCh* op = e ? e->getAttributeNS(NULL, _operator) : NULL;
+    if (XMLString::equals(op, AND))
+        m_op=OP_AND;
+    else if (XMLString::equals(op, OR))
+        m_op=OP_OR;
+    else
+        throw ConfigurationException("Missing or unrecognized operator in Chaining AccessControl configuration.");
+
+    try {
+        e = e ? XMLHelper::getFirstChildElement(e, _AccessControl) : NULL;
+        while (e) {
+            auto_ptr_char type(e->getAttributeNS(NULL, _type));
+            if (type.get() && *type.get()) {
+                Category::getInstance(SHIBSP_LOGCAT".AccessControl.Chaining").info("building AccessControl provider of type (%s)...", type.get());
+                m_ac.push_back(SPConfig::getConfig().AccessControlManager.newPlugin(type.get(), e));
+            }
+            e = XMLHelper::getNextSiblingElement(e, _AccessControl);
+        }
+    }
+    catch (exception&) {
+        for_each(m_ac.begin(), m_ac.end(), xmltooling::cleanup<AccessControl>());
+        throw;
+    }
+    if (m_ac.empty())
+        throw ConfigurationException("Chaining AccessControl plugin requires at least one child plugin.");
+}
+
+AccessControl::aclresult_t ChainingAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+    switch (m_op) {
+        case OP_AND:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+                if ((*i)->authorized(request, session) != shib_acl_true)
+                    return shib_acl_false;
+            }
+            return shib_acl_true;
+        }
+
+        case OP_OR:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_ac.begin(); i!=m_ac.end(); ++i) {
+                if ((*i)->authorized(request,session) == shib_acl_true)
+                    return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+    }
+    request.log(SPRequest::SPWarn, "unknown operation in access control policy, denying access");
+    return shib_acl_false;
+}
index 27f7610..16cf5e5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #include "remoting/ListenerService.h"
 #include "util/SPConstants.h"
 
+#include <algorithm>
+#include <xmltooling/io/HTTPRequest.h>
+#include <xmltooling/io/HTTPResponse.h>
+#include <xmltooling/util/DateTime.h>
 #include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
+#include <xmltooling/util/Threads.h>
 #include <xmltooling/util/XMLHelper.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 
 #ifndef SHIBSP_LITE
+# include <saml/exceptions.h>
 # include <saml/SAMLConfig.h>
+# include <saml/saml2/core/Assertions.h>
+# include <saml/saml2/metadata/Metadata.h>
+# include <xmltooling/XMLToolingConfig.h>
 # include <xmltooling/util/StorageService.h>
 using namespace opensaml::saml2md;
 #else
@@ -352,6 +362,14 @@ void SHIBSP_API shibsp::registerSessionCaches()
     SPConfig::getConfig().SessionCacheManager.registerFactory(STORAGESERVICE_SESSION_CACHE, StorageServiceCacheFactory);
 }
 
+Session::Session()
+{
+}
+
+Session::~Session()
+{
+}
+
 void StoredSession::unmarshallAttributes() const
 {
     Attribute* attribute;
@@ -711,6 +729,22 @@ void StoredSession::addAssertion(Assertion* assertion)
 
 #endif
 
+SessionCache::SessionCache()
+{
+}
+
+SessionCache::~SessionCache()
+{
+}
+
+SessionCacheEx::SessionCacheEx()
+{
+}
+
+SessionCacheEx::~SessionCacheEx()
+{
+}
+
 SSCache::SSCache(const DOMElement* e)
     : m_log(Category::getInstance(SHIBSP_LOGCAT".SessionCache")), inproc(true), m_cacheTimeout(28800),
 #ifndef SHIBSP_LITE
index 5d9d352..7e08b73 100644 (file)
-/*\r
- *  Copyright 2001-2007 Internet2\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * XMLAccessControl.cpp\r
- *\r
- * XML-based access control syntax\r
- */\r
-\r
-#include "internal.h"\r
-#include "exceptions.h"\r
-#include "AccessControl.h"\r
-#include "SessionCache.h"\r
-#include "SPRequest.h"\r
-#include "attribute/Attribute.h"\r
-\r
-#include <xmltooling/util/ReloadableXMLFile.h>\r
-#include <xmltooling/util/XMLHelper.h>\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-#include <xercesc/util/regx/RegularExpression.hpp>\r
-\r
-#ifndef HAVE_STRCASECMP\r
-# define strcasecmp _stricmp\r
-#endif\r
-\r
-using namespace shibsp;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-namespace shibsp {\r
-\r
-    class Rule : public AccessControl\r
-    {\r
-    public:\r
-        Rule(const DOMElement* e);\r
-        ~Rule() {}\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        string m_alias;\r
-        vector <string> m_vals;\r
-    };\r
-\r
-    class RuleRegex : public AccessControl\r
-    {\r
-    public:\r
-        RuleRegex(const DOMElement* e);\r
-        ~RuleRegex() {\r
-            delete m_re;\r
-        }\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        string m_alias;\r
-        auto_arrayptr<char> m_exp;\r
-        RegularExpression* m_re;\r
-    };\r
-\r
-    class Operator : public AccessControl\r
-    {\r
-    public:\r
-        Operator(const DOMElement* e);\r
-        ~Operator();\r
-\r
-        Lockable* lock() {return this;}\r
-        void unlock() {}\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    private:\r
-        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;\r
-        vector<AccessControl*> m_operands;\r
-    };\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( push )\r
-    #pragma warning( disable : 4250 )\r
-#endif\r
-\r
-    class XMLAccessControl : public AccessControl, public ReloadableXMLFile\r
-    {\r
-    public:\r
-        XMLAccessControl(const DOMElement* e)\r
-                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {\r
-            load(); // guarantees an exception or the policy is loaded\r
-        }\r
-\r
-        ~XMLAccessControl() {\r
-            delete m_rootAuthz;\r
-        }\r
-\r
-        aclresult_t authorized(const SPRequest& request, const Session* session) const;\r
-\r
-    protected:\r
-        pair<bool,DOMElement*> load();\r
-\r
-    private:\r
-        AccessControl* m_rootAuthz;\r
-    };\r
-\r
-#if defined (_MSC_VER)\r
-    #pragma warning( pop )\r
-#endif\r
-\r
-    AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)\r
-    {\r
-        return new XMLAccessControl(e);\r
-    }\r
-\r
-    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);\r
-    static const XMLCh ignoreCase[] =       UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);\r
-    static const XMLCh ignoreOption[] =     UNICODE_LITERAL_1(i);\r
-    static const XMLCh _list[] =            UNICODE_LITERAL_4(l,i,s,t);\r
-    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);\r
-    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);\r
-    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);\r
-    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);\r
-    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);\r
-    static const XMLCh _RuleRegex[] =       UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);\r
-}\r
-\r
-Rule::Rule(const DOMElement* e)\r
-{\r
-    auto_ptr_char req(e->getAttributeNS(NULL,require));\r
-    if (!req.get() || !*req.get())\r
-        throw ConfigurationException("Access control rule missing require attribute");\r
-    m_alias=req.get();\r
-\r
-    auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));\r
-    if (!vals.get())\r
-        return;\r
-\r
-    const XMLCh* flag = e->getAttributeNS(NULL,_list);\r
-    if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {\r
-        if (*vals.get())\r
-            m_vals.push_back(vals.get());\r
-        return;\r
-    }\r
-\r
-#ifdef HAVE_STRTOK_R\r
-    char* pos=NULL;\r
-    const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);\r
-#else\r
-    const char* token=strtok(const_cast<char*>(vals.get())," ");\r
-#endif\r
-    while (token) {\r
-        m_vals.push_back(token);\r
-#ifdef HAVE_STRTOK_R\r
-        token=strtok_r(NULL," ",&pos);\r
-#else\r
-        token=strtok(NULL," ");\r
-#endif\r
-    }\r
-}\r
-\r
-AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    // We can make this more complex later using pluggable comparison functions,\r
-    // but for now, just a straight port to the new Attribute API.\r
-\r
-    // Map alias in rule to the attribute.\r
-    if (!session) {\r
-        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    if (m_alias == "valid-user") {\r
-        if (session) {\r
-            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
-            return shib_acl_true;\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    if (m_alias == "user") {\r
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
-            if (*i == request.getRemoteUser()) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    else if (m_alias == "authnContextClassRef") {\r
-        const char* ref = session->getAuthnContextClassRef();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
-            if (!strcmp(i->c_str(),ref)) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-    else if (m_alias == "authnContextDeclRef") {\r
-        const char* ref = session->getAuthnContextDeclRef();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {\r
-            if (!strcmp(i->c_str(),ref)) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-\r
-    // Find the attribute(s) matching the require rule.\r
-    pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
-        session->getIndexedAttributes().equal_range(m_alias);\r
-    if (attrs.first == attrs.second) {\r
-        request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    for (; attrs.first != attrs.second; ++attrs.first) {\r
-        bool caseSensitive = attrs.first->second->isCaseSensitive();\r
-\r
-        // Now we have to intersect the attribute's values against the rule's list.\r
-        const vector<string>& vals = attrs.first->second->getSerializedValues();\r
-        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {\r
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
-                if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {\r
-                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");\r
-                    return shib_acl_true;\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    return shib_acl_false;\r
-}\r
-\r
-RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))\r
-{\r
-    auto_ptr_char req(e->getAttributeNS(NULL,require));\r
-    if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())\r
-        throw ConfigurationException("Access control rule missing require attribute or element content.");\r
-    m_alias=req.get();\r
-\r
-    const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);\r
-    bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));\r
-    try {\r
-        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));\r
-    }\r
-    catch (XMLException& ex) {\r
-        auto_ptr_char tmp(ex.getMessage());\r
-        throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));\r
-    }\r
-}\r
-\r
-AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    // Map alias in rule to the attribute.\r
-    if (!session) {\r
-        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");\r
-        return shib_acl_false;\r
-    }\r
-\r
-    if (m_alias == "valid-user") {\r
-        if (session) {\r
-            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");\r
-            return shib_acl_true;\r
-        }\r
-        return shib_acl_false;\r
-    }\r
-\r
-    try {\r
-        if (m_alias == "user") {\r
-            if (m_re->matches(request.getRemoteUser().c_str())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-        else if (m_alias == "authnContextClassRef") {\r
-            if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-        else if (m_alias == "authnContextDeclRef") {\r
-            if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {\r
-                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");\r
-                return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-\r
-        // Find the attribute(s) matching the require rule.\r
-        pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =\r
-            session->getIndexedAttributes().equal_range(m_alias);\r
-        if (attrs.first == attrs.second) {\r
-            request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");\r
-            return shib_acl_false;\r
-        }\r
-\r
-        for (; attrs.first != attrs.second; ++attrs.first) {\r
-            // Now we have to intersect the attribute's values against the regular expression.\r
-            const vector<string>& vals = attrs.first->second->getSerializedValues();\r
-            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {\r
-                if (m_re->matches(j->c_str())) {\r
-                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");\r
-                    return shib_acl_true;\r
-                }\r
-            }\r
-        }\r
-    }\r
-    catch (XMLException& ex) {\r
-        auto_ptr_char tmp(ex.getMessage());\r
-        request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());\r
-    }\r
-\r
-    return shib_acl_false;\r
-}\r
-\r
-Operator::Operator(const DOMElement* e)\r
-{\r
-    if (XMLString::equals(e->getLocalName(),NOT))\r
-        m_op=OP_NOT;\r
-    else if (XMLString::equals(e->getLocalName(),AND))\r
-        m_op=OP_AND;\r
-    else if (XMLString::equals(e->getLocalName(),OR))\r
-        m_op=OP_OR;\r
-    else\r
-        throw ConfigurationException("Unrecognized operator in access control rule");\r
-\r
-    try {\r
-        e=XMLHelper::getFirstChildElement(e);\r
-        if (XMLString::equals(e->getLocalName(),_Rule))\r
-            m_operands.push_back(new Rule(e));\r
-        else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
-            m_operands.push_back(new RuleRegex(e));\r
-        else\r
-            m_operands.push_back(new Operator(e));\r
-\r
-        if (m_op==OP_NOT)\r
-            return;\r
-\r
-        e=XMLHelper::getNextSiblingElement(e);\r
-        while (e) {\r
-            if (XMLString::equals(e->getLocalName(),_Rule))\r
-                m_operands.push_back(new Rule(e));\r
-            else if (XMLString::equals(e->getLocalName(),_RuleRegex))\r
-                m_operands.push_back(new RuleRegex(e));\r
-            else\r
-                m_operands.push_back(new Operator(e));\r
-            e=XMLHelper::getNextSiblingElement(e);\r
-        }\r
-    }\r
-    catch (exception&) {\r
-        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
-        throw;\r
-    }\r
-}\r
-\r
-Operator::~Operator()\r
-{\r
-    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());\r
-}\r
-\r
-AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    switch (m_op) {\r
-        case OP_NOT:\r
-            switch (m_operands.front()->authorized(request,session)) {\r
-                case shib_acl_true:\r
-                    return shib_acl_false;\r
-                case shib_acl_false:\r
-                    return shib_acl_true;\r
-                default:\r
-                    return shib_acl_indeterminate;\r
-            }\r
-\r
-        case OP_AND:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
-                if ((*i)->authorized(request,session) != shib_acl_true)\r
-                    return shib_acl_false;\r
-            }\r
-            return shib_acl_true;\r
-        }\r
-\r
-        case OP_OR:\r
-        {\r
-            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {\r
-                if ((*i)->authorized(request,session) == shib_acl_true)\r
-                    return shib_acl_true;\r
-            }\r
-            return shib_acl_false;\r
-        }\r
-    }\r
-    request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");\r
-    return shib_acl_false;\r
-}\r
-\r
-pair<bool,DOMElement*> XMLAccessControl::load()\r
-{\r
-    // Load from source using base class.\r
-    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
-\r
-    // If we own it, wrap it.\r
-    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
-\r
-    // Check for AccessControl wrapper and drop a level.\r
-    if (XMLString::equals(raw.second->getLocalName(),_AccessControl))\r
-        raw.second = XMLHelper::getFirstChildElement(raw.second);\r
-\r
-    AccessControl* authz;\r
-    if (XMLString::equals(raw.second->getLocalName(),_Rule))\r
-        authz=new Rule(raw.second);\r
-    else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))\r
-        authz=new RuleRegex(raw.second);\r
-    else\r
-        authz=new Operator(raw.second);\r
-\r
-    delete m_rootAuthz;\r
-    m_rootAuthz = authz;\r
-    return make_pair(false,(DOMElement*)NULL);\r
-}\r
-\r
-AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const\r
-{\r
-    return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * XMLAccessControl.cpp
+ *
+ * XML-based access control syntax
+ */
+
+#include "internal.h"
+#include "exceptions.h"
+#include "AccessControl.h"
+#include "SessionCache.h"
+#include "SPRequest.h"
+#include "attribute/Attribute.h"
+
+#include <algorithm>
+#include <xmltooling/unicode.h>
+#include <xmltooling/util/ReloadableXMLFile.h>
+#include <xmltooling/util/XMLHelper.h>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xercesc/util/regx/RegularExpression.hpp>
+
+#ifndef HAVE_STRCASECMP
+# define strcasecmp _stricmp
+#endif
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace std;
+
+namespace shibsp {
+
+    class Rule : public AccessControl
+    {
+    public:
+        Rule(const DOMElement* e);
+        ~Rule() {}
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        string m_alias;
+        vector <string> m_vals;
+    };
+
+    class RuleRegex : public AccessControl
+    {
+    public:
+        RuleRegex(const DOMElement* e);
+        ~RuleRegex() {
+            delete m_re;
+        }
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        string m_alias;
+        auto_arrayptr<char> m_exp;
+        RegularExpression* m_re;
+    };
+
+    class Operator : public AccessControl
+    {
+    public:
+        Operator(const DOMElement* e);
+        ~Operator();
+
+        Lockable* lock() {return this;}
+        void unlock() {}
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    private:
+        enum operator_t { OP_NOT, OP_AND, OP_OR } m_op;
+        vector<AccessControl*> m_operands;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4250 )
+#endif
+
+    class XMLAccessControl : public AccessControl, public ReloadableXMLFile
+    {
+    public:
+        XMLAccessControl(const DOMElement* e)
+                : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".AccessControl.XML")), m_rootAuthz(NULL) {
+            load(); // guarantees an exception or the policy is loaded
+        }
+
+        ~XMLAccessControl() {
+            delete m_rootAuthz;
+        }
+
+        aclresult_t authorized(const SPRequest& request, const Session* session) const;
+
+    protected:
+        pair<bool,DOMElement*> load();
+
+    private:
+        AccessControl* m_rootAuthz;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+    AccessControl* SHIBSP_DLLLOCAL XMLAccessControlFactory(const DOMElement* const & e)
+    {
+        return new XMLAccessControl(e);
+    }
+
+    static const XMLCh _AccessControl[] =   UNICODE_LITERAL_13(A,c,c,e,s,s,C,o,n,t,r,o,l);
+    static const XMLCh ignoreCase[] =       UNICODE_LITERAL_10(i,g,n,o,r,e,C,a,s,e);
+    static const XMLCh ignoreOption[] =     UNICODE_LITERAL_1(i);
+    static const XMLCh _list[] =            UNICODE_LITERAL_4(l,i,s,t);
+    static const XMLCh require[] =          UNICODE_LITERAL_7(r,e,q,u,i,r,e);
+    static const XMLCh NOT[] =              UNICODE_LITERAL_3(N,O,T);
+    static const XMLCh AND[] =              UNICODE_LITERAL_3(A,N,D);
+    static const XMLCh OR[] =               UNICODE_LITERAL_2(O,R);
+    static const XMLCh _Rule[] =            UNICODE_LITERAL_4(R,u,l,e);
+    static const XMLCh _RuleRegex[] =       UNICODE_LITERAL_9(R,u,l,e,R,e,g,e,x);
+}
+
+Rule::Rule(const DOMElement* e)
+{
+    auto_ptr_char req(e->getAttributeNS(NULL,require));
+    if (!req.get() || !*req.get())
+        throw ConfigurationException("Access control rule missing require attribute");
+    m_alias=req.get();
+
+    auto_arrayptr<char> vals(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL));
+    if (!vals.get())
+        return;
+
+    const XMLCh* flag = e->getAttributeNS(NULL,_list);
+    if (flag && (*flag == chLatin_f || *flag == chDigit_0)) {
+        if (*vals.get())
+            m_vals.push_back(vals.get());
+        return;
+    }
+
+#ifdef HAVE_STRTOK_R
+    char* pos=NULL;
+    const char* token=strtok_r(const_cast<char*>(vals.get())," ",&pos);
+#else
+    const char* token=strtok(const_cast<char*>(vals.get())," ");
+#endif
+    while (token) {
+        m_vals.push_back(token);
+#ifdef HAVE_STRTOK_R
+        token=strtok_r(NULL," ",&pos);
+#else
+        token=strtok(NULL," ");
+#endif
+    }
+}
+
+AccessControl::aclresult_t Rule::authorized(const SPRequest& request, const Session* session) const
+{
+    // We can make this more complex later using pluggable comparison functions,
+    // but for now, just a straight port to the new Attribute API.
+
+    // Map alias in rule to the attribute.
+    if (!session) {
+        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+        return shib_acl_false;
+    }
+
+    if (m_alias == "valid-user") {
+        if (session) {
+            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+            return shib_acl_true;
+        }
+        return shib_acl_false;
+    }
+    if (m_alias == "user") {
+        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+            if (*i == request.getRemoteUser()) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+    else if (m_alias == "authnContextClassRef") {
+        const char* ref = session->getAuthnContextClassRef();
+        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+            if (!strcmp(i->c_str(),ref)) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+    else if (m_alias == "authnContextDeclRef") {
+        const char* ref = session->getAuthnContextDeclRef();
+        for (vector<string>::const_iterator i=m_vals.begin(); ref && i!=m_vals.end(); ++i) {
+            if (!strcmp(i->c_str(),ref)) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + *i + "), authz granted");
+                return shib_acl_true;
+            }
+        }
+        return shib_acl_false;
+    }
+
+    // Find the attribute(s) matching the require rule.
+    pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+        session->getIndexedAttributes().equal_range(m_alias);
+    if (attrs.first == attrs.second) {
+        request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+        return shib_acl_false;
+    }
+
+    for (; attrs.first != attrs.second; ++attrs.first) {
+        bool caseSensitive = attrs.first->second->isCaseSensitive();
+
+        // Now we have to intersect the attribute's values against the rule's list.
+        const vector<string>& vals = attrs.first->second->getSerializedValues();
+        for (vector<string>::const_iterator i=m_vals.begin(); i!=m_vals.end(); ++i) {
+            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+                if ((caseSensitive && *i == *j) || (!caseSensitive && !strcasecmp(i->c_str(),j->c_str()))) {
+                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + *j + "), authz granted");
+                    return shib_acl_true;
+                }
+            }
+        }
+    }
+
+    return shib_acl_false;
+}
+
+RuleRegex::RuleRegex(const DOMElement* e) : m_exp(toUTF8(e->hasChildNodes() ? e->getFirstChild()->getNodeValue() : NULL))
+{
+    auto_ptr_char req(e->getAttributeNS(NULL,require));
+    if (!req.get() || !*req.get() || !m_exp.get() || !*m_exp.get())
+        throw ConfigurationException("Access control rule missing require attribute or element content.");
+    m_alias=req.get();
+
+    const XMLCh* flag = e->getAttributeNS(NULL,ignoreCase);
+    bool ignore = (flag && (*flag == chLatin_t || *flag == chDigit_1));
+    try {
+        m_re = new RegularExpression(e->getFirstChild()->getNodeValue(), (ignore ? ignoreOption : &chNull));
+    }
+    catch (XMLException& ex) {
+        auto_ptr_char tmp(ex.getMessage());
+        throw ConfigurationException("Caught exception while parsing RuleRegex regular expression: $1", params(1,tmp.get()));
+    }
+}
+
+AccessControl::aclresult_t RuleRegex::authorized(const SPRequest& request, const Session* session) const
+{
+    // Map alias in rule to the attribute.
+    if (!session) {
+        request.log(SPRequest::SPWarn, "AccessControl plugin not given a valid session to evaluate, are you using lazy sessions?");
+        return shib_acl_false;
+    }
+
+    if (m_alias == "valid-user") {
+        if (session) {
+            request.log(SPRequest::SPDebug,"AccessControl plugin accepting valid-user based on active session");
+            return shib_acl_true;
+        }
+        return shib_acl_false;
+    }
+
+    try {
+        if (m_alias == "user") {
+            if (m_re->matches(request.getRemoteUser().c_str())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting REMOTE_USER (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+        else if (m_alias == "authnContextClassRef") {
+            if (session->getAuthnContextClassRef() && m_re->matches(session->getAuthnContextClassRef())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextClassRef (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+        else if (m_alias == "authnContextDeclRef") {
+            if (session->getAuthnContextDeclRef() && m_re->matches(session->getAuthnContextDeclRef())) {
+                request.log(SPRequest::SPDebug, string("AccessControl plugin expecting authnContextDeclRef (") + m_exp.get() + "), authz granted");
+                return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+
+        // Find the attribute(s) matching the require rule.
+        pair<multimap<string,const Attribute*>::const_iterator, multimap<string,const Attribute*>::const_iterator> attrs =
+            session->getIndexedAttributes().equal_range(m_alias);
+        if (attrs.first == attrs.second) {
+            request.log(SPRequest::SPWarn, string("rule requires attribute (") + m_alias + "), not found in session");
+            return shib_acl_false;
+        }
+
+        for (; attrs.first != attrs.second; ++attrs.first) {
+            // Now we have to intersect the attribute's values against the regular expression.
+            const vector<string>& vals = attrs.first->second->getSerializedValues();
+            for (vector<string>::const_iterator j=vals.begin(); j!=vals.end(); ++j) {
+                if (m_re->matches(j->c_str())) {
+                    request.log(SPRequest::SPDebug, string("AccessControl plugin expecting (") + m_exp.get() + "), authz granted");
+                    return shib_acl_true;
+                }
+            }
+        }
+    }
+    catch (XMLException& ex) {
+        auto_ptr_char tmp(ex.getMessage());
+        request.log(SPRequest::SPError, string("caught exception while parsing RuleRegex regular expression: ") + tmp.get());
+    }
+
+    return shib_acl_false;
+}
+
+Operator::Operator(const DOMElement* e)
+{
+    if (XMLString::equals(e->getLocalName(),NOT))
+        m_op=OP_NOT;
+    else if (XMLString::equals(e->getLocalName(),AND))
+        m_op=OP_AND;
+    else if (XMLString::equals(e->getLocalName(),OR))
+        m_op=OP_OR;
+    else
+        throw ConfigurationException("Unrecognized operator in access control rule");
+
+    try {
+        e=XMLHelper::getFirstChildElement(e);
+        if (XMLString::equals(e->getLocalName(),_Rule))
+            m_operands.push_back(new Rule(e));
+        else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+            m_operands.push_back(new RuleRegex(e));
+        else
+            m_operands.push_back(new Operator(e));
+
+        if (m_op==OP_NOT)
+            return;
+
+        e=XMLHelper::getNextSiblingElement(e);
+        while (e) {
+            if (XMLString::equals(e->getLocalName(),_Rule))
+                m_operands.push_back(new Rule(e));
+            else if (XMLString::equals(e->getLocalName(),_RuleRegex))
+                m_operands.push_back(new RuleRegex(e));
+            else
+                m_operands.push_back(new Operator(e));
+            e=XMLHelper::getNextSiblingElement(e);
+        }
+    }
+    catch (exception&) {
+        for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+        throw;
+    }
+}
+
+Operator::~Operator()
+{
+    for_each(m_operands.begin(),m_operands.end(),xmltooling::cleanup<AccessControl>());
+}
+
+AccessControl::aclresult_t Operator::authorized(const SPRequest& request, const Session* session) const
+{
+    switch (m_op) {
+        case OP_NOT:
+            switch (m_operands.front()->authorized(request,session)) {
+                case shib_acl_true:
+                    return shib_acl_false;
+                case shib_acl_false:
+                    return shib_acl_true;
+                default:
+                    return shib_acl_indeterminate;
+            }
+
+        case OP_AND:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+                if ((*i)->authorized(request,session) != shib_acl_true)
+                    return shib_acl_false;
+            }
+            return shib_acl_true;
+        }
+
+        case OP_OR:
+        {
+            for (vector<AccessControl*>::const_iterator i=m_operands.begin(); i!=m_operands.end(); i++) {
+                if ((*i)->authorized(request,session) == shib_acl_true)
+                    return shib_acl_true;
+            }
+            return shib_acl_false;
+        }
+    }
+    request.log(SPRequest::SPWarn,"unknown operation in access control policy, denying access");
+    return shib_acl_false;
+}
+
+pair<bool,DOMElement*> XMLAccessControl::load()
+{
+    // Load from source using base class.
+    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
+
+    // If we own it, wrap it.
+    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
+
+    // Check for AccessControl wrapper and drop a level.
+    if (XMLString::equals(raw.second->getLocalName(),_AccessControl))
+        raw.second = XMLHelper::getFirstChildElement(raw.second);
+
+    AccessControl* authz;
+    if (XMLString::equals(raw.second->getLocalName(),_Rule))
+        authz=new Rule(raw.second);
+    else if (XMLString::equals(raw.second->getLocalName(),_RuleRegex))
+        authz=new RuleRegex(raw.second);
+    else
+        authz=new Operator(raw.second);
+
+    delete m_rootAuthz;
+    m_rootAuthz = authz;
+    return make_pair(false,(DOMElement*)NULL);
+}
+
+AccessControl::aclresult_t XMLAccessControl::authorized(const SPRequest& request, const Session* session) const
+{
+    return m_rootAuthz ? m_rootAuthz->authorized(request,session) : shib_acl_false;
+}
index 78e6edf..c048e0c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
 
 /** XMLRequestMapper.cpp
  *
- * XML-based RequestMapper implementation
+ * XML-based RequestMapper implementation.
  */
 
 #include "internal.h"
@@ -27,6 +27,7 @@
 #include "util/DOMPropertySet.h"
 #include "util/SPConstants.h"
 
+#include <algorithm>
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/ReloadableXMLFile.h>
 #include <xmltooling/util/XMLHelper.h>
@@ -162,6 +163,14 @@ void SHIBSP_API shibsp::registerRequestMappers()
     conf.RequestMapperManager.registerFactory(NATIVE_REQUEST_MAPPER, XMLRequestMapperFactory);
 }
 
+RequestMapper::RequestMapper()
+{
+}
+
+RequestMapper::~RequestMapper()
+{
+}
+
 void Override::loadACL(const DOMElement* e, Category& log)
 {
     try {
index 5b9de5f..05f3ef4 100644 (file)
-/*
- *  Copyright 2001-2009 Internet2
- *
- * Licensed 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.
- */
-
-/**
- * XMLServiceProvider.cpp
- *
- * XML-based SP configuration and mgmt
- */
-
-#include "internal.h"
-#include "exceptions.h"
-#include "version.h"
-#include "AccessControl.h"
-#include "Application.h"
-#include "RequestMapper.h"
-#include "ServiceProvider.h"
-#include "SessionCache.h"
-#include "SPConfig.h"
-#include "SPRequest.h"
-#include "handler/SessionInitiator.h"
-#include "remoting/ListenerService.h"
-#include "util/DOMPropertySet.h"
-#include "util/SPConstants.h"
-
-#if defined(XMLTOOLING_LOG4SHIB)
-# include <log4shib/PropertyConfigurator.hh>
-#elif defined(XMLTOOLING_LOG4CPP)
-# include <log4cpp/PropertyConfigurator.hh>
-#else
-# error "Supported logging library not available."
-#endif
-#include <xercesc/util/XMLUniDefs.hpp>
-#include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/version.h>
-#include <xmltooling/util/NDC.h>
-#include <xmltooling/util/ReloadableXMLFile.h>
-#include <xmltooling/util/TemplateEngine.h>
-#include <xmltooling/util/XMLHelper.h>
-
-#ifndef SHIBSP_LITE
-# include "TransactionLog.h"
-# include "attribute/filtering/AttributeFilter.h"
-# include "attribute/resolver/AttributeExtractor.h"
-# include "attribute/resolver/AttributeResolver.h"
-# include "security/PKIXTrustEngine.h"
-# include <saml/SAMLConfig.h>
-# include <saml/version.h>
-# include <saml/binding/ArtifactMap.h>
-# include <saml/binding/SAMLArtifact.h>
-# include <saml/saml1/core/Assertions.h>
-# include <saml/saml2/binding/SAML2ArtifactType0004.h>
-# include <xmltooling/util/ReplayCache.h>
-using namespace opensaml::saml2;
-using namespace opensaml::saml2p;
-using namespace opensaml::saml2md;
-using namespace opensaml;
-#endif
-
-using namespace shibsp;
-using namespace xmltooling;
-using namespace std;
-
-#ifndef min
-# define min(a,b)            (((a) < (b)) ? (a) : (b))
-#endif
-
-namespace {
-
-#if defined (_MSC_VER)
-    #pragma warning( push )
-    #pragma warning( disable : 4250 )
-#endif
-
-    static vector<const Handler*> g_noHandlers;
-
-    // Application configuration wrapper
-    class SHIBSP_DLLLOCAL XMLApplication : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter
-    {
-    public:
-        XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL);
-        ~XMLApplication() { cleanup(); }
-
-        const char* getHash() const {return m_hash.c_str();}
-
-#ifndef SHIBSP_LITE
-        SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {
-            throw ConfigurationException("No support for SAML 1.x artifact generation.");
-        }
-        SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {
-            pair<bool,int> index = make_pair(false,0);
-            const PropertySet* props = getRelyingParty(relyingParty);
-            index = props->getInt("artifactEndpointIndex");
-            if (!index.first)
-                index = getArtifactEndpointIndex();
-            return new SAML2ArtifactType0004(SAMLConfig::getConfig().hashSHA1(props->getString("entityID").second),index.first ? index.second : 1);
-        }
-
-        MetadataProvider* getMetadataProvider(bool required=true) const {
-            if (required && !m_base && !m_metadata)
-                throw ConfigurationException("No MetadataProvider available.");
-            return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata;
-        }
-        TrustEngine* getTrustEngine(bool required=true) const {
-            if (required && !m_base && !m_trust)
-                throw ConfigurationException("No TrustEngine available.");
-            return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust;
-        }
-        AttributeExtractor* getAttributeExtractor() const {
-            return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;
-        }
-        AttributeFilter* getAttributeFilter() const {
-            return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;
-        }
-        AttributeResolver* getAttributeResolver() const {
-            return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;
-        }
-        CredentialResolver* getCredentialResolver() const {
-            return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;
-        }
-        const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;
-        const PropertySet* getRelyingParty(const XMLCh* entityID) const;
-        const vector<const XMLCh*>* getAudiences() const {
-            return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences;
-        }
-#endif
-        string getNotificationURL(const char* resource, bool front, unsigned int index) const;
-
-        const vector<string>& getRemoteUserAttributeIds() const {
-            return (m_remoteUsers.empty() && m_base) ? m_base->getRemoteUserAttributeIds() : m_remoteUsers;
-        }
-
-        void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;
-        void setHeader(SPRequest& request, const char* name, const char* value) const;
-        string getSecureHeader(const SPRequest& request, const char* name) const;
-
-        const SessionInitiator* getDefaultSessionInitiator() const;
-        const SessionInitiator* getSessionInitiatorById(const char* id) const;
-        const Handler* getDefaultAssertionConsumerService() const;
-        const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;
-        const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;
-        const Handler* getHandler(const char* path) const;
-        void getHandlers(vector<const Handler*>& handlers) const;
-
-        void receive(DDF& in, ostream& out) {
-            // Only current function is to return the headers to clear.
-            DDF header;
-            DDF ret=DDF(NULL).list();
-            DDFJanitor jret(ret);
-            for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) {
-                header = DDF(i->first.c_str()).string(i->second.c_str());
-                ret.add(header);
-            }
-            out << ret;
-        }
-
-        // Provides filter to exclude special config elements.
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-        short
-#else
-        FilterAction
-#endif
-        acceptNode(const DOMNode* node) const;
-
-    private:
-        void cleanup();
-        const XMLApplication* m_base;
-        string m_hash;
-        std::pair<std::string,std::string> m_attributePrefix;
-#ifndef SHIBSP_LITE
-        MetadataProvider* m_metadata;
-        TrustEngine* m_trust;
-        AttributeExtractor* m_attrExtractor;
-        AttributeFilter* m_attrFilter;
-        AttributeResolver* m_attrResolver;
-        CredentialResolver* m_credResolver;
-        vector<const XMLCh*> m_audiences;
-
-        // RelyingParty properties
-        map<xstring,PropertySet*> m_partyMap;
-#endif
-        vector<string> m_remoteUsers,m_frontLogout,m_backLogout;
-
-        // manage handler objects
-        vector<Handler*> m_handlers;
-
-        // maps location (path info) to applicable handlers
-        map<string,const Handler*> m_handlerMap;
-
-        // maps unique indexes to consumer services
-        map<unsigned int,const Handler*> m_acsIndexMap;
-
-        // pointer to default consumer service
-        const Handler* m_acsDefault;
-
-        // maps binding strings to supporting consumer service(s)
-        typedef map<xstring,vector<const Handler*> > ACSBindingMap;
-        ACSBindingMap m_acsBindingMap;
-
-        // pointer to default session initiator
-        const SessionInitiator* m_sessionInitDefault;
-
-        // maps unique ID strings to session initiators
-        map<string,const SessionInitiator*> m_sessionInitMap;
-
-        // pointer to default artifact resolution service
-        const Handler* m_artifactResolutionDefault;
-
-        pair<bool,int> getArtifactEndpointIndex() const {
-            if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index");
-            return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0);
-        }
-    };
-
-    // Top-level configuration implementation
-    class SHIBSP_DLLLOCAL XMLConfig;
-    class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter
-    {
-    public:
-        XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);
-        ~XMLConfigImpl();
-
-        RequestMapper* m_requestMapper;
-        map<string,Application*> m_appmap;
-#ifndef SHIBSP_LITE
-        map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;
-        vector< pair< string, pair<string,string> > > m_transportOptions;
-#endif
-
-        // Provides filter to exclude special config elements.
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-        short
-#else
-        FilterAction
-#endif
-        acceptNode(const DOMNode* node) const;
-
-        void setDocument(DOMDocument* doc) {
-            m_document = doc;
-        }
-
-    private:
-        void doExtensions(const DOMElement* e, const char* label, Category& log);
-        void cleanup();
-
-        const XMLConfig* m_outer;
-        DOMDocument* m_document;
-    };
-
-    class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile
-#ifndef SHIBSP_LITE
-        ,public Remoted
-#endif
-    {
-    public:
-        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),
-            m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)
-#ifndef SHIBSP_LITE
-            , m_tranLog(NULL)
-#endif
-        {
-        }
-
-        void init() {
-            load();
-        }
-
-        ~XMLConfig() {
-            delete m_impl;
-            delete m_sessionCache;
-            delete m_listener;
-#ifndef SHIBSP_LITE
-            delete m_tranLog;
-            SAMLConfig::getConfig().setArtifactMap(NULL);
-            XMLToolingConfig::getConfig().setReplayCache(NULL);
-            for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());
-#endif
-        }
-
-        // PropertySet
-        const PropertySet* getParent() const { return m_impl->getParent(); }
-        void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}
-        pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}
-        pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}
-        pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}
-        pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}
-        pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}
-        void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}
-        const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}
-        const DOMElement* getElement() const {return m_impl->getElement();}
-
-        // ServiceProvider
-#ifndef SHIBSP_LITE
-        // Remoted
-        void receive(DDF& in, ostream& out);
-
-        TransactionLog* getTransactionLog() const {
-            if (m_tranLog)
-                return m_tranLog;
-            throw ConfigurationException("No TransactionLog available.");
-        }
-
-        StorageService* getStorageService(const char* id) const {
-            if (id) {
-                map<string,StorageService*>::const_iterator i=m_storage.find(id);
-                if (i!=m_storage.end())
-                    return i->second;
-            }
-            return NULL;
-        }
-#endif
-
-        ListenerService* getListenerService(bool required=true) const {
-            if (required && !m_listener)
-                throw ConfigurationException("No ListenerService available.");
-            return m_listener;
-        }
-
-        SessionCache* getSessionCache(bool required=true) const {
-            if (required && !m_sessionCache)
-                throw ConfigurationException("No SessionCache available.");
-            return m_sessionCache;
-        }
-
-        RequestMapper* getRequestMapper(bool required=true) const {
-            if (required && !m_impl->m_requestMapper)
-                throw ConfigurationException("No RequestMapper available.");
-            return m_impl->m_requestMapper;
-        }
-
-        const Application* getApplication(const char* applicationId) const {
-            map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);
-            return (i!=m_impl->m_appmap.end()) ? i->second : NULL;
-        }
-
-#ifndef SHIBSP_LITE
-        const PropertySet* getPolicySettings(const char* id) const {
-            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
-            if (i!=m_impl->m_policyMap.end())
-                return i->second.first;
-            throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
-        }
-
-        const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {
-            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);
-            if (i!=m_impl->m_policyMap.end())
-                return i->second.second;
-            throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));
-        }
-
-        bool setTransportOptions(SOAPTransport& transport) const {
-            bool ret = true;
-            vector< pair< string, pair<string,string> > >::const_iterator opt;
-            for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {
-                if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {
-                    m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());
-                    ret = false;
-                }
-            }
-            return ret;
-        }
-#endif
-
-    protected:
-        pair<bool,DOMElement*> load();
-
-    private:
-        friend class XMLConfigImpl;
-        XMLConfigImpl* m_impl;
-        mutable ListenerService* m_listener;
-        mutable SessionCache* m_sessionCache;
-#ifndef SHIBSP_LITE
-        mutable TransactionLog* m_tranLog;
-        mutable map<string,StorageService*> m_storage;
-#endif
-    };
-
-#if defined (_MSC_VER)
-    #pragma warning( pop )
-#endif
-
-    static const XMLCh ApplicationOverride[] =  UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e);
-    static const XMLCh ApplicationDefaults[] =  UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,D,e,f,a,u,l,t,s);
-    static const XMLCh _ArtifactMap[] =         UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);
-    static const XMLCh _AttributeExtractor[] =  UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);
-    static const XMLCh _AttributeFilter[] =     UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);
-    static const XMLCh _AttributeResolver[] =   UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);
-    static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);
-    static const XMLCh _ArtifactResolutionService[] =UNICODE_LITERAL_25(A,r,t,i,f,a,c,t,R,e,s,o,l,u,t,i,o,n,S,e,r,v,i,c,e);
-    static const XMLCh _Audience[] =            UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);
-    static const XMLCh Binding[] =              UNICODE_LITERAL_7(B,i,n,d,i,n,g);
-    static const XMLCh Channel[]=               UNICODE_LITERAL_7(C,h,a,n,n,e,l);
-    static const XMLCh _CredentialResolver[] =  UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);
-    static const XMLCh _Extensions[] =          UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);
-    static const XMLCh _fatal[] =               UNICODE_LITERAL_5(f,a,t,a,l);
-    static const XMLCh _Handler[] =             UNICODE_LITERAL_7(H,a,n,d,l,e,r);
-    static const XMLCh _id[] =                  UNICODE_LITERAL_2(i,d);
-    static const XMLCh InProcess[] =            UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);
-    static const XMLCh Library[] =              UNICODE_LITERAL_7(L,i,b,r,a,r,y);
-    static const XMLCh Listener[] =             UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);
-    static const XMLCh Location[] =             UNICODE_LITERAL_8(L,o,c,a,t,i,o,n);
-    static const XMLCh logger[] =               UNICODE_LITERAL_6(l,o,g,g,e,r);
-    static const XMLCh _LogoutInitiator[] =     UNICODE_LITERAL_15(L,o,g,o,u,t,I,n,i,t,i,a,t,o,r);
-    static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);
-    static const XMLCh _MetadataProvider[] =    UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);
-    static const XMLCh Notify[] =               UNICODE_LITERAL_6(N,o,t,i,f,y);
-    static const XMLCh _option[] =              UNICODE_LITERAL_6(o,p,t,i,o,n);
-    static const XMLCh OutOfProcess[] =         UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);
-    static const XMLCh _path[] =                UNICODE_LITERAL_4(p,a,t,h);
-    static const XMLCh Policy[] =               UNICODE_LITERAL_6(P,o,l,i,c,y);
-    static const XMLCh PolicyRule[] =           UNICODE_LITERAL_10(P,o,l,i,c,y,R,u,l,e);
-    static const XMLCh _provider[] =            UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);
-    static const XMLCh RelyingParty[] =         UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);
-    static const XMLCh _ReplayCache[] =         UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);
-    static const XMLCh _RequestMapper[] =       UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);
-    static const XMLCh Rule[] =                 UNICODE_LITERAL_4(R,u,l,e);
-    static const XMLCh SecurityPolicies[] =     UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);
-    static const XMLCh _SessionCache[] =        UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);
-    static const XMLCh _SessionInitiator[] =    UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);
-    static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);
-    static const XMLCh Site[] =                 UNICODE_LITERAL_4(S,i,t,e);
-    static const XMLCh _StorageService[] =      UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);
-    static const XMLCh TCPListener[] =          UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);
-    static const XMLCh TransportOption[] =      UNICODE_LITERAL_15(T,r,a,n,s,p,o,r,t,O,p,t,i,o,n);
-    static const XMLCh _TrustEngine[] =         UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);
-    static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);
-    static const XMLCh UnixListener[] =         UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);
-
-#ifndef SHIBSP_LITE
-    class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter
-    {
-    public:
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-        short
-#else
-        FilterAction
-#endif
-        acceptNode(const DOMNode* node) const {
-            return FILTER_REJECT;
-        }
-    };
-#endif
-};
-
-namespace shibsp {
-    ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)
-    {
-        return new XMLConfig(e);
-    }
-};
-
-XMLApplication::XMLApplication(
-    const ServiceProvider* sp,
-    const DOMElement* e,
-    const XMLApplication* base
-    ) : Application(sp), m_base(base),
-#ifndef SHIBSP_LITE
-        m_metadata(NULL), m_trust(NULL),
-        m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL),
-        m_credResolver(NULL),
-#endif
-        m_acsDefault(NULL), m_sessionInitDefault(NULL), m_artifactResolutionDefault(NULL)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("XMLApplication");
-#endif
-    Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");
-
-    try {
-        // First load any property sets.
-        load(e,NULL,this);
-        if (base)
-            setParent(base);
-
-        SPConfig& conf=SPConfig::getConfig();
-#ifndef SHIBSP_LITE
-        SAMLConfig& samlConf=SAMLConfig::getConfig();
-        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
-#endif
-
-        // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.
-        static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
-        string tohash=getId();
-        tohash+=getString("entityID").second;
-        for (const char* ch = tohash.c_str(); *ch; ++ch) {
-            m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);
-            m_hash += (DIGITS[0x0F & *ch]);
-        }
-
-        // Populate prefix pair.
-        m_attributePrefix.second = "HTTP_";
-        pair<bool,const char*> prefix = getString("attributePrefix");
-        if (prefix.first) {
-            m_attributePrefix.first = prefix.second;
-            const char* pch = prefix.second;
-            while (*pch) {
-                m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');
-                pch++;
-            }
-        }
-
-        // Load attribute ID lists for REMOTE_USER and header clearing.
-        if (conf.isEnabled(SPConfig::InProcess)) {
-            pair<bool,const char*> attributes = getString("REMOTE_USER");
-            if (attributes.first) {
-                char* dup = strdup(attributes.second);
-                char* pos;
-                char* start = dup;
-                while (start && *start) {
-                    while (*start && isspace(*start))
-                        start++;
-                    if (!*start)
-                        break;
-                    pos = strchr(start,' ');
-                    if (pos)
-                        *pos=0;
-                    m_remoteUsers.push_back(start);
-                    start = pos ? pos+1 : NULL;
-                }
-                free(dup);
-            }
-
-            attributes = getString("unsetHeaders");
-            if (attributes.first) {
-                string transformedprefix(m_attributePrefix.second);
-                const char* pch;
-                prefix = getString("metadataAttributePrefix");
-                if (prefix.first) {
-                    pch = prefix.second;
-                    while (*pch) {
-                        transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');
-                        pch++;
-                    }
-                }
-                char* dup = strdup(attributes.second);
-                char* pos;
-                char* start = dup;
-                while (start && *start) {
-                    while (*start && isspace(*start))
-                        start++;
-                    if (!*start)
-                        break;
-                    pos = strchr(start,' ');
-                    if (pos)
-                        *pos=0;
-
-                    string transformed;
-                    pch = start;
-                    while (*pch) {
-                        transformed += (isalnum(*pch) ? toupper(*pch) : '_');
-                        pch++;
-                    }
-
-                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));
-                    if (prefix.first)
-                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));
-                    start = pos ? pos+1 : NULL;
-                }
-                free(dup);
-                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
-            }
-        }
-
-        Handler* handler=NULL;
-        const PropertySet* sessions = getPropertySet("Sessions");
-
-        // Process assertion export handler.
-        pair<bool,const char*> location = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,NULL);
-        if (location.first) {
-            try {
-                DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler);
-                exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second);
-                pair<bool,const XMLCh*> exportACL = sessions->getXMLString("exportACL");
-                if (exportACL.first) {
-                    static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);
-                    exportElement->setAttributeNS(NULL,_acl,exportACL.second);
-                }
-                handler = conf.HandlerManager.newPlugin(
-                    samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())
-                    );
-                m_handlers.push_back(handler);
-
-                // Insert into location map. If it contains the handlerURL, we skip past that part.
-                const char* pch = strstr(location.second, sessions->getString("handlerURL").second);
-                if (pch)
-                    location.second = pch + strlen(sessions->getString("handlerURL").second);
-                if (*location.second == '/')
-                    m_handlerMap[location.second]=handler;
-                else
-                    m_handlerMap[string("/") + location.second]=handler;
-            }
-            catch (exception& ex) {
-                log.error("caught exception installing assertion lookup handler: %s", ex.what());
-            }
-        }
-
-        // Process other handlers.
-        bool hardACS=false, hardSessionInit=false, hardArt=false;
-        const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;
-        while (child) {
-            try {
-                // A handler is based on the Binding property in conjunction with the element name.
-                // If it's an ACS or SI, also handle index/id mappings and defaulting.
-                if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {
-                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
-                    if (!bindprop.get() || !*(bindprop.get())) {
-                        log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-                    // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)
-                    m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);
-                    m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;
-
-                    if (!hardACS) {
-                        pair<bool,bool> defprop=handler->getBool("isDefault");
-                        if (defprop.first) {
-                            if (defprop.second) {
-                                hardACS=true;
-                                m_acsDefault=handler;
-                            }
-                        }
-                        else if (!m_acsDefault)
-                            m_acsDefault=handler;
-                    }
-                }
-                else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {
-                    auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                    if (!type.get() || !*(type.get())) {
-                        log.warn("SessionInitiator element has no type attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));
-                    handler=sihandler;
-                    pair<bool,const char*> si_id=handler->getString("id");
-                    if (si_id.first && si_id.second)
-                        m_sessionInitMap[si_id.second]=sihandler;
-                    if (!hardSessionInit) {
-                        pair<bool,bool> defprop=handler->getBool("isDefault");
-                        if (defprop.first) {
-                            if (defprop.second) {
-                                hardSessionInit=true;
-                                m_sessionInitDefault=sihandler;
-                            }
-                        }
-                        else if (!m_sessionInitDefault)
-                            m_sessionInitDefault=sihandler;
-                    }
-                }
-                else if (XMLString::equals(child->getLocalName(),_LogoutInitiator)) {
-                    auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                    if (!type.get() || !*(type.get())) {
-                        log.warn("LogoutInitiator element has no type attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.LogoutInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));
-                }
-                else if (XMLString::equals(child->getLocalName(),_ArtifactResolutionService)) {
-                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
-                    if (!bindprop.get() || !*(bindprop.get())) {
-                        log.warn("md:ArtifactResolutionService element has no Binding attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-
-                    if (!hardArt) {
-                        pair<bool,bool> defprop=handler->getBool("isDefault");
-                        if (defprop.first) {
-                            if (defprop.second) {
-                                hardArt=true;
-                                m_artifactResolutionDefault=handler;
-                            }
-                        }
-                        else if (!m_artifactResolutionDefault)
-                            m_artifactResolutionDefault=handler;
-                    }
-                }
-                else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {
-                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
-                    if (!bindprop.get() || !*(bindprop.get())) {
-                        log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-                }
-                else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {
-                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));
-                    if (!bindprop.get() || !*(bindprop.get())) {
-                        log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));
-                }
-                else {
-                    auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                    if (!type.get() || !*(type.get())) {
-                        log.warn("Handler element has no type attribute, skipping it...");
-                        child = XMLHelper::getNextSiblingElement(child);
-                        continue;
-                    }
-                    handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));
-                }
-
-                m_handlers.push_back(handler);
-
-                // Insert into location map.
-                location=handler->getString("Location");
-                if (location.first && *location.second == '/')
-                    m_handlerMap[location.second]=handler;
-                else if (location.first)
-                    m_handlerMap[string("/") + location.second]=handler;
-
-            }
-            catch (exception& ex) {
-                log.error("caught exception processing handler element: %s", ex.what());
-            }
-
-            child = XMLHelper::getNextSiblingElement(child);
-        }
-
-        // Notification.
-        DOMNodeList* nlist=e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS,Notify);
-        for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++) {
-            if (nlist->item(i)->getParentNode()->isSameNode(e)) {
-                const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Channel);
-                auto_ptr_char loc(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Location));
-                if (loc.get() && *loc.get()) {
-                    if (channel && *channel == chLatin_f)
-                        m_frontLogout.push_back(loc.get());
-                    else
-                        m_backLogout.push_back(loc.get());
-                }
-            }
-        }
-
-#ifndef SHIBSP_LITE
-        nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);
-        if (nlist && nlist->getLength()) {
-            log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");
-            for (XMLSize_t i=0; i<nlist->getLength(); i++)
-                if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())
-                    m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());
-        }
-
-        if (conf.isEnabled(SPConfig::Metadata)) {
-            child = XMLHelper::getFirstChildElement(e,_MetadataProvider);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building MetadataProvider of type %s...",type.get());
-                try {
-                    auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));
-                    mp->init();
-                    m_metadata = mp.release();
-                }
-                catch (exception& ex) {
-                    log.crit("error building/initializing MetadataProvider: %s", ex.what());
-                }
-            }
-        }
-
-        if (conf.isEnabled(SPConfig::Trust)) {
-            child = XMLHelper::getFirstChildElement(e,_TrustEngine);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building TrustEngine of type %s...",type.get());
-                try {
-                    m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);
-                }
-                catch (exception& ex) {
-                    log.crit("error building TrustEngine: %s", ex.what());
-                }
-            }
-        }
-
-        if (conf.isEnabled(SPConfig::AttributeResolution)) {
-            child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building AttributeExtractor of type %s...",type.get());
-                try {
-                    m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);
-                }
-                catch (exception& ex) {
-                    log.crit("error building AttributeExtractor: %s", ex.what());
-                }
-            }
-
-            child = XMLHelper::getFirstChildElement(e,_AttributeFilter);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building AttributeFilter of type %s...",type.get());
-                try {
-                    m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);
-                }
-                catch (exception& ex) {
-                    log.crit("error building AttributeFilter: %s", ex.what());
-                }
-            }
-
-            child = XMLHelper::getFirstChildElement(e,_AttributeResolver);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building AttributeResolver of type %s...",type.get());
-                try {
-                    m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);
-                }
-                catch (exception& ex) {
-                    log.crit("error building AttributeResolver: %s", ex.what());
-                }
-            }
-
-            if (m_unsetHeaders.empty()) {
-                vector<string> unsetHeaders;
-                if (m_attrExtractor) {
-                    Locker extlock(m_attrExtractor);
-                    m_attrExtractor->getAttributeIds(unsetHeaders);
-                }
-                else if (m_base && m_base->m_attrExtractor) {
-                    Locker extlock(m_base->m_attrExtractor);
-                    m_base->m_attrExtractor->getAttributeIds(unsetHeaders);
-                }
-                if (m_attrResolver) {
-                    Locker reslock(m_attrResolver);
-                    m_attrResolver->getAttributeIds(unsetHeaders);
-                }
-                else if (m_base && m_base->m_attrResolver) {
-                    Locker extlock(m_base->m_attrResolver);
-                    m_base->m_attrResolver->getAttributeIds(unsetHeaders);
-                }
-                if (!unsetHeaders.empty()) {
-                    string transformedprefix(m_attributePrefix.second);
-                    const char* pch;
-                    pair<bool,const char*> prefix = getString("metadataAttributePrefix");
-                    if (prefix.first) {
-                        pch = prefix.second;
-                        while (*pch) {
-                            transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');
-                            pch++;
-                        }
-                    }
-                    for (vector<string>::const_iterator hdr = unsetHeaders.begin(); hdr!=unsetHeaders.end(); ++hdr) {
-                        string transformed;
-                        pch = hdr->c_str();
-                        while (*pch) {
-                            transformed += (isalnum(*pch) ? toupper(*pch) : '_');
-                            pch++;
-                        }
-                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));
-                        if (prefix.first)
-                            m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));
-                    }
-                }
-                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));
-            }
-        }
-
-        if (conf.isEnabled(SPConfig::Credentials)) {
-            child = XMLHelper::getFirstChildElement(e,_CredentialResolver);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building CredentialResolver of type %s...",type.get());
-                try {
-                    m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);
-                }
-                catch (exception& ex) {
-                    log.crit("error building CredentialResolver: %s", ex.what());
-                }
-            }
-        }
-
-        // Finally, load relying parties.
-        child = XMLHelper::getFirstChildElement(e,RelyingParty);
-        while (child) {
-            auto_ptr<DOMPropertySet> rp(new DOMPropertySet());
-            rp->load(child,NULL,this);
-            rp->setParent(this);
-            m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();
-            child = XMLHelper::getNextSiblingElement(child,RelyingParty);
-        }
-#endif
-
-        // Out of process only, we register a listener endpoint.
-        if (!conf.isEnabled(SPConfig::InProcess)) {
-            ListenerService* listener = sp->getListenerService(false);
-            if (listener) {
-                string addr=string(getId()) + "::getHeaders::Application";
-                listener->regListener(addr.c_str(),this);
-            }
-            else
-                log.info("no ListenerService available, Application remoting disabled");
-        }
-    }
-    catch (exception&) {
-        cleanup();
-        throw;
-    }
-#ifndef _DEBUG
-    catch (...) {
-        cleanup();
-        throw;
-    }
-#endif
-}
-
-void XMLApplication::cleanup()
-{
-    ListenerService* listener=getServiceProvider().getListenerService(false);
-    if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
-        string addr=string(getId()) + "::getHeaders::Application";
-        listener->unregListener(addr.c_str(),this);
-    }
-    for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());
-    m_handlers.clear();
-#ifndef SHIBSP_LITE
-    for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());
-    m_partyMap.clear();
-    delete m_credResolver;
-    m_credResolver = NULL;
-    delete m_attrResolver;
-    m_attrResolver = NULL;
-    delete m_attrFilter;
-    m_attrFilter = NULL;
-    delete m_attrExtractor;
-    m_attrExtractor = NULL;
-    delete m_trust;
-    m_trust = NULL;
-    delete m_metadata;
-    m_metadata = NULL;
-#endif
-}
-
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-short
-#else
-DOMNodeFilter::FilterAction
-#endif
-XMLApplication::acceptNode(const DOMNode* node) const
-{
-    const XMLCh* name=node->getLocalName();
-    if (XMLString::equals(name,ApplicationOverride) ||
-        XMLString::equals(name,_Audience) ||
-        XMLString::equals(name,Notify) ||
-        XMLString::equals(name,_Handler) ||
-        XMLString::equals(name,_AssertionConsumerService) ||
-        XMLString::equals(name,_ArtifactResolutionService) ||
-        XMLString::equals(name,_LogoutInitiator) ||
-        XMLString::equals(name,_ManageNameIDService) ||
-        XMLString::equals(name,_SessionInitiator) ||
-        XMLString::equals(name,_SingleLogoutService) ||
-        XMLString::equals(name,RelyingParty) ||
-        XMLString::equals(name,_MetadataProvider) ||
-        XMLString::equals(name,_TrustEngine) ||
-        XMLString::equals(name,_CredentialResolver) ||
-        XMLString::equals(name,_AttributeFilter) ||
-        XMLString::equals(name,_AttributeExtractor) ||
-        XMLString::equals(name,_AttributeResolver))
-        return FILTER_REJECT;
-
-    return FILTER_ACCEPT;
-}
-
-#ifndef SHIBSP_LITE
-
-const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provider) const
-{
-    if (!provider)
-        return this;
-
-    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());
-    if (i!=m_partyMap.end())
-        return i->second;
-    const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());
-    while (group) {
-        if (group->getName()) {
-            i=m_partyMap.find(group->getName());
-            if (i!=m_partyMap.end())
-                return i->second;
-        }
-        group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());
-    }
-    return this;
-}
-
-const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const
-{
-    if (!entityID)
-        return this;
-
-    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);
-    if (i!=m_partyMap.end())
-        return i->second;
-    return this;
-}
-
-#endif
-
-string XMLApplication::getNotificationURL(const char* resource, bool front, unsigned int index) const
-{
-    const vector<string>& locs = front ? m_frontLogout : m_backLogout;
-    if (locs.empty())
-        return m_base ? m_base->getNotificationURL(resource, front, index) : string();
-    else if (index >= locs.size())
-        return string();
-
-#ifdef HAVE_STRCASECMP
-    if (!resource || (strncasecmp(resource,"http://",7) && strncasecmp(resource,"https://",8)))
-#else
-    if (!resource || (strnicmp(resource,"http://",7) && strnicmp(resource,"https://",8)))
-#endif
-        throw ConfigurationException("Request URL was not absolute.");
-
-    const char* handler=locs[index].c_str();
-
-    // Should never happen...
-    if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))
-        throw ConfigurationException(
-            "Invalid Location property ($1) in Notify element for Application ($2)",
-            params(2, handler ? handler : "null", getId())
-            );
-
-    // The "Location" property can be in one of three formats:
-    //
-    // 1) a full URI:       http://host/foo/bar
-    // 2) a hostless URI:   http:///foo/bar
-    // 3) a relative path:  /foo/bar
-    //
-    // #  Protocol  Host        Path
-    // 1  handler   handler     handler
-    // 2  handler   resource    handler
-    // 3  resource  resource    handler
-
-    const char* path = NULL;
-
-    // Decide whether to use the handler or the resource for the "protocol"
-    const char* prot;
-    if (*handler != '/') {
-        prot = handler;
-    }
-    else {
-        prot = resource;
-        path = handler;
-    }
-
-    // break apart the "protocol" string into protocol, host, and "the rest"
-    const char* colon=strchr(prot,':');
-    colon += 3;
-    const char* slash=strchr(colon,'/');
-    if (!path)
-        path = slash;
-
-    // Compute the actual protocol and store.
-    string notifyURL(prot, colon-prot);
-
-    // create the "host" from either the colon/slash or from the target string
-    // If prot == handler then we're in either #1 or #2, else #3.
-    // If slash == colon then we're in #2.
-    if (prot != handler || slash == colon) {
-        colon = strchr(resource, ':');
-        colon += 3;      // Get past the ://
-        slash = strchr(colon, '/');
-    }
-    string host(colon, (slash ? slash-colon : strlen(colon)));
-
-    // Build the URL
-    notifyURL += host + path;
-    return notifyURL;
-}
-
-void XMLApplication::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const
-{
-    if (!m_attributePrefix.first.empty()) {
-        string temp = m_attributePrefix.first + rawname;
-        string temp2 = m_attributePrefix.second + (cginame + 5);
-        request.clearHeader(temp.c_str(), temp2.c_str());
-    }
-    else if (m_base) {
-        m_base->clearHeader(request, rawname, cginame);
-    }
-    else {
-        request.clearHeader(rawname, cginame);
-    }
-}
-
-void XMLApplication::setHeader(SPRequest& request, const char* name, const char* value) const
-{
-    if (!m_attributePrefix.first.empty()) {
-        string temp = m_attributePrefix.first + name;
-        request.setHeader(temp.c_str(), value);
-    }
-    else if (m_base) {
-        m_base->setHeader(request, name, value);
-    }
-    else {
-        request.setHeader(name, value);
-    }
-}
-
-string XMLApplication::getSecureHeader(const SPRequest& request, const char* name) const
-{
-    if (!m_attributePrefix.first.empty()) {
-        string temp = m_attributePrefix.first + name;
-        return request.getSecureHeader(temp.c_str());
-    }
-    else if (m_base) {
-        return m_base->getSecureHeader(request,name);
-    }
-    else {
-        return request.getSecureHeader(name);
-    }
-}
-
-const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const
-{
-    if (m_sessionInitDefault) return m_sessionInitDefault;
-    return m_base ? m_base->getDefaultSessionInitiator() : NULL;
-}
-
-const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const
-{
-    map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);
-    if (i!=m_sessionInitMap.end()) return i->second;
-    return m_base ? m_base->getSessionInitiatorById(id) : NULL;
-}
-
-const Handler* XMLApplication::getDefaultAssertionConsumerService() const
-{
-    if (m_acsDefault) return m_acsDefault;
-    return m_base ? m_base->getDefaultAssertionConsumerService() : NULL;
-}
-
-const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const
-{
-    map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);
-    if (i!=m_acsIndexMap.end()) return i->second;
-    return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;
-}
-
-const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const
-{
-    ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);
-    if (i!=m_acsBindingMap.end())
-        return i->second;
-    return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;
-}
-
-const Handler* XMLApplication::getHandler(const char* path) const
-{
-    string wrap(path);
-    wrap = wrap.substr(0,wrap.find(';'));
-    map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));
-    if (i!=m_handlerMap.end())
-        return i->second;
-    return m_base ? m_base->getHandler(path) : NULL;
-}
-
-void XMLApplication::getHandlers(vector<const Handler*>& handlers) const
-{
-    handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());
-    if (m_base) {
-        for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {
-            if (m_handlerMap.count(h->first) == 0)
-                handlers.push_back(h->second);
-        }
-    }
-}
-
-#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE
-short
-#else
-DOMNodeFilter::FilterAction
-#endif
-XMLConfigImpl::acceptNode(const DOMNode* node) const
-{
-    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))
-        return FILTER_ACCEPT;
-    const XMLCh* name=node->getLocalName();
-    if (XMLString::equals(name,ApplicationDefaults) ||
-        XMLString::equals(name,_ArtifactMap) ||
-        XMLString::equals(name,_Extensions) ||
-        XMLString::equals(name,Listener) ||
-        XMLString::equals(name,_RequestMapper) ||
-        XMLString::equals(name,_ReplayCache) ||
-        XMLString::equals(name,SecurityPolicies) ||
-        XMLString::equals(name,_SessionCache) ||
-        XMLString::equals(name,Site) ||
-        XMLString::equals(name,_StorageService) ||
-        XMLString::equals(name,TCPListener) ||
-        XMLString::equals(name,TransportOption) ||
-        XMLString::equals(name,UnixListener))
-        return FILTER_REJECT;
-
-    return FILTER_ACCEPT;
-}
-
-void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log)
-{
-    const DOMElement* exts=XMLHelper::getFirstChildElement(e,_Extensions);
-    if (exts) {
-        exts=XMLHelper::getFirstChildElement(exts,Library);
-        while (exts) {
-            auto_ptr_char path(exts->getAttributeNS(NULL,_path));
-            try {
-                if (path.get()) {
-                    if (!XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts))
-                        throw ConfigurationException("XMLToolingConfig::load_library failed.");
-                    log.debug("loaded %s extension library (%s)", label, path.get());
-                }
-            }
-            catch (exception& e) {
-                const XMLCh* fatal=exts->getAttributeNS(NULL,_fatal);
-                if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) {
-                    log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what());
-                    throw;
-                }
-                else {
-                    log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what());
-                }
-            }
-            exts=XMLHelper::getNextSiblingElement(exts,Library);
-        }
-    }
-}
-
-XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)
-    : m_requestMapper(NULL), m_outer(outer), m_document(NULL)
-{
-#ifdef _DEBUG
-    xmltooling::NDC ndc("XMLConfigImpl");
-#endif
-
-    try {
-        SPConfig& conf=SPConfig::getConfig();
-#ifndef SHIBSP_LITE
-        SAMLConfig& samlConf=SAMLConfig::getConfig();
-#endif
-        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();
-        const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);
-        const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess);
-
-        // Initialize log4cpp manually in order to redirect log messages as soon as possible.
-        if (conf.isEnabled(SPConfig::Logging)) {
-            const XMLCh* logconf=NULL;
-            if (conf.isEnabled(SPConfig::OutOfProcess))
-                logconf=SHAR->getAttributeNS(NULL,logger);
-            else if (conf.isEnabled(SPConfig::InProcess))
-                logconf=SHIRE->getAttributeNS(NULL,logger);
-            if (!logconf || !*logconf)
-                logconf=e->getAttributeNS(NULL,logger);
-            if (logconf && *logconf) {
-                auto_ptr_char logpath(logconf);
-                log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());
-                if (!XMLToolingConfig::getConfig().log_config(logpath.get()))
-                    log.crit("failed to load new logging configuration from (%s)", logpath.get());
-            }
-
-#ifndef SHIBSP_LITE
-            if (first)
-                m_outer->m_tranLog = new TransactionLog();
-#endif
-        }
-
-        // Re-log library versions now that logging is set up.
-#ifndef SHIBSP_LITE
-        log.info(
-            "Library versions: Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",
-            XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, OPENSAML_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT
-            );
-#else
-        log.info(
-            "Library versions: Xerces-C %s, XMLTooling-C %s, Shibboleth %s",
-            XERCES_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT
-            );
-#endif
-
-        // First load any property sets.
-        load(e,NULL,this);
-
-        const DOMElement* child;
-        string plugtype;
-
-        // Much of the processing can only occur on the first instantiation.
-        if (first) {
-            // Set clock skew.
-            pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");
-            if (skew.first)
-                xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));
-
-            pair<bool,const char*> unsafe = getString("unsafeChars");
-            if (unsafe.first)
-                TemplateEngine::unsafe_chars = unsafe.second;
-
-            // Extensions
-            doExtensions(e, "global", log);
-            if (conf.isEnabled(SPConfig::OutOfProcess))
-                doExtensions(SHAR, "out of process", log);
-
-            if (conf.isEnabled(SPConfig::InProcess))
-                doExtensions(SHIRE, "in process", log);
-
-            // Instantiate the ListenerService and SessionCache objects.
-            if (conf.isEnabled(SPConfig::Listener)) {
-                child=XMLHelper::getFirstChildElement(e,UnixListener);
-                if (child)
-                    plugtype=UNIX_LISTENER_SERVICE;
-                else {
-                    child=XMLHelper::getFirstChildElement(e,TCPListener);
-                    if (child)
-                        plugtype=TCP_LISTENER_SERVICE;
-                    else {
-                        child=XMLHelper::getFirstChildElement(e,Listener);
-                        if (child) {
-                            auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                            if (type.get())
-                                plugtype=type.get();
-                        }
-                    }
-                }
-                if (child) {
-                    log.info("building ListenerService of type %s...", plugtype.c_str());
-                    m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);
-                }
-                else {
-                    log.fatal("can't build ListenerService, missing conf:Listener element?");
-                    throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?");
-                }
-            }
-
-#ifndef SHIBSP_LITE
-            if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {
-                m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));
-                m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));
-                m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));
-                m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));
-            }
-#endif
-
-            if (conf.isEnabled(SPConfig::Caching)) {
-                if (conf.isEnabled(SPConfig::OutOfProcess)) {
-#ifndef SHIBSP_LITE
-                    // First build any StorageServices.
-                    child=XMLHelper::getFirstChildElement(e,_StorageService);
-                    while (child) {
-                        auto_ptr_char id(child->getAttributeNS(NULL,_id));
-                        auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                        try {
-                            log.info("building StorageService (%s) of type %s...", id.get(), type.get());
-                            m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child);
-                        }
-                        catch (exception& ex) {
-                            log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what());
-                        }
-                        child=XMLHelper::getNextSiblingElement(child,_StorageService);
-                    }
-
-                    // Replay cache.
-                    StorageService* replaySS=NULL;
-                    child=XMLHelper::getFirstChildElement(e,_ReplayCache);
-                    if (child) {
-                        auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));
-                        if (ssid.get() && *ssid.get()) {
-                            if (m_outer->m_storage.count(ssid.get()))
-                                replaySS = m_outer->m_storage[ssid.get()];
-                            if (replaySS)
-                                log.info("building ReplayCache on top of StorageService (%s)...", ssid.get());
-                            else
-                                log.warn("unable to locate StorageService (%s) for ReplayCache, using dedicated in-memory instance", ssid.get());
-                        }
-                        xmlConf.setReplayCache(new ReplayCache(replaySS));
-                    }
-                    else {
-                        log.warn("no ReplayCache built, missing conf:ReplayCache element?");
-                    }
-
-                    // ArtifactMap
-                    child=XMLHelper::getFirstChildElement(e,_ArtifactMap);
-                    if (child) {
-                        auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));
-                        if (ssid.get() && *ssid.get() && m_outer->m_storage.count(ssid.get())) {
-                            log.info("building ArtifactMap on top of StorageService (%s)...", ssid.get());
-                            samlConf.setArtifactMap(new ArtifactMap(child, m_outer->m_storage[ssid.get()]));
-                        }
-                    }
-                    if (samlConf.getArtifactMap()==NULL) {
-                        log.info("building in-memory ArtifactMap...");
-                        samlConf.setArtifactMap(new ArtifactMap(child));
-                    }
-#endif
-                }
-                child=XMLHelper::getFirstChildElement(e,_SessionCache);
-                if (child) {
-                    auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                    log.info("building SessionCache of type %s...",type.get());
-                    m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(), child);
-                }
-                else {
-                    log.fatal("can't build SessionCache, missing conf:SessionCache element?");
-                    throw ConfigurationException("Can't build SessionCache, missing conf:SessionCache element?");
-                }
-            }
-        } // end of first-time-only stuff
-
-        // Back to the fully dynamic stuff...next up is the RequestMapper.
-        if (conf.isEnabled(SPConfig::RequestMapping)) {
-            child=XMLHelper::getFirstChildElement(e,_RequestMapper);
-            if (child) {
-                auto_ptr_char type(child->getAttributeNS(NULL,_type));
-                log.info("building RequestMapper of type %s...",type.get());
-                m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);
-            }
-            else {
-                log.fatal("can't build RequestMapper, missing conf:RequestMapper element?");
-                throw ConfigurationException("Can't build RequestMapper, missing conf:RequestMapper element?");
-            }
-        }
-
-#ifndef SHIBSP_LITE
-        // Load security policies.
-        child = XMLHelper::getLastChildElement(e,SecurityPolicies);
-        if (child) {
-            PolicyNodeFilter filter;
-            child = XMLHelper::getFirstChildElement(child,Policy);
-            while (child) {
-                auto_ptr_char id(child->getAttributeNS(NULL,_id));
-                pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];
-                rules.first = NULL;
-                auto_ptr<DOMPropertySet> settings(new DOMPropertySet());
-                settings->load(child, NULL, &filter);
-                rules.first = settings.release();
-
-                // Process PolicyRule elements.
-                const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);
-                while (rule) {
-                    auto_ptr_char type(rule->getAttributeNS(NULL,_type));
-                    try {
-                        rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
-                    }
-                    catch (exception& ex) {
-                        log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
-                    }
-                    rule = XMLHelper::getNextSiblingElement(rule,PolicyRule);
-                }
-
-                if (rules.second.size() == 0) {
-                    // Process Rule elements.
-                    log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");
-                    rule = XMLHelper::getFirstChildElement(child,Rule);
-                    while (rule) {
-                        auto_ptr_char type(rule->getAttributeNS(NULL,_type));
-                        try {
-                            rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));
-                        }
-                        catch (exception& ex) {
-                            log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());
-                        }
-                        rule = XMLHelper::getNextSiblingElement(rule,Rule);
-                    }
-
-                    // Manually add a basic Conditions rule.
-                    log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());
-                    rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL));
-                }
-
-                child = XMLHelper::getNextSiblingElement(child,Policy);
-            }
-        }
-
-        // Process TransportOption elements.
-        child = XMLHelper::getLastChildElement(e,TransportOption);
-        while (child) {
-            if (child->hasChildNodes()) {
-                auto_ptr_char provider(child->getAttributeNS(NULL,_provider));
-                auto_ptr_char option(child->getAttributeNS(NULL,_option));
-                auto_ptr_char value(child->getFirstChild()->getNodeValue());
-                if (provider.get() && *provider.get() && option.get() && *option.get() && value.get() && *value.get()) {
-                    m_transportOptions.push_back(make_pair(string(provider.get()), make_pair(string(option.get()), string(value.get()))));
-                }
-            }
-            child = XMLHelper::getPreviousSiblingElement(child,TransportOption);
-        }
-#endif
-
-        // Load the default application. This actually has a fixed ID of "default". ;-)
-        child=XMLHelper::getLastChildElement(e,ApplicationDefaults);
-        if (!child) {
-            log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");
-            throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");
-        }
-        XMLApplication* defapp=new XMLApplication(m_outer,child);
-        m_appmap[defapp->getId()]=defapp;
-
-        // Load any overrides.
-        child = XMLHelper::getFirstChildElement(child,ApplicationOverride);
-        while (child) {
-            auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer,child,defapp));
-            if (m_appmap.count(iapp->getId()))
-                log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());
-            else {
-                const char* iappid=iapp->getId();
-                m_appmap[iappid]=iapp.release();
-            }
-
-            child = XMLHelper::getNextSiblingElement(child,ApplicationOverride);
-        }
-    }
-    catch (exception&) {
-        cleanup();
-        throw;
-    }
-}
-
-XMLConfigImpl::~XMLConfigImpl()
-{
-    cleanup();
-}
-
-void XMLConfigImpl::cleanup()
-{
-    for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());
-    m_appmap.clear();
-#ifndef SHIBSP_LITE
-    for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i=m_policyMap.begin(); i!=m_policyMap.end(); ++i) {
-        delete i->second.first;
-        for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());
-    }
-    m_policyMap.clear();
-#endif
-    delete m_requestMapper;
-    m_requestMapper = NULL;
-    if (m_document)
-        m_document->release();
-    m_document = NULL;
-}
-
-#ifndef SHIBSP_LITE
-void XMLConfig::receive(DDF& in, ostream& out)
-{
-    if (!strcmp(in.name(), "get::RelayState")) {
-        const char* id = in["id"].string();
-        const char* key = in["key"].string();
-        if (!id || !key)
-            throw ListenerException("Required parameters missing for RelayState recovery.");
-
-        string relayState;
-        StorageService* storage = getStorageService(id);
-        if (storage) {
-            if (storage->readString("RelayState",key,&relayState)>0) {
-                if (in["clear"].integer())
-                    storage->deleteString("RelayState",key);
-            }
-        }
-        else {
-            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
-                "Storage-backed RelayState with invalid StorageService ID (%s)", id
-                );
-        }
-
-        // Repack for return to caller.
-        DDF ret=DDF(NULL).unsafe_string(relayState.c_str());
-        DDFJanitor jret(ret);
-        out << ret;
-    }
-    else if (!strcmp(in.name(), "set::RelayState")) {
-        const char* id = in["id"].string();
-        const char* value = in["value"].string();
-        if (!id || !value)
-            throw ListenerException("Required parameters missing for RelayState creation.");
-
-        string rsKey;
-        StorageService* storage = getStorageService(id);
-        if (storage) {
-            SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
-            rsKey = SAMLArtifact::toHex(rsKey);
-            storage->createString("RelayState", rsKey.c_str(), value, time(NULL) + 600);
-        }
-        else {
-            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
-                "Storage-backed RelayState with invalid StorageService ID (%s)", id
-                );
-        }
-
-        // Repack for return to caller.
-        DDF ret=DDF(NULL).string(rsKey.c_str());
-        DDFJanitor jret(ret);
-        out << ret;
-    }
-    else if (!strcmp(in.name(), "get::PostData")) {
-        const char* id = in["id"].string();
-        const char* key = in["key"].string();
-        if (!id || !key)
-            throw ListenerException("Required parameters missing for PostData recovery.");
-
-        string postData;
-        StorageService* storage = getStorageService(id);
-        if (storage) {
-            if (storage->readString("PostData",key,&postData) > 0) {
-                storage->deleteString("PostData",key);
-            }
-        }
-        else {
-            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
-                "Storage-backed PostData with invalid StorageService ID (%s)", id
-                );
-        }
-        // If the data's empty, we'll send nothing back.
-        // If not, we don't need to round trip it, just send back the serialized DDF list.
-        if (postData.empty()) {
-            DDF ret(NULL);
-            DDFJanitor jret(ret);
-            out << ret;
-        }
-        else {
-            out << postData;
-        }
-    }
-    else if (!strcmp(in.name(), "set::PostData")) {
-        const char* id = in["id"].string();
-        if (!id || !in["parameters"].islist())
-            throw ListenerException("Required parameters missing for PostData creation.");
-
-        string rsKey;
-        StorageService* storage = getStorageService(id);
-        if (storage) {
-            SAMLConfig::getConfig().generateRandomBytes(rsKey,20);
-            rsKey = SAMLArtifact::toHex(rsKey);
-            ostringstream params;
-            params << in["parameters"];
-            storage->createString("PostData", rsKey.c_str(), params.str().c_str(), time(NULL) + 600);
-        }
-        else {
-            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(
-                "Storage-backed PostData with invalid StorageService ID (%s)", id
-                );
-        }
-
-        // Repack for return to caller.
-        DDF ret=DDF(NULL).string(rsKey.c_str());
-        DDFJanitor jret(ret);
-        out << ret;
-    }
-}
-#endif
-
-pair<bool,DOMElement*> XMLConfig::load()
-{
-    // Load from source using base class.
-    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();
-
-    // If we own it, wrap it.
-    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);
-
-    XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this,m_log);
-
-    // If we held the document, transfer it to the impl. If we didn't, it's a no-op.
-    impl->setDocument(docjanitor.release());
-
-    delete m_impl;
-    m_impl = impl;
-
-    return make_pair(false,(DOMElement*)NULL);
-}
+/*\r
+ *  Copyright 2001-2009 Internet2\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+/**\r
+ * XMLServiceProvider.cpp\r
+ *\r
+ * XML-based SP configuration and mgmt.\r
+ */\r
+\r
+#include "internal.h"\r
+#include "exceptions.h"\r
+#include "version.h"\r
+#include "AccessControl.h"\r
+#include "Application.h"\r
+#include "RequestMapper.h"\r
+#include "ServiceProvider.h"\r
+#include "SessionCache.h"\r
+#include "SPConfig.h"\r
+#include "SPRequest.h"\r
+#include "handler/SessionInitiator.h"\r
+#include "remoting/ListenerService.h"\r
+#include "util/DOMPropertySet.h"\r
+#include "util/SPConstants.h"\r
+\r
+#if defined(XMLTOOLING_LOG4SHIB)\r
+# include <log4shib/PropertyConfigurator.hh>\r
+#elif defined(XMLTOOLING_LOG4CPP)\r
+# include <log4cpp/PropertyConfigurator.hh>\r
+#else\r
+# error "Supported logging library not available."\r
+#endif\r
+#include <algorithm>\r
+#include <xercesc/util/XMLUniDefs.hpp>\r
+#include <xmltooling/XMLToolingConfig.h>\r
+#include <xmltooling/version.h>\r
+#include <xmltooling/util/NDC.h>\r
+#include <xmltooling/util/ReloadableXMLFile.h>\r
+#include <xmltooling/util/TemplateEngine.h>\r
+#include <xmltooling/util/XMLHelper.h>\r
+\r
+#ifndef SHIBSP_LITE\r
+# include "TransactionLog.h"\r
+# include "attribute/filtering/AttributeFilter.h"\r
+# include "attribute/resolver/AttributeExtractor.h"\r
+# include "attribute/resolver/AttributeResolver.h"\r
+# include "security/PKIXTrustEngine.h"\r
+# include <saml/SAMLConfig.h>\r
+# include <saml/version.h>\r
+# include <saml/binding/ArtifactMap.h>\r
+# include <saml/binding/SAMLArtifact.h>\r
+# include <saml/binding/SecurityPolicyRule.h>\r
+# include <saml/saml1/core/Assertions.h>\r
+# include <saml/saml2/core/Assertions.h>\r
+# include <saml/saml2/binding/SAML2ArtifactType0004.h>\r
+# include <saml/saml2/metadata/Metadata.h>\r
+# include <saml/saml2/metadata/MetadataProvider.h>\r
+# include <saml/util/SAMLConstants.h>\r
+# include <xmltooling/security/CredentialResolver.h>\r
+# include <xmltooling/security/SecurityHelper.h>\r
+# include <xmltooling/security/TrustEngine.h>\r
+# include <xmltooling/util/ReplayCache.h>\r
+# include <xmltooling/util/StorageService.h>\r
+using namespace opensaml::saml2;\r
+using namespace opensaml::saml2p;\r
+using namespace opensaml::saml2md;\r
+using namespace opensaml;\r
+#else\r
+# include "lite/SAMLConstants.h"\r
+#endif\r
+\r
+using namespace shibsp;\r
+using namespace xmltooling;\r
+using namespace std;\r
+\r
+#ifndef min\r
+# define min(a,b)            (((a) < (b)) ? (a) : (b))\r
+#endif\r
+\r
+namespace {\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( push )\r
+    #pragma warning( disable : 4250 )\r
+#endif\r
+\r
+    static vector<const Handler*> g_noHandlers;\r
+\r
+    // Application configuration wrapper\r
+    class SHIBSP_DLLLOCAL XMLApplication : public Application, public Remoted, public DOMPropertySet, public DOMNodeFilter\r
+    {\r
+    public:\r
+        XMLApplication(const ServiceProvider*, const DOMElement* e, const XMLApplication* base=NULL);\r
+        ~XMLApplication() { cleanup(); }\r
+\r
+        const char* getHash() const {return m_hash.c_str();}\r
+\r
+#ifndef SHIBSP_LITE\r
+        SAMLArtifact* generateSAML1Artifact(const EntityDescriptor* relyingParty) const {\r
+            throw ConfigurationException("No support for SAML 1.x artifact generation.");\r
+        }\r
+        SAML2Artifact* generateSAML2Artifact(const EntityDescriptor* relyingParty) const {\r
+            pair<bool,int> index = make_pair(false,0);\r
+            const PropertySet* props = getRelyingParty(relyingParty);\r
+            index = props->getInt("artifactEndpointIndex");\r
+            if (!index.first)\r
+                index = getArtifactEndpointIndex();\r
+            pair<bool,const char*> entityID = props->getString("entityID");\r
+            return new SAML2ArtifactType0004(\r
+                SecurityHelper::doHash("SHA1", entityID.second, strlen(entityID.second), false),\r
+                index.first ? index.second : 1\r
+                );\r
+        }\r
+\r
+        MetadataProvider* getMetadataProvider(bool required=true) const {\r
+            if (required && !m_base && !m_metadata)\r
+                throw ConfigurationException("No MetadataProvider available.");\r
+            return (!m_metadata && m_base) ? m_base->getMetadataProvider() : m_metadata;\r
+        }\r
+        TrustEngine* getTrustEngine(bool required=true) const {\r
+            if (required && !m_base && !m_trust)\r
+                throw ConfigurationException("No TrustEngine available.");\r
+            return (!m_trust && m_base) ? m_base->getTrustEngine() : m_trust;\r
+        }\r
+        AttributeExtractor* getAttributeExtractor() const {\r
+            return (!m_attrExtractor && m_base) ? m_base->getAttributeExtractor() : m_attrExtractor;\r
+        }\r
+        AttributeFilter* getAttributeFilter() const {\r
+            return (!m_attrFilter && m_base) ? m_base->getAttributeFilter() : m_attrFilter;\r
+        }\r
+        AttributeResolver* getAttributeResolver() const {\r
+            return (!m_attrResolver && m_base) ? m_base->getAttributeResolver() : m_attrResolver;\r
+        }\r
+        CredentialResolver* getCredentialResolver() const {\r
+            return (!m_credResolver && m_base) ? m_base->getCredentialResolver() : m_credResolver;\r
+        }\r
+        const PropertySet* getRelyingParty(const EntityDescriptor* provider) const;\r
+        const PropertySet* getRelyingParty(const XMLCh* entityID) const;\r
+        const vector<const XMLCh*>* getAudiences() const {\r
+            return (m_audiences.empty() && m_base) ? m_base->getAudiences() : &m_audiences;\r
+        }\r
+#endif\r
+        string getNotificationURL(const char* resource, bool front, unsigned int index) const;\r
+\r
+        const vector<string>& getRemoteUserAttributeIds() const {\r
+            return (m_remoteUsers.empty() && m_base) ? m_base->getRemoteUserAttributeIds() : m_remoteUsers;\r
+        }\r
+\r
+        void clearHeader(SPRequest& request, const char* rawname, const char* cginame) const;\r
+        void setHeader(SPRequest& request, const char* name, const char* value) const;\r
+        string getSecureHeader(const SPRequest& request, const char* name) const;\r
+\r
+        const SessionInitiator* getDefaultSessionInitiator() const;\r
+        const SessionInitiator* getSessionInitiatorById(const char* id) const;\r
+        const Handler* getDefaultAssertionConsumerService() const;\r
+        const Handler* getAssertionConsumerServiceByIndex(unsigned short index) const;\r
+        const vector<const Handler*>& getAssertionConsumerServicesByBinding(const XMLCh* binding) const;\r
+        const Handler* getHandler(const char* path) const;\r
+        void getHandlers(vector<const Handler*>& handlers) const;\r
+\r
+        void receive(DDF& in, ostream& out) {\r
+            // Only current function is to return the headers to clear.\r
+            DDF header;\r
+            DDF ret=DDF(NULL).list();\r
+            DDFJanitor jret(ret);\r
+            for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i) {\r
+                header = DDF(i->first.c_str()).string(i->second.c_str());\r
+                ret.add(header);\r
+            }\r
+            out << ret;\r
+        }\r
+\r
+        // Provides filter to exclude special config elements.\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+        short\r
+#else\r
+        FilterAction\r
+#endif\r
+        acceptNode(const DOMNode* node) const;\r
+\r
+    private:\r
+        void cleanup();\r
+        const XMLApplication* m_base;\r
+        string m_hash;\r
+        std::pair<std::string,std::string> m_attributePrefix;\r
+#ifndef SHIBSP_LITE\r
+        MetadataProvider* m_metadata;\r
+        TrustEngine* m_trust;\r
+        AttributeExtractor* m_attrExtractor;\r
+        AttributeFilter* m_attrFilter;\r
+        AttributeResolver* m_attrResolver;\r
+        CredentialResolver* m_credResolver;\r
+        vector<const XMLCh*> m_audiences;\r
+\r
+        // RelyingParty properties\r
+        map<xstring,PropertySet*> m_partyMap;\r
+#endif\r
+        vector<string> m_remoteUsers,m_frontLogout,m_backLogout;\r
+\r
+        // manage handler objects\r
+        vector<Handler*> m_handlers;\r
+\r
+        // maps location (path info) to applicable handlers\r
+        map<string,const Handler*> m_handlerMap;\r
+\r
+        // maps unique indexes to consumer services\r
+        map<unsigned int,const Handler*> m_acsIndexMap;\r
+\r
+        // pointer to default consumer service\r
+        const Handler* m_acsDefault;\r
+\r
+        // maps binding strings to supporting consumer service(s)\r
+        typedef map<xstring,vector<const Handler*> > ACSBindingMap;\r
+        ACSBindingMap m_acsBindingMap;\r
+\r
+        // pointer to default session initiator\r
+        const SessionInitiator* m_sessionInitDefault;\r
+\r
+        // maps unique ID strings to session initiators\r
+        map<string,const SessionInitiator*> m_sessionInitMap;\r
+\r
+        // pointer to default artifact resolution service\r
+        const Handler* m_artifactResolutionDefault;\r
+\r
+        pair<bool,int> getArtifactEndpointIndex() const {\r
+            if (m_artifactResolutionDefault) return m_artifactResolutionDefault->getInt("index");\r
+            return m_base ? m_base->getArtifactEndpointIndex() : make_pair(false,0);\r
+        }\r
+    };\r
+\r
+    // Top-level configuration implementation\r
+    class SHIBSP_DLLLOCAL XMLConfig;\r
+    class SHIBSP_DLLLOCAL XMLConfigImpl : public DOMPropertySet, public DOMNodeFilter\r
+    {\r
+    public:\r
+        XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log);\r
+        ~XMLConfigImpl();\r
+\r
+        RequestMapper* m_requestMapper;\r
+        map<string,Application*> m_appmap;\r
+#ifndef SHIBSP_LITE\r
+        map< string,pair< PropertySet*,vector<const SecurityPolicyRule*> > > m_policyMap;\r
+        vector< pair< string, pair<string,string> > > m_transportOptions;\r
+#endif\r
+\r
+        // Provides filter to exclude special config elements.\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+        short\r
+#else\r
+        FilterAction\r
+#endif\r
+        acceptNode(const DOMNode* node) const;\r
+\r
+        void setDocument(DOMDocument* doc) {\r
+            m_document = doc;\r
+        }\r
+\r
+    private:\r
+        void doExtensions(const DOMElement* e, const char* label, Category& log);\r
+        void cleanup();\r
+\r
+        const XMLConfig* m_outer;\r
+        DOMDocument* m_document;\r
+    };\r
+\r
+    class SHIBSP_DLLLOCAL XMLConfig : public ServiceProvider, public ReloadableXMLFile\r
+#ifndef SHIBSP_LITE\r
+        ,public Remoted\r
+#endif\r
+    {\r
+    public:\r
+        XMLConfig(const DOMElement* e) : ReloadableXMLFile(e, Category::getInstance(SHIBSP_LOGCAT".Config")),\r
+            m_impl(NULL), m_listener(NULL), m_sessionCache(NULL)\r
+#ifndef SHIBSP_LITE\r
+            , m_tranLog(NULL)\r
+#endif\r
+        {\r
+        }\r
+\r
+        void init() {\r
+            load();\r
+        }\r
+\r
+        ~XMLConfig() {\r
+            delete m_impl;\r
+            delete m_sessionCache;\r
+            delete m_listener;\r
+#ifndef SHIBSP_LITE\r
+            delete m_tranLog;\r
+            SAMLConfig::getConfig().setArtifactMap(NULL);\r
+            XMLToolingConfig::getConfig().setReplayCache(NULL);\r
+            for_each(m_storage.begin(), m_storage.end(), cleanup_pair<string,StorageService>());\r
+#endif\r
+        }\r
+\r
+        // PropertySet\r
+        const PropertySet* getParent() const { return m_impl->getParent(); }\r
+        void setParent(const PropertySet* parent) {return m_impl->setParent(parent);}\r
+        pair<bool,bool> getBool(const char* name, const char* ns=NULL) const {return m_impl->getBool(name,ns);}\r
+        pair<bool,const char*> getString(const char* name, const char* ns=NULL) const {return m_impl->getString(name,ns);}\r
+        pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const {return m_impl->getXMLString(name,ns);}\r
+        pair<bool,unsigned int> getUnsignedInt(const char* name, const char* ns=NULL) const {return m_impl->getUnsignedInt(name,ns);}\r
+        pair<bool,int> getInt(const char* name, const char* ns=NULL) const {return m_impl->getInt(name,ns);}\r
+        void getAll(map<string,const char*>& properties) const {return m_impl->getAll(properties);}\r
+        const PropertySet* getPropertySet(const char* name, const char* ns="urn:mace:shibboleth:2.0:native:sp:config") const {return m_impl->getPropertySet(name,ns);}\r
+        const DOMElement* getElement() const {return m_impl->getElement();}\r
+\r
+        // ServiceProvider\r
+#ifndef SHIBSP_LITE\r
+        // Remoted\r
+        void receive(DDF& in, ostream& out);\r
+\r
+        TransactionLog* getTransactionLog() const {\r
+            if (m_tranLog)\r
+                return m_tranLog;\r
+            throw ConfigurationException("No TransactionLog available.");\r
+        }\r
+\r
+        StorageService* getStorageService(const char* id) const {\r
+            if (id) {\r
+                map<string,StorageService*>::const_iterator i=m_storage.find(id);\r
+                if (i!=m_storage.end())\r
+                    return i->second;\r
+            }\r
+            return NULL;\r
+        }\r
+#endif\r
+\r
+        ListenerService* getListenerService(bool required=true) const {\r
+            if (required && !m_listener)\r
+                throw ConfigurationException("No ListenerService available.");\r
+            return m_listener;\r
+        }\r
+\r
+        SessionCache* getSessionCache(bool required=true) const {\r
+            if (required && !m_sessionCache)\r
+                throw ConfigurationException("No SessionCache available.");\r
+            return m_sessionCache;\r
+        }\r
+\r
+        RequestMapper* getRequestMapper(bool required=true) const {\r
+            if (required && !m_impl->m_requestMapper)\r
+                throw ConfigurationException("No RequestMapper available.");\r
+            return m_impl->m_requestMapper;\r
+        }\r
+\r
+        const Application* getApplication(const char* applicationId) const {\r
+            map<string,Application*>::const_iterator i=m_impl->m_appmap.find(applicationId);\r
+            return (i!=m_impl->m_appmap.end()) ? i->second : NULL;\r
+        }\r
+\r
+#ifndef SHIBSP_LITE\r
+        const PropertySet* getPolicySettings(const char* id) const {\r
+            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
+            if (i!=m_impl->m_policyMap.end())\r
+                return i->second.first;\r
+            throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
+        }\r
+\r
+        const vector<const SecurityPolicyRule*>& getPolicyRules(const char* id) const {\r
+            map<string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::const_iterator i = m_impl->m_policyMap.find(id);\r
+            if (i!=m_impl->m_policyMap.end())\r
+                return i->second.second;\r
+            throw ConfigurationException("Security Policy ($1) not found, check <SecurityPolicies> element.", params(1,id));\r
+        }\r
+\r
+        bool setTransportOptions(SOAPTransport& transport) const {\r
+            bool ret = true;\r
+            vector< pair< string, pair<string,string> > >::const_iterator opt;\r
+            for (opt = m_impl->m_transportOptions.begin(); opt != m_impl->m_transportOptions.end(); ++opt) {\r
+                if (!transport.setProviderOption(opt->first.c_str(), opt->second.first.c_str(), opt->second.second.c_str())) {\r
+                    m_log.error("failed to set SOAPTransport option (%s)", opt->second.first.c_str());\r
+                    ret = false;\r
+                }\r
+            }\r
+            return ret;\r
+        }\r
+#endif\r
+\r
+    protected:\r
+        pair<bool,DOMElement*> load();\r
+\r
+    private:\r
+        friend class XMLConfigImpl;\r
+        XMLConfigImpl* m_impl;\r
+        mutable ListenerService* m_listener;\r
+        mutable SessionCache* m_sessionCache;\r
+#ifndef SHIBSP_LITE\r
+        mutable TransactionLog* m_tranLog;\r
+        mutable map<string,StorageService*> m_storage;\r
+#endif\r
+    };\r
+\r
+#if defined (_MSC_VER)\r
+    #pragma warning( pop )\r
+#endif\r
+\r
+    static const XMLCh ApplicationOverride[] =  UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,O,v,e,r,r,i,d,e);\r
+    static const XMLCh ApplicationDefaults[] =  UNICODE_LITERAL_19(A,p,p,l,i,c,a,t,i,o,n,D,e,f,a,u,l,t,s);\r
+    static const XMLCh _ArtifactMap[] =         UNICODE_LITERAL_11(A,r,t,i,f,a,c,t,M,a,p);\r
+    static const XMLCh _AttributeExtractor[] =  UNICODE_LITERAL_18(A,t,t,r,i,b,u,t,e,E,x,t,r,a,c,t,o,r);\r
+    static const XMLCh _AttributeFilter[] =     UNICODE_LITERAL_15(A,t,t,r,i,b,u,t,e,F,i,l,t,e,r);\r
+    static const XMLCh _AttributeResolver[] =   UNICODE_LITERAL_17(A,t,t,r,i,b,u,t,e,R,e,s,o,l,v,e,r);\r
+    static const XMLCh _AssertionConsumerService[] = UNICODE_LITERAL_24(A,s,s,e,r,t,i,o,n,C,o,n,s,u,m,e,r,S,e,r,v,i,c,e);\r
+    static const XMLCh _ArtifactResolutionService[] =UNICODE_LITERAL_25(A,r,t,i,f,a,c,t,R,e,s,o,l,u,t,i,o,n,S,e,r,v,i,c,e);\r
+    static const XMLCh _Audience[] =            UNICODE_LITERAL_8(A,u,d,i,e,n,c,e);\r
+    static const XMLCh Binding[] =              UNICODE_LITERAL_7(B,i,n,d,i,n,g);\r
+    static const XMLCh Channel[]=               UNICODE_LITERAL_7(C,h,a,n,n,e,l);\r
+    static const XMLCh _CredentialResolver[] =  UNICODE_LITERAL_18(C,r,e,d,e,n,t,i,a,l,R,e,s,o,l,v,e,r);\r
+    static const XMLCh _Extensions[] =          UNICODE_LITERAL_10(E,x,t,e,n,s,i,o,n,s);\r
+    static const XMLCh _fatal[] =               UNICODE_LITERAL_5(f,a,t,a,l);\r
+    static const XMLCh _Handler[] =             UNICODE_LITERAL_7(H,a,n,d,l,e,r);\r
+    static const XMLCh _id[] =                  UNICODE_LITERAL_2(i,d);\r
+    static const XMLCh InProcess[] =            UNICODE_LITERAL_9(I,n,P,r,o,c,e,s,s);\r
+    static const XMLCh Library[] =              UNICODE_LITERAL_7(L,i,b,r,a,r,y);\r
+    static const XMLCh Listener[] =             UNICODE_LITERAL_8(L,i,s,t,e,n,e,r);\r
+    static const XMLCh Location[] =             UNICODE_LITERAL_8(L,o,c,a,t,i,o,n);\r
+    static const XMLCh logger[] =               UNICODE_LITERAL_6(l,o,g,g,e,r);\r
+    static const XMLCh _LogoutInitiator[] =     UNICODE_LITERAL_15(L,o,g,o,u,t,I,n,i,t,i,a,t,o,r);\r
+    static const XMLCh _ManageNameIDService[] = UNICODE_LITERAL_19(M,a,n,a,g,e,N,a,m,e,I,D,S,e,r,v,i,c,e);\r
+    static const XMLCh _MetadataProvider[] =    UNICODE_LITERAL_16(M,e,t,a,d,a,t,a,P,r,o,v,i,d,e,r);\r
+    static const XMLCh Notify[] =               UNICODE_LITERAL_6(N,o,t,i,f,y);\r
+    static const XMLCh _option[] =              UNICODE_LITERAL_6(o,p,t,i,o,n);\r
+    static const XMLCh OutOfProcess[] =         UNICODE_LITERAL_12(O,u,t,O,f,P,r,o,c,e,s,s);\r
+    static const XMLCh _path[] =                UNICODE_LITERAL_4(p,a,t,h);\r
+    static const XMLCh Policy[] =               UNICODE_LITERAL_6(P,o,l,i,c,y);\r
+    static const XMLCh PolicyRule[] =           UNICODE_LITERAL_10(P,o,l,i,c,y,R,u,l,e);\r
+    static const XMLCh _provider[] =            UNICODE_LITERAL_8(p,r,o,v,i,d,e,r);\r
+    static const XMLCh RelyingParty[] =         UNICODE_LITERAL_12(R,e,l,y,i,n,g,P,a,r,t,y);\r
+    static const XMLCh _ReplayCache[] =         UNICODE_LITERAL_11(R,e,p,l,a,y,C,a,c,h,e);\r
+    static const XMLCh _RequestMapper[] =       UNICODE_LITERAL_13(R,e,q,u,e,s,t,M,a,p,p,e,r);\r
+    static const XMLCh Rule[] =                 UNICODE_LITERAL_4(R,u,l,e);\r
+    static const XMLCh SecurityPolicies[] =     UNICODE_LITERAL_16(S,e,c,u,r,i,t,y,P,o,l,i,c,i,e,s);\r
+    static const XMLCh _SessionCache[] =        UNICODE_LITERAL_12(S,e,s,s,i,o,n,C,a,c,h,e);\r
+    static const XMLCh _SessionInitiator[] =    UNICODE_LITERAL_16(S,e,s,s,i,o,n,I,n,i,t,i,a,t,o,r);\r
+    static const XMLCh _SingleLogoutService[] = UNICODE_LITERAL_19(S,i,n,g,l,e,L,o,g,o,u,t,S,e,r,v,i,c,e);\r
+    static const XMLCh Site[] =                 UNICODE_LITERAL_4(S,i,t,e);\r
+    static const XMLCh _StorageService[] =      UNICODE_LITERAL_14(S,t,o,r,a,g,e,S,e,r,v,i,c,e);\r
+    static const XMLCh TCPListener[] =          UNICODE_LITERAL_11(T,C,P,L,i,s,t,e,n,e,r);\r
+    static const XMLCh TransportOption[] =      UNICODE_LITERAL_15(T,r,a,n,s,p,o,r,t,O,p,t,i,o,n);\r
+    static const XMLCh _TrustEngine[] =         UNICODE_LITERAL_11(T,r,u,s,t,E,n,g,i,n,e);\r
+    static const XMLCh _type[] =                UNICODE_LITERAL_4(t,y,p,e);\r
+    static const XMLCh UnixListener[] =         UNICODE_LITERAL_12(U,n,i,x,L,i,s,t,e,n,e,r);\r
+\r
+#ifndef SHIBSP_LITE\r
+    class SHIBSP_DLLLOCAL PolicyNodeFilter : public DOMNodeFilter\r
+    {\r
+    public:\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+        short\r
+#else\r
+        FilterAction\r
+#endif\r
+        acceptNode(const DOMNode* node) const {\r
+            return FILTER_REJECT;\r
+        }\r
+    };\r
+#endif\r
+};\r
+\r
+namespace shibsp {\r
+    ServiceProvider* XMLServiceProviderFactory(const DOMElement* const & e)\r
+    {\r
+        return new XMLConfig(e);\r
+    }\r
+};\r
+\r
+XMLApplication::XMLApplication(\r
+    const ServiceProvider* sp,\r
+    const DOMElement* e,\r
+    const XMLApplication* base\r
+    ) : Application(sp), m_base(base),\r
+#ifndef SHIBSP_LITE\r
+        m_metadata(NULL), m_trust(NULL),\r
+        m_attrExtractor(NULL), m_attrFilter(NULL), m_attrResolver(NULL),\r
+        m_credResolver(NULL),\r
+#endif\r
+        m_acsDefault(NULL), m_sessionInitDefault(NULL), m_artifactResolutionDefault(NULL)\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("XMLApplication");\r
+#endif\r
+    Category& log=Category::getInstance(SHIBSP_LOGCAT".Application");\r
+\r
+    try {\r
+        // First load any property sets.\r
+        load(e,NULL,this);\r
+        if (base)\r
+            setParent(base);\r
+\r
+        SPConfig& conf=SPConfig::getConfig();\r
+#ifndef SHIBSP_LITE\r
+        SAMLConfig& samlConf=SAMLConfig::getConfig();\r
+        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();\r
+#endif\r
+\r
+        // This used to be an actual hash, but now it's just a hex-encode to avoid xmlsec.\r
+        static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};\r
+        string tohash=getId();\r
+        tohash+=getString("entityID").second;\r
+        for (const char* ch = tohash.c_str(); *ch; ++ch) {\r
+            m_hash += (DIGITS[((unsigned char)(0xF0 & *ch)) >> 4 ]);\r
+            m_hash += (DIGITS[0x0F & *ch]);\r
+        }\r
+\r
+        // Populate prefix pair.\r
+        m_attributePrefix.second = "HTTP_";\r
+        pair<bool,const char*> prefix = getString("attributePrefix");\r
+        if (prefix.first) {\r
+            m_attributePrefix.first = prefix.second;\r
+            const char* pch = prefix.second;\r
+            while (*pch) {\r
+                m_attributePrefix.second += (isalnum(*pch) ? toupper(*pch) : '_');\r
+                pch++;\r
+            }\r
+        }\r
+\r
+        // Load attribute ID lists for REMOTE_USER and header clearing.\r
+        if (conf.isEnabled(SPConfig::InProcess)) {\r
+            pair<bool,const char*> attributes = getString("REMOTE_USER");\r
+            if (attributes.first) {\r
+                char* dup = strdup(attributes.second);\r
+                char* pos;\r
+                char* start = dup;\r
+                while (start && *start) {\r
+                    while (*start && isspace(*start))\r
+                        start++;\r
+                    if (!*start)\r
+                        break;\r
+                    pos = strchr(start,' ');\r
+                    if (pos)\r
+                        *pos=0;\r
+                    m_remoteUsers.push_back(start);\r
+                    start = pos ? pos+1 : NULL;\r
+                }\r
+                free(dup);\r
+            }\r
+\r
+            attributes = getString("unsetHeaders");\r
+            if (attributes.first) {\r
+                string transformedprefix(m_attributePrefix.second);\r
+                const char* pch;\r
+                prefix = getString("metadataAttributePrefix");\r
+                if (prefix.first) {\r
+                    pch = prefix.second;\r
+                    while (*pch) {\r
+                        transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');\r
+                        pch++;\r
+                    }\r
+                }\r
+                char* dup = strdup(attributes.second);\r
+                char* pos;\r
+                char* start = dup;\r
+                while (start && *start) {\r
+                    while (*start && isspace(*start))\r
+                        start++;\r
+                    if (!*start)\r
+                        break;\r
+                    pos = strchr(start,' ');\r
+                    if (pos)\r
+                        *pos=0;\r
+\r
+                    string transformed;\r
+                    pch = start;\r
+                    while (*pch) {\r
+                        transformed += (isalnum(*pch) ? toupper(*pch) : '_');\r
+                        pch++;\r
+                    }\r
+\r
+                    m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + start, m_attributePrefix.second + transformed));\r
+                    if (prefix.first)\r
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + start, transformedprefix + transformed));\r
+                    start = pos ? pos+1 : NULL;\r
+                }\r
+                free(dup);\r
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));\r
+            }\r
+        }\r
+\r
+        Handler* handler=NULL;\r
+        const PropertySet* sessions = getPropertySet("Sessions");\r
+\r
+        // Process assertion export handler.\r
+        pair<bool,const char*> location = sessions ? sessions->getString("exportLocation") : pair<bool,const char*>(false,NULL);\r
+        if (location.first) {\r
+            try {\r
+                DOMElement* exportElement = e->getOwnerDocument()->createElementNS(shibspconstants::SHIB2SPCONFIG_NS,_Handler);\r
+                exportElement->setAttributeNS(NULL,Location,sessions->getXMLString("exportLocation").second);\r
+                pair<bool,const XMLCh*> exportACL = sessions->getXMLString("exportACL");\r
+                if (exportACL.first) {\r
+                    static const XMLCh _acl[] = UNICODE_LITERAL_9(e,x,p,o,r,t,A,C,L);\r
+                    exportElement->setAttributeNS(NULL,_acl,exportACL.second);\r
+                }\r
+                handler = conf.HandlerManager.newPlugin(\r
+                    samlconstants::SAML20_BINDING_URI, pair<const DOMElement*,const char*>(exportElement, getId())\r
+                    );\r
+                m_handlers.push_back(handler);\r
+\r
+                // Insert into location map. If it contains the handlerURL, we skip past that part.\r
+                const char* pch = strstr(location.second, sessions->getString("handlerURL").second);\r
+                if (pch)\r
+                    location.second = pch + strlen(sessions->getString("handlerURL").second);\r
+                if (*location.second == '/')\r
+                    m_handlerMap[location.second]=handler;\r
+                else\r
+                    m_handlerMap[string("/") + location.second]=handler;\r
+            }\r
+            catch (exception& ex) {\r
+                log.error("caught exception installing assertion lookup handler: %s", ex.what());\r
+            }\r
+        }\r
+\r
+        // Process other handlers.\r
+        bool hardACS=false, hardSessionInit=false, hardArt=false;\r
+        const DOMElement* child = sessions ? XMLHelper::getFirstChildElement(sessions->getElement()) : NULL;\r
+        while (child) {\r
+            try {\r
+                // A handler is based on the Binding property in conjunction with the element name.\r
+                // If it's an ACS or SI, also handle index/id mappings and defaulting.\r
+                if (XMLString::equals(child->getLocalName(),_AssertionConsumerService)) {\r
+                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+                    if (!bindprop.get() || !*(bindprop.get())) {\r
+                        log.warn("md:AssertionConsumerService element has no Binding attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.AssertionConsumerServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+                    // Map by binding (may be > 1 per binding, e.g. SAML 1.0 vs 1.1)\r
+                    m_acsBindingMap[handler->getXMLString("Binding").second].push_back(handler);\r
+                    m_acsIndexMap[handler->getUnsignedInt("index").second]=handler;\r
+\r
+                    if (!hardACS) {\r
+                        pair<bool,bool> defprop=handler->getBool("isDefault");\r
+                        if (defprop.first) {\r
+                            if (defprop.second) {\r
+                                hardACS=true;\r
+                                m_acsDefault=handler;\r
+                            }\r
+                        }\r
+                        else if (!m_acsDefault)\r
+                            m_acsDefault=handler;\r
+                    }\r
+                }\r
+                else if (XMLString::equals(child->getLocalName(),_SessionInitiator)) {\r
+                    auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                    if (!type.get() || !*(type.get())) {\r
+                        log.warn("SessionInitiator element has no type attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    SessionInitiator* sihandler=conf.SessionInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+                    handler=sihandler;\r
+                    pair<bool,const char*> si_id=handler->getString("id");\r
+                    if (si_id.first && si_id.second)\r
+                        m_sessionInitMap[si_id.second]=sihandler;\r
+                    if (!hardSessionInit) {\r
+                        pair<bool,bool> defprop=handler->getBool("isDefault");\r
+                        if (defprop.first) {\r
+                            if (defprop.second) {\r
+                                hardSessionInit=true;\r
+                                m_sessionInitDefault=sihandler;\r
+                            }\r
+                        }\r
+                        else if (!m_sessionInitDefault)\r
+                            m_sessionInitDefault=sihandler;\r
+                    }\r
+                }\r
+                else if (XMLString::equals(child->getLocalName(),_LogoutInitiator)) {\r
+                    auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                    if (!type.get() || !*(type.get())) {\r
+                        log.warn("LogoutInitiator element has no type attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.LogoutInitiatorManager.newPlugin(type.get(),make_pair(child, getId()));\r
+                }\r
+                else if (XMLString::equals(child->getLocalName(),_ArtifactResolutionService)) {\r
+                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+                    if (!bindprop.get() || !*(bindprop.get())) {\r
+                        log.warn("md:ArtifactResolutionService element has no Binding attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.ArtifactResolutionServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+\r
+                    if (!hardArt) {\r
+                        pair<bool,bool> defprop=handler->getBool("isDefault");\r
+                        if (defprop.first) {\r
+                            if (defprop.second) {\r
+                                hardArt=true;\r
+                                m_artifactResolutionDefault=handler;\r
+                            }\r
+                        }\r
+                        else if (!m_artifactResolutionDefault)\r
+                            m_artifactResolutionDefault=handler;\r
+                    }\r
+                }\r
+                else if (XMLString::equals(child->getLocalName(),_SingleLogoutService)) {\r
+                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+                    if (!bindprop.get() || !*(bindprop.get())) {\r
+                        log.warn("md:SingleLogoutService element has no Binding attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.SingleLogoutServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+                }\r
+                else if (XMLString::equals(child->getLocalName(),_ManageNameIDService)) {\r
+                    auto_ptr_char bindprop(child->getAttributeNS(NULL,Binding));\r
+                    if (!bindprop.get() || !*(bindprop.get())) {\r
+                        log.warn("md:ManageNameIDService element has no Binding attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.ManageNameIDServiceManager.newPlugin(bindprop.get(),make_pair(child, getId()));\r
+                }\r
+                else {\r
+                    auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                    if (!type.get() || !*(type.get())) {\r
+                        log.warn("Handler element has no type attribute, skipping it...");\r
+                        child = XMLHelper::getNextSiblingElement(child);\r
+                        continue;\r
+                    }\r
+                    handler=conf.HandlerManager.newPlugin(type.get(),make_pair(child, getId()));\r
+                }\r
+\r
+                m_handlers.push_back(handler);\r
+\r
+                // Insert into location map.\r
+                location=handler->getString("Location");\r
+                if (location.first && *location.second == '/')\r
+                    m_handlerMap[location.second]=handler;\r
+                else if (location.first)\r
+                    m_handlerMap[string("/") + location.second]=handler;\r
+\r
+            }\r
+            catch (exception& ex) {\r
+                log.error("caught exception processing handler element: %s", ex.what());\r
+            }\r
+\r
+            child = XMLHelper::getNextSiblingElement(child);\r
+        }\r
+\r
+        // Notification.\r
+        DOMNodeList* nlist=e->getElementsByTagNameNS(shibspconstants::SHIB2SPCONFIG_NS,Notify);\r
+        for (XMLSize_t i=0; nlist && i<nlist->getLength(); i++) {\r
+            if (nlist->item(i)->getParentNode()->isSameNode(e)) {\r
+                const XMLCh* channel = static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Channel);\r
+                auto_ptr_char loc(static_cast<DOMElement*>(nlist->item(i))->getAttributeNS(NULL,Location));\r
+                if (loc.get() && *loc.get()) {\r
+                    if (channel && *channel == chLatin_f)\r
+                        m_frontLogout.push_back(loc.get());\r
+                    else\r
+                        m_backLogout.push_back(loc.get());\r
+                }\r
+            }\r
+        }\r
+\r
+#ifndef SHIBSP_LITE\r
+        nlist=e->getElementsByTagNameNS(samlconstants::SAML20_NS,Audience::LOCAL_NAME);\r
+        if (nlist && nlist->getLength()) {\r
+            log.warn("use of <saml:Audience> elements outside of a Security Policy Rule is deprecated");\r
+            for (XMLSize_t i=0; i<nlist->getLength(); i++)\r
+                if (nlist->item(i)->getParentNode()->isSameNode(e) && nlist->item(i)->hasChildNodes())\r
+                    m_audiences.push_back(nlist->item(i)->getFirstChild()->getNodeValue());\r
+        }\r
+\r
+        if (conf.isEnabled(SPConfig::Metadata)) {\r
+            child = XMLHelper::getFirstChildElement(e,_MetadataProvider);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building MetadataProvider of type %s...",type.get());\r
+                try {\r
+                    auto_ptr<MetadataProvider> mp(samlConf.MetadataProviderManager.newPlugin(type.get(),child));\r
+                    mp->init();\r
+                    m_metadata = mp.release();\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building/initializing MetadataProvider: %s", ex.what());\r
+                }\r
+            }\r
+        }\r
+\r
+        if (conf.isEnabled(SPConfig::Trust)) {\r
+            child = XMLHelper::getFirstChildElement(e,_TrustEngine);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building TrustEngine of type %s...",type.get());\r
+                try {\r
+                    m_trust = xmlConf.TrustEngineManager.newPlugin(type.get(),child);\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building TrustEngine: %s", ex.what());\r
+                }\r
+            }\r
+        }\r
+\r
+        if (conf.isEnabled(SPConfig::AttributeResolution)) {\r
+            child = XMLHelper::getFirstChildElement(e,_AttributeExtractor);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building AttributeExtractor of type %s...",type.get());\r
+                try {\r
+                    m_attrExtractor = conf.AttributeExtractorManager.newPlugin(type.get(),child);\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building AttributeExtractor: %s", ex.what());\r
+                }\r
+            }\r
+\r
+            child = XMLHelper::getFirstChildElement(e,_AttributeFilter);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building AttributeFilter of type %s...",type.get());\r
+                try {\r
+                    m_attrFilter = conf.AttributeFilterManager.newPlugin(type.get(),child);\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building AttributeFilter: %s", ex.what());\r
+                }\r
+            }\r
+\r
+            child = XMLHelper::getFirstChildElement(e,_AttributeResolver);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building AttributeResolver of type %s...",type.get());\r
+                try {\r
+                    m_attrResolver = conf.AttributeResolverManager.newPlugin(type.get(),child);\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building AttributeResolver: %s", ex.what());\r
+                }\r
+            }\r
+\r
+            if (m_unsetHeaders.empty()) {\r
+                vector<string> unsetHeaders;\r
+                if (m_attrExtractor) {\r
+                    Locker extlock(m_attrExtractor);\r
+                    m_attrExtractor->getAttributeIds(unsetHeaders);\r
+                }\r
+                else if (m_base && m_base->m_attrExtractor) {\r
+                    Locker extlock(m_base->m_attrExtractor);\r
+                    m_base->m_attrExtractor->getAttributeIds(unsetHeaders);\r
+                }\r
+                if (m_attrResolver) {\r
+                    Locker reslock(m_attrResolver);\r
+                    m_attrResolver->getAttributeIds(unsetHeaders);\r
+                }\r
+                else if (m_base && m_base->m_attrResolver) {\r
+                    Locker extlock(m_base->m_attrResolver);\r
+                    m_base->m_attrResolver->getAttributeIds(unsetHeaders);\r
+                }\r
+                if (!unsetHeaders.empty()) {\r
+                    string transformedprefix(m_attributePrefix.second);\r
+                    const char* pch;\r
+                    pair<bool,const char*> prefix = getString("metadataAttributePrefix");\r
+                    if (prefix.first) {\r
+                        pch = prefix.second;\r
+                        while (*pch) {\r
+                            transformedprefix += (isalnum(*pch) ? toupper(*pch) : '_');\r
+                            pch++;\r
+                        }\r
+                    }\r
+                    for (vector<string>::const_iterator hdr = unsetHeaders.begin(); hdr!=unsetHeaders.end(); ++hdr) {\r
+                        string transformed;\r
+                        pch = hdr->c_str();\r
+                        while (*pch) {\r
+                            transformed += (isalnum(*pch) ? toupper(*pch) : '_');\r
+                            pch++;\r
+                        }\r
+                        m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + *hdr, m_attributePrefix.second + transformed));\r
+                        if (prefix.first)\r
+                            m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + prefix.second + *hdr, transformedprefix + transformed));\r
+                    }\r
+                }\r
+                m_unsetHeaders.push_back(pair<string,string>(m_attributePrefix.first + "Shib-Application-ID", m_attributePrefix.second + "SHIB_APPLICATION_ID"));\r
+            }\r
+        }\r
+\r
+        if (conf.isEnabled(SPConfig::Credentials)) {\r
+            child = XMLHelper::getFirstChildElement(e,_CredentialResolver);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building CredentialResolver of type %s...",type.get());\r
+                try {\r
+                    m_credResolver = xmlConf.CredentialResolverManager.newPlugin(type.get(),child);\r
+                }\r
+                catch (exception& ex) {\r
+                    log.crit("error building CredentialResolver: %s", ex.what());\r
+                }\r
+            }\r
+        }\r
+\r
+        // Finally, load relying parties.\r
+        child = XMLHelper::getFirstChildElement(e,RelyingParty);\r
+        while (child) {\r
+            auto_ptr<DOMPropertySet> rp(new DOMPropertySet());\r
+            rp->load(child,NULL,this);\r
+            rp->setParent(this);\r
+            m_partyMap[child->getAttributeNS(NULL,saml2::Attribute::NAME_ATTRIB_NAME)]=rp.release();\r
+            child = XMLHelper::getNextSiblingElement(child,RelyingParty);\r
+        }\r
+#endif\r
+\r
+        // Out of process only, we register a listener endpoint.\r
+        if (!conf.isEnabled(SPConfig::InProcess)) {\r
+            ListenerService* listener = sp->getListenerService(false);\r
+            if (listener) {\r
+                string addr=string(getId()) + "::getHeaders::Application";\r
+                listener->regListener(addr.c_str(),this);\r
+            }\r
+            else\r
+                log.info("no ListenerService available, Application remoting disabled");\r
+        }\r
+    }\r
+    catch (exception&) {\r
+        cleanup();\r
+        throw;\r
+    }\r
+#ifndef _DEBUG\r
+    catch (...) {\r
+        cleanup();\r
+        throw;\r
+    }\r
+#endif\r
+}\r
+\r
+void XMLApplication::cleanup()\r
+{\r
+    ListenerService* listener=getServiceProvider().getListenerService(false);\r
+    if (listener && SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess) && !SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {\r
+        string addr=string(getId()) + "::getHeaders::Application";\r
+        listener->unregListener(addr.c_str(),this);\r
+    }\r
+    for_each(m_handlers.begin(),m_handlers.end(),xmltooling::cleanup<Handler>());\r
+    m_handlers.clear();\r
+#ifndef SHIBSP_LITE\r
+    for_each(m_partyMap.begin(),m_partyMap.end(),cleanup_pair<xstring,PropertySet>());\r
+    m_partyMap.clear();\r
+    delete m_credResolver;\r
+    m_credResolver = NULL;\r
+    delete m_attrResolver;\r
+    m_attrResolver = NULL;\r
+    delete m_attrFilter;\r
+    m_attrFilter = NULL;\r
+    delete m_attrExtractor;\r
+    m_attrExtractor = NULL;\r
+    delete m_trust;\r
+    m_trust = NULL;\r
+    delete m_metadata;\r
+    m_metadata = NULL;\r
+#endif\r
+}\r
+\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+short\r
+#else\r
+DOMNodeFilter::FilterAction\r
+#endif\r
+XMLApplication::acceptNode(const DOMNode* node) const\r
+{\r
+    const XMLCh* name=node->getLocalName();\r
+    if (XMLString::equals(name,ApplicationOverride) ||\r
+        XMLString::equals(name,_Audience) ||\r
+        XMLString::equals(name,Notify) ||\r
+        XMLString::equals(name,_Handler) ||\r
+        XMLString::equals(name,_AssertionConsumerService) ||\r
+        XMLString::equals(name,_ArtifactResolutionService) ||\r
+        XMLString::equals(name,_LogoutInitiator) ||\r
+        XMLString::equals(name,_ManageNameIDService) ||\r
+        XMLString::equals(name,_SessionInitiator) ||\r
+        XMLString::equals(name,_SingleLogoutService) ||\r
+        XMLString::equals(name,RelyingParty) ||\r
+        XMLString::equals(name,_MetadataProvider) ||\r
+        XMLString::equals(name,_TrustEngine) ||\r
+        XMLString::equals(name,_CredentialResolver) ||\r
+        XMLString::equals(name,_AttributeFilter) ||\r
+        XMLString::equals(name,_AttributeExtractor) ||\r
+        XMLString::equals(name,_AttributeResolver))\r
+        return FILTER_REJECT;\r
+\r
+    return FILTER_ACCEPT;\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+\r
+const PropertySet* XMLApplication::getRelyingParty(const EntityDescriptor* provider) const\r
+{\r
+    if (!provider)\r
+        return this;\r
+\r
+    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(provider->getEntityID());\r
+    if (i!=m_partyMap.end())\r
+        return i->second;\r
+    const EntitiesDescriptor* group=dynamic_cast<const EntitiesDescriptor*>(provider->getParent());\r
+    while (group) {\r
+        if (group->getName()) {\r
+            i=m_partyMap.find(group->getName());\r
+            if (i!=m_partyMap.end())\r
+                return i->second;\r
+        }\r
+        group=dynamic_cast<const EntitiesDescriptor*>(group->getParent());\r
+    }\r
+    return this;\r
+}\r
+\r
+const PropertySet* XMLApplication::getRelyingParty(const XMLCh* entityID) const\r
+{\r
+    if (!entityID)\r
+        return this;\r
+\r
+    map<xstring,PropertySet*>::const_iterator i=m_partyMap.find(entityID);\r
+    if (i!=m_partyMap.end())\r
+        return i->second;\r
+    return this;\r
+}\r
+\r
+#endif\r
+\r
+string XMLApplication::getNotificationURL(const char* resource, bool front, unsigned int index) const\r
+{\r
+    const vector<string>& locs = front ? m_frontLogout : m_backLogout;\r
+    if (locs.empty())\r
+        return m_base ? m_base->getNotificationURL(resource, front, index) : string();\r
+    else if (index >= locs.size())\r
+        return string();\r
+\r
+#ifdef HAVE_STRCASECMP\r
+    if (!resource || (strncasecmp(resource,"http://",7) && strncasecmp(resource,"https://",8)))\r
+#else\r
+    if (!resource || (strnicmp(resource,"http://",7) && strnicmp(resource,"https://",8)))\r
+#endif\r
+        throw ConfigurationException("Request URL was not absolute.");\r
+\r
+    const char* handler=locs[index].c_str();\r
+\r
+    // Should never happen...\r
+    if (!handler || (*handler!='/' && strncmp(handler,"http:",5) && strncmp(handler,"https:",6)))\r
+        throw ConfigurationException(\r
+            "Invalid Location property ($1) in Notify element for Application ($2)",\r
+            params(2, handler ? handler : "null", getId())\r
+            );\r
+\r
+    // The "Location" property can be in one of three formats:\r
+    //\r
+    // 1) a full URI:       http://host/foo/bar\r
+    // 2) a hostless URI:   http:///foo/bar\r
+    // 3) a relative path:  /foo/bar\r
+    //\r
+    // #  Protocol  Host        Path\r
+    // 1  handler   handler     handler\r
+    // 2  handler   resource    handler\r
+    // 3  resource  resource    handler\r
+\r
+    const char* path = NULL;\r
+\r
+    // Decide whether to use the handler or the resource for the "protocol"\r
+    const char* prot;\r
+    if (*handler != '/') {\r
+        prot = handler;\r
+    }\r
+    else {\r
+        prot = resource;\r
+        path = handler;\r
+    }\r
+\r
+    // break apart the "protocol" string into protocol, host, and "the rest"\r
+    const char* colon=strchr(prot,':');\r
+    colon += 3;\r
+    const char* slash=strchr(colon,'/');\r
+    if (!path)\r
+        path = slash;\r
+\r
+    // Compute the actual protocol and store.\r
+    string notifyURL(prot, colon-prot);\r
+\r
+    // create the "host" from either the colon/slash or from the target string\r
+    // If prot == handler then we're in either #1 or #2, else #3.\r
+    // If slash == colon then we're in #2.\r
+    if (prot != handler || slash == colon) {\r
+        colon = strchr(resource, ':');\r
+        colon += 3;      // Get past the ://\r
+        slash = strchr(colon, '/');\r
+    }\r
+    string host(colon, (slash ? slash-colon : strlen(colon)));\r
+\r
+    // Build the URL\r
+    notifyURL += host + path;\r
+    return notifyURL;\r
+}\r
+\r
+void XMLApplication::clearHeader(SPRequest& request, const char* rawname, const char* cginame) const\r
+{\r
+    if (!m_attributePrefix.first.empty()) {\r
+        string temp = m_attributePrefix.first + rawname;\r
+        string temp2 = m_attributePrefix.second + (cginame + 5);\r
+        request.clearHeader(temp.c_str(), temp2.c_str());\r
+    }\r
+    else if (m_base) {\r
+        m_base->clearHeader(request, rawname, cginame);\r
+    }\r
+    else {\r
+        request.clearHeader(rawname, cginame);\r
+    }\r
+}\r
+\r
+void XMLApplication::setHeader(SPRequest& request, const char* name, const char* value) const\r
+{\r
+    if (!m_attributePrefix.first.empty()) {\r
+        string temp = m_attributePrefix.first + name;\r
+        request.setHeader(temp.c_str(), value);\r
+    }\r
+    else if (m_base) {\r
+        m_base->setHeader(request, name, value);\r
+    }\r
+    else {\r
+        request.setHeader(name, value);\r
+    }\r
+}\r
+\r
+string XMLApplication::getSecureHeader(const SPRequest& request, const char* name) const\r
+{\r
+    if (!m_attributePrefix.first.empty()) {\r
+        string temp = m_attributePrefix.first + name;\r
+        return request.getSecureHeader(temp.c_str());\r
+    }\r
+    else if (m_base) {\r
+        return m_base->getSecureHeader(request,name);\r
+    }\r
+    else {\r
+        return request.getSecureHeader(name);\r
+    }\r
+}\r
+\r
+const SessionInitiator* XMLApplication::getDefaultSessionInitiator() const\r
+{\r
+    if (m_sessionInitDefault) return m_sessionInitDefault;\r
+    return m_base ? m_base->getDefaultSessionInitiator() : NULL;\r
+}\r
+\r
+const SessionInitiator* XMLApplication::getSessionInitiatorById(const char* id) const\r
+{\r
+    map<string,const SessionInitiator*>::const_iterator i=m_sessionInitMap.find(id);\r
+    if (i!=m_sessionInitMap.end()) return i->second;\r
+    return m_base ? m_base->getSessionInitiatorById(id) : NULL;\r
+}\r
+\r
+const Handler* XMLApplication::getDefaultAssertionConsumerService() const\r
+{\r
+    if (m_acsDefault) return m_acsDefault;\r
+    return m_base ? m_base->getDefaultAssertionConsumerService() : NULL;\r
+}\r
+\r
+const Handler* XMLApplication::getAssertionConsumerServiceByIndex(unsigned short index) const\r
+{\r
+    map<unsigned int,const Handler*>::const_iterator i=m_acsIndexMap.find(index);\r
+    if (i!=m_acsIndexMap.end()) return i->second;\r
+    return m_base ? m_base->getAssertionConsumerServiceByIndex(index) : NULL;\r
+}\r
+\r
+const vector<const Handler*>& XMLApplication::getAssertionConsumerServicesByBinding(const XMLCh* binding) const\r
+{\r
+    ACSBindingMap::const_iterator i=m_acsBindingMap.find(binding);\r
+    if (i!=m_acsBindingMap.end())\r
+        return i->second;\r
+    return m_base ? m_base->getAssertionConsumerServicesByBinding(binding) : g_noHandlers;\r
+}\r
+\r
+const Handler* XMLApplication::getHandler(const char* path) const\r
+{\r
+    string wrap(path);\r
+    wrap = wrap.substr(0,wrap.find(';'));\r
+    map<string,const Handler*>::const_iterator i=m_handlerMap.find(wrap.substr(0,wrap.find('?')));\r
+    if (i!=m_handlerMap.end())\r
+        return i->second;\r
+    return m_base ? m_base->getHandler(path) : NULL;\r
+}\r
+\r
+void XMLApplication::getHandlers(vector<const Handler*>& handlers) const\r
+{\r
+    handlers.insert(handlers.end(), m_handlers.begin(), m_handlers.end());\r
+    if (m_base) {\r
+        for (map<string,const Handler*>::const_iterator h = m_base->m_handlerMap.begin(); h != m_base->m_handlerMap.end(); ++h) {\r
+            if (m_handlerMap.count(h->first) == 0)\r
+                handlers.push_back(h->second);\r
+        }\r
+    }\r
+}\r
+\r
+#ifdef SHIBSP_XERCESC_SHORT_ACCEPTNODE\r
+short\r
+#else\r
+DOMNodeFilter::FilterAction\r
+#endif\r
+XMLConfigImpl::acceptNode(const DOMNode* node) const\r
+{\r
+    if (!XMLString::equals(node->getNamespaceURI(),shibspconstants::SHIB2SPCONFIG_NS))\r
+        return FILTER_ACCEPT;\r
+    const XMLCh* name=node->getLocalName();\r
+    if (XMLString::equals(name,ApplicationDefaults) ||\r
+        XMLString::equals(name,_ArtifactMap) ||\r
+        XMLString::equals(name,_Extensions) ||\r
+        XMLString::equals(name,Listener) ||\r
+        XMLString::equals(name,_RequestMapper) ||\r
+        XMLString::equals(name,_ReplayCache) ||\r
+        XMLString::equals(name,SecurityPolicies) ||\r
+        XMLString::equals(name,_SessionCache) ||\r
+        XMLString::equals(name,Site) ||\r
+        XMLString::equals(name,_StorageService) ||\r
+        XMLString::equals(name,TCPListener) ||\r
+        XMLString::equals(name,TransportOption) ||\r
+        XMLString::equals(name,UnixListener))\r
+        return FILTER_REJECT;\r
+\r
+    return FILTER_ACCEPT;\r
+}\r
+\r
+void XMLConfigImpl::doExtensions(const DOMElement* e, const char* label, Category& log)\r
+{\r
+    const DOMElement* exts=XMLHelper::getFirstChildElement(e,_Extensions);\r
+    if (exts) {\r
+        exts=XMLHelper::getFirstChildElement(exts,Library);\r
+        while (exts) {\r
+            auto_ptr_char path(exts->getAttributeNS(NULL,_path));\r
+            try {\r
+                if (path.get()) {\r
+                    if (!XMLToolingConfig::getConfig().load_library(path.get(),(void*)exts))\r
+                        throw ConfigurationException("XMLToolingConfig::load_library failed.");\r
+                    log.debug("loaded %s extension library (%s)", label, path.get());\r
+                }\r
+            }\r
+            catch (exception& e) {\r
+                const XMLCh* fatal=exts->getAttributeNS(NULL,_fatal);\r
+                if (fatal && (*fatal==chLatin_t || *fatal==chDigit_1)) {\r
+                    log.fatal("unable to load mandatory %s extension library %s: %s", label, path.get(), e.what());\r
+                    throw;\r
+                }\r
+                else {\r
+                    log.crit("unable to load optional %s extension library %s: %s", label, path.get(), e.what());\r
+                }\r
+            }\r
+            exts=XMLHelper::getNextSiblingElement(exts,Library);\r
+        }\r
+    }\r
+}\r
+\r
+XMLConfigImpl::XMLConfigImpl(const DOMElement* e, bool first, const XMLConfig* outer, Category& log)\r
+    : m_requestMapper(NULL), m_outer(outer), m_document(NULL)\r
+{\r
+#ifdef _DEBUG\r
+    xmltooling::NDC ndc("XMLConfigImpl");\r
+#endif\r
+\r
+    try {\r
+        SPConfig& conf=SPConfig::getConfig();\r
+#ifndef SHIBSP_LITE\r
+        SAMLConfig& samlConf=SAMLConfig::getConfig();\r
+#endif\r
+        XMLToolingConfig& xmlConf=XMLToolingConfig::getConfig();\r
+        const DOMElement* SHAR=XMLHelper::getFirstChildElement(e,OutOfProcess);\r
+        const DOMElement* SHIRE=XMLHelper::getFirstChildElement(e,InProcess);\r
+\r
+        // Initialize log4cpp manually in order to redirect log messages as soon as possible.\r
+        if (conf.isEnabled(SPConfig::Logging)) {\r
+            const XMLCh* logconf=NULL;\r
+            if (conf.isEnabled(SPConfig::OutOfProcess))\r
+                logconf=SHAR->getAttributeNS(NULL,logger);\r
+            else if (conf.isEnabled(SPConfig::InProcess))\r
+                logconf=SHIRE->getAttributeNS(NULL,logger);\r
+            if (!logconf || !*logconf)\r
+                logconf=e->getAttributeNS(NULL,logger);\r
+            if (logconf && *logconf) {\r
+                auto_ptr_char logpath(logconf);\r
+                log.debug("loading new logging configuration from (%s), check log destination for status of configuration",logpath.get());\r
+                if (!XMLToolingConfig::getConfig().log_config(logpath.get()))\r
+                    log.crit("failed to load new logging configuration from (%s)", logpath.get());\r
+            }\r
+\r
+#ifndef SHIBSP_LITE\r
+            if (first)\r
+                m_outer->m_tranLog = new TransactionLog();\r
+#endif\r
+        }\r
+\r
+        // Re-log library versions now that logging is set up.\r
+#ifndef SHIBSP_LITE\r
+        log.info(\r
+            "Library versions: Xerces-C %s, XML-Security-C %s, XMLTooling-C %s, OpenSAML-C %s, Shibboleth %s",\r
+            XERCES_FULLVERSIONDOT, XSEC_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, OPENSAML_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT\r
+            );\r
+#else\r
+        log.info(\r
+            "Library versions: Xerces-C %s, XMLTooling-C %s, Shibboleth %s",\r
+            XERCES_FULLVERSIONDOT, XMLTOOLING_FULLVERSIONDOT, SHIBSP_FULLVERSIONDOT\r
+            );\r
+#endif\r
+\r
+        // First load any property sets.\r
+        load(e,NULL,this);\r
+\r
+        const DOMElement* child;\r
+        string plugtype;\r
+\r
+        // Much of the processing can only occur on the first instantiation.\r
+        if (first) {\r
+            // Set clock skew.\r
+            pair<bool,unsigned int> skew=getUnsignedInt("clockSkew");\r
+            if (skew.first)\r
+                xmlConf.clock_skew_secs=min(skew.second,(60*60*24*7*28));\r
+\r
+            pair<bool,const char*> unsafe = getString("unsafeChars");\r
+            if (unsafe.first)\r
+                TemplateEngine::unsafe_chars = unsafe.second;\r
+\r
+            unsafe = getString("allowedSchemes");\r
+            if (unsafe.first) {\r
+                HTTPResponse::getAllowedSchemes().clear();\r
+                string schemes=unsafe.second;\r
+                unsigned int j_sch=0;\r
+                for (unsigned int i_sch=0;  i_sch < schemes.length();  i_sch++) {\r
+                    if (schemes.at(i_sch)==' ') {\r
+                        HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, i_sch-j_sch));\r
+                        j_sch = i_sch + 1;\r
+                    }\r
+                }\r
+                HTTPResponse::getAllowedSchemes().push_back(schemes.substr(j_sch, schemes.length()-j_sch));\r
+            }\r
+\r
+            // Extensions\r
+            doExtensions(e, "global", log);\r
+            if (conf.isEnabled(SPConfig::OutOfProcess))\r
+                doExtensions(SHAR, "out of process", log);\r
+\r
+            if (conf.isEnabled(SPConfig::InProcess))\r
+                doExtensions(SHIRE, "in process", log);\r
+\r
+            // Instantiate the ListenerService and SessionCache objects.\r
+            if (conf.isEnabled(SPConfig::Listener)) {\r
+                child=XMLHelper::getFirstChildElement(e,UnixListener);\r
+                if (child)\r
+                    plugtype=UNIX_LISTENER_SERVICE;\r
+                else {\r
+                    child=XMLHelper::getFirstChildElement(e,TCPListener);\r
+                    if (child)\r
+                        plugtype=TCP_LISTENER_SERVICE;\r
+                    else {\r
+                        child=XMLHelper::getFirstChildElement(e,Listener);\r
+                        if (child) {\r
+                            auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                            if (type.get())\r
+                                plugtype=type.get();\r
+                        }\r
+                    }\r
+                }\r
+                if (child) {\r
+                    log.info("building ListenerService of type %s...", plugtype.c_str());\r
+                    m_outer->m_listener = conf.ListenerServiceManager.newPlugin(plugtype.c_str(), child);\r
+                }\r
+                else {\r
+                    log.fatal("can't build ListenerService, missing conf:Listener element?");\r
+                    throw ConfigurationException("Can't build ListenerService, missing conf:Listener element?");\r
+                }\r
+            }\r
+\r
+#ifndef SHIBSP_LITE\r
+            if (m_outer->m_listener && conf.isEnabled(SPConfig::OutOfProcess) && !conf.isEnabled(SPConfig::InProcess)) {\r
+                m_outer->m_listener->regListener("set::RelayState", const_cast<XMLConfig*>(m_outer));\r
+                m_outer->m_listener->regListener("get::RelayState", const_cast<XMLConfig*>(m_outer));\r
+                m_outer->m_listener->regListener("set::PostData", const_cast<XMLConfig*>(m_outer));\r
+                m_outer->m_listener->regListener("get::PostData", const_cast<XMLConfig*>(m_outer));\r
+            }\r
+#endif\r
+\r
+            if (conf.isEnabled(SPConfig::Caching)) {\r
+                if (conf.isEnabled(SPConfig::OutOfProcess)) {\r
+#ifndef SHIBSP_LITE\r
+                    // First build any StorageServices.\r
+                    child=XMLHelper::getFirstChildElement(e,_StorageService);\r
+                    while (child) {\r
+                        auto_ptr_char id(child->getAttributeNS(NULL,_id));\r
+                        auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                        try {\r
+                            log.info("building StorageService (%s) of type %s...", id.get(), type.get());\r
+                            m_outer->m_storage[id.get()] = xmlConf.StorageServiceManager.newPlugin(type.get(),child);\r
+                        }\r
+                        catch (exception& ex) {\r
+                            log.crit("failed to instantiate StorageService (%s): %s", id.get(), ex.what());\r
+                        }\r
+                        child=XMLHelper::getNextSiblingElement(child,_StorageService);\r
+                    }\r
+\r
+                    // Replay cache.\r
+                    StorageService* replaySS=NULL;\r
+                    child=XMLHelper::getFirstChildElement(e,_ReplayCache);\r
+                    if (child) {\r
+                        auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));\r
+                        if (ssid.get() && *ssid.get()) {\r
+                            if (m_outer->m_storage.count(ssid.get()))\r
+                                replaySS = m_outer->m_storage[ssid.get()];\r
+                            if (replaySS)\r
+                                log.info("building ReplayCache on top of StorageService (%s)...", ssid.get());\r
+                            else\r
+                                log.warn("unable to locate StorageService (%s) for ReplayCache, using dedicated in-memory instance", ssid.get());\r
+                        }\r
+                        xmlConf.setReplayCache(new ReplayCache(replaySS));\r
+                    }\r
+                    else {\r
+                        log.warn("no ReplayCache built, missing conf:ReplayCache element?");\r
+                    }\r
+\r
+                    // ArtifactMap\r
+                    child=XMLHelper::getFirstChildElement(e,_ArtifactMap);\r
+                    if (child) {\r
+                        auto_ptr_char ssid(child->getAttributeNS(NULL,_StorageService));\r
+                        if (ssid.get() && *ssid.get() && m_outer->m_storage.count(ssid.get())) {\r
+                            log.info("building ArtifactMap on top of StorageService (%s)...", ssid.get());\r
+                            samlConf.setArtifactMap(new ArtifactMap(child, m_outer->m_storage[ssid.get()]));\r
+                        }\r
+                    }\r
+                    if (samlConf.getArtifactMap()==NULL) {\r
+                        log.info("building in-memory ArtifactMap...");\r
+                        samlConf.setArtifactMap(new ArtifactMap(child));\r
+                    }\r
+#endif\r
+                }\r
+                child=XMLHelper::getFirstChildElement(e,_SessionCache);\r
+                if (child) {\r
+                    auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                    log.info("building SessionCache of type %s...",type.get());\r
+                    m_outer->m_sessionCache=conf.SessionCacheManager.newPlugin(type.get(), child);\r
+                }\r
+                else {\r
+                    log.fatal("can't build SessionCache, missing conf:SessionCache element?");\r
+                    throw ConfigurationException("Can't build SessionCache, missing conf:SessionCache element?");\r
+                }\r
+            }\r
+        } // end of first-time-only stuff\r
+\r
+        // Back to the fully dynamic stuff...next up is the RequestMapper.\r
+        if (conf.isEnabled(SPConfig::RequestMapping)) {\r
+            child=XMLHelper::getFirstChildElement(e,_RequestMapper);\r
+            if (child) {\r
+                auto_ptr_char type(child->getAttributeNS(NULL,_type));\r
+                log.info("building RequestMapper of type %s...",type.get());\r
+                m_requestMapper=conf.RequestMapperManager.newPlugin(type.get(),child);\r
+            }\r
+            else {\r
+                log.fatal("can't build RequestMapper, missing conf:RequestMapper element?");\r
+                throw ConfigurationException("Can't build RequestMapper, missing conf:RequestMapper element?");\r
+            }\r
+        }\r
+\r
+#ifndef SHIBSP_LITE\r
+        // Load security policies.\r
+        child = XMLHelper::getLastChildElement(e,SecurityPolicies);\r
+        if (child) {\r
+            PolicyNodeFilter filter;\r
+            child = XMLHelper::getFirstChildElement(child,Policy);\r
+            while (child) {\r
+                auto_ptr_char id(child->getAttributeNS(NULL,_id));\r
+                pair< PropertySet*,vector<const SecurityPolicyRule*> >& rules = m_policyMap[id.get()];\r
+                rules.first = NULL;\r
+                auto_ptr<DOMPropertySet> settings(new DOMPropertySet());\r
+                settings->load(child, NULL, &filter);\r
+                rules.first = settings.release();\r
+\r
+                // Process PolicyRule elements.\r
+                const DOMElement* rule = XMLHelper::getFirstChildElement(child,PolicyRule);\r
+                while (rule) {\r
+                    auto_ptr_char type(rule->getAttributeNS(NULL,_type));\r
+                    try {\r
+                        rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));\r
+                    }\r
+                    catch (exception& ex) {\r
+                        log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+                    }\r
+                    rule = XMLHelper::getNextSiblingElement(rule,PolicyRule);\r
+                }\r
+\r
+                if (rules.second.size() == 0) {\r
+                    // Process Rule elements.\r
+                    log.warn("detected legacy Policy configuration, please convert to new PolicyRule syntax");\r
+                    rule = XMLHelper::getFirstChildElement(child,Rule);\r
+                    while (rule) {\r
+                        auto_ptr_char type(rule->getAttributeNS(NULL,_type));\r
+                        try {\r
+                            rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(type.get(),rule));\r
+                        }\r
+                        catch (exception& ex) {\r
+                            log.crit("error instantiating policy rule (%s) in policy (%s): %s", type.get(), id.get(), ex.what());\r
+                        }\r
+                        rule = XMLHelper::getNextSiblingElement(rule,Rule);\r
+                    }\r
+\r
+                    // Manually add a basic Conditions rule.\r
+                    log.info("installing a default Conditions rule in policy (%s) for compatibility with legacy configuration", id.get());\r
+                    rules.second.push_back(samlConf.SecurityPolicyRuleManager.newPlugin(CONDITIONS_POLICY_RULE, NULL));\r
+                }\r
+\r
+                child = XMLHelper::getNextSiblingElement(child,Policy);\r
+            }\r
+        }\r
+\r
+        // Process TransportOption elements.\r
+        child = XMLHelper::getLastChildElement(e,TransportOption);\r
+        while (child) {\r
+            if (child->hasChildNodes()) {\r
+                auto_ptr_char provider(child->getAttributeNS(NULL,_provider));\r
+                auto_ptr_char option(child->getAttributeNS(NULL,_option));\r
+                auto_ptr_char value(child->getFirstChild()->getNodeValue());\r
+                if (provider.get() && *provider.get() && option.get() && *option.get() && value.get() && *value.get()) {\r
+                    m_transportOptions.push_back(make_pair(string(provider.get()), make_pair(string(option.get()), string(value.get()))));\r
+                }\r
+            }\r
+            child = XMLHelper::getPreviousSiblingElement(child,TransportOption);\r
+        }\r
+#endif\r
+\r
+        // Load the default application. This actually has a fixed ID of "default". ;-)\r
+        child=XMLHelper::getLastChildElement(e,ApplicationDefaults);\r
+        if (!child) {\r
+            log.fatal("can't build default Application object, missing conf:ApplicationDefaults element?");\r
+            throw ConfigurationException("can't build default Application object, missing conf:ApplicationDefaults element?");\r
+        }\r
+        XMLApplication* defapp=new XMLApplication(m_outer,child);\r
+        m_appmap[defapp->getId()]=defapp;\r
+\r
+        // Load any overrides.\r
+        child = XMLHelper::getFirstChildElement(child,ApplicationOverride);\r
+        while (child) {\r
+            auto_ptr<XMLApplication> iapp(new XMLApplication(m_outer,child,defapp));\r
+            if (m_appmap.count(iapp->getId()))\r
+                log.crit("found conf:ApplicationOverride element with duplicate id attribute (%s), skipping it", iapp->getId());\r
+            else {\r
+                const char* iappid=iapp->getId();\r
+                m_appmap[iappid]=iapp.release();\r
+            }\r
+\r
+            child = XMLHelper::getNextSiblingElement(child,ApplicationOverride);\r
+        }\r
+    }\r
+    catch (exception&) {\r
+        cleanup();\r
+        throw;\r
+    }\r
+}\r
+\r
+XMLConfigImpl::~XMLConfigImpl()\r
+{\r
+    cleanup();\r
+}\r
+\r
+void XMLConfigImpl::cleanup()\r
+{\r
+    for_each(m_appmap.begin(),m_appmap.end(),cleanup_pair<string,Application>());\r
+    m_appmap.clear();\r
+#ifndef SHIBSP_LITE\r
+    for (map< string,pair<PropertySet*,vector<const SecurityPolicyRule*> > >::iterator i=m_policyMap.begin(); i!=m_policyMap.end(); ++i) {\r
+        delete i->second.first;\r
+        for_each(i->second.second.begin(), i->second.second.end(), xmltooling::cleanup<SecurityPolicyRule>());\r
+    }\r
+    m_policyMap.clear();\r
+#endif\r
+    delete m_requestMapper;\r
+    m_requestMapper = NULL;\r
+    if (m_document)\r
+        m_document->release();\r
+    m_document = NULL;\r
+}\r
+\r
+#ifndef SHIBSP_LITE\r
+void XMLConfig::receive(DDF& in, ostream& out)\r
+{\r
+    if (!strcmp(in.name(), "get::RelayState")) {\r
+        const char* id = in["id"].string();\r
+        const char* key = in["key"].string();\r
+        if (!id || !key)\r
+            throw ListenerException("Required parameters missing for RelayState recovery.");\r
+\r
+        string relayState;\r
+        StorageService* storage = getStorageService(id);\r
+        if (storage) {\r
+            if (storage->readString("RelayState",key,&relayState)>0) {\r
+                if (in["clear"].integer())\r
+                    storage->deleteString("RelayState",key);\r
+            }\r
+        }\r
+        else {\r
+            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+                "Storage-backed RelayState with invalid StorageService ID (%s)", id\r
+                );\r
+        }\r
+\r
+        // Repack for return to caller.\r
+        DDF ret=DDF(NULL).unsafe_string(relayState.c_str());\r
+        DDFJanitor jret(ret);\r
+        out << ret;\r
+    }\r
+    else if (!strcmp(in.name(), "set::RelayState")) {\r
+        const char* id = in["id"].string();\r
+        const char* value = in["value"].string();\r
+        if (!id || !value)\r
+            throw ListenerException("Required parameters missing for RelayState creation.");\r
+\r
+        string rsKey;\r
+        StorageService* storage = getStorageService(id);\r
+        if (storage) {\r
+            SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+            rsKey = SAMLArtifact::toHex(rsKey);\r
+            storage->createString("RelayState", rsKey.c_str(), value, time(NULL) + 600);\r
+        }\r
+        else {\r
+            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+                "Storage-backed RelayState with invalid StorageService ID (%s)", id\r
+                );\r
+        }\r
+\r
+        // Repack for return to caller.\r
+        DDF ret=DDF(NULL).string(rsKey.c_str());\r
+        DDFJanitor jret(ret);\r
+        out << ret;\r
+    }\r
+    else if (!strcmp(in.name(), "get::PostData")) {\r
+        const char* id = in["id"].string();\r
+        const char* key = in["key"].string();\r
+        if (!id || !key)\r
+            throw ListenerException("Required parameters missing for PostData recovery.");\r
+\r
+        string postData;\r
+        StorageService* storage = getStorageService(id);\r
+        if (storage) {\r
+            if (storage->readString("PostData",key,&postData) > 0) {\r
+                storage->deleteString("PostData",key);\r
+            }\r
+        }\r
+        else {\r
+            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+                "Storage-backed PostData with invalid StorageService ID (%s)", id\r
+                );\r
+        }\r
+        // If the data's empty, we'll send nothing back.\r
+        // If not, we don't need to round trip it, just send back the serialized DDF list.\r
+        if (postData.empty()) {\r
+            DDF ret(NULL);\r
+            DDFJanitor jret(ret);\r
+            out << ret;\r
+        }\r
+        else {\r
+            out << postData;\r
+        }\r
+    }\r
+    else if (!strcmp(in.name(), "set::PostData")) {\r
+        const char* id = in["id"].string();\r
+        if (!id || !in["parameters"].islist())\r
+            throw ListenerException("Required parameters missing for PostData creation.");\r
+\r
+        string rsKey;\r
+        StorageService* storage = getStorageService(id);\r
+        if (storage) {\r
+            SAMLConfig::getConfig().generateRandomBytes(rsKey,20);\r
+            rsKey = SAMLArtifact::toHex(rsKey);\r
+            ostringstream params;\r
+            params << in["parameters"];\r
+            storage->createString("PostData", rsKey.c_str(), params.str().c_str(), time(NULL) + 600);\r
+        }\r
+        else {\r
+            Category::getInstance(SHIBSP_LOGCAT".ServiceProvider").error(\r
+                "Storage-backed PostData with invalid StorageService ID (%s)", id\r
+                );\r
+        }\r
+\r
+        // Repack for return to caller.\r
+        DDF ret=DDF(NULL).string(rsKey.c_str());\r
+        DDFJanitor jret(ret);\r
+        out << ret;\r
+    }\r
+}\r
+#endif\r
+\r
+pair<bool,DOMElement*> XMLConfig::load()\r
+{\r
+    // Load from source using base class.\r
+    pair<bool,DOMElement*> raw = ReloadableXMLFile::load();\r
+\r
+    // If we own it, wrap it.\r
+    XercesJanitor<DOMDocument> docjanitor(raw.first ? raw.second->getOwnerDocument() : NULL);\r
+\r
+    XMLConfigImpl* impl = new XMLConfigImpl(raw.second,(m_impl==NULL),this,m_log);\r
+\r
+    // If we held the document, transfer it to the impl. If we didn't, it's a no-op.\r
+    impl->setDocument(docjanitor.release());\r
+\r
+    delete m_impl;\r
+    m_impl = impl;\r
+\r
+    return make_pair(false,(DOMElement*)NULL);\r
+}\r
index cb8ffc0..2d3eeee 100644 (file)
@@ -69,6 +69,15 @@ CommonDomainCookie::CommonDomainCookie(const char* cookie)
     }
 }
 
+CommonDomainCookie::~CommonDomainCookie()
+{
+}
+
+const vector<string>& CommonDomainCookie::get() const
+{
+    return m_list;
+}
+
 const char* CommonDomainCookie::set(const char* entityID)
 {
     // First scan the list for this IdP.
index a15f88c..faffa46 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -47,16 +47,14 @@ namespace opensaml {
          */
         CommonDomainCookie(const char* cookie);
         
-        ~CommonDomainCookie() {}
+        ~CommonDomainCookie();
         
         /**
          * Returns list of IdPs stored in cookie.
          * 
          * @return  reference to vector of entityIDs
          */
-        const std::vector<std::string>& get() const {
-            return m_list;
-        }
+        const std::vector<std::string>& get() const;
         
         /**
          * Adds/moves an IdP to the front of the list.
index f04b3f3..83b4de9 100644 (file)
@@ -23,7 +23,8 @@
 #ifndef __shibsp_xmlconstants_h__
 #define __shibsp_xmlconstants_h__
 
-#include <xmltooling/util/XMLConstants.h>
+#include <shibsp/base.h>
+#include <xercesc/util/XercesDefs.hpp>
 
 /**
  * SAML related constants.
index 9e583e4..98605c1 100644 (file)
 
 #include "internal.h"
 #include "exceptions.h"
+#include "Application.h"
 #include "ServiceProvider.h"
 #include "metadata/MetadataProviderCriteria.h"
 
+#include <xercesc/framework/Wrapper4InputSource.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xsec/framework/XSECDefs.hpp>
 #include <saml/version.h>
 #include <saml/binding/SAMLArtifact.h>
 #include <saml/saml2/metadata/Metadata.h>
 #include <saml/saml2/metadata/DynamicMetadataProvider.h>
-
 #include <xmltooling/logging.h>
-#include <xmltooling/util/NDC.h>
+#include <xmltooling/XMLToolingConfig.h>
 #include <xmltooling/security/Credential.h>
 #include <xmltooling/security/CredentialCriteria.h>
 #include <xmltooling/security/CredentialResolver.h>
 #include <xmltooling/security/X509TrustEngine.h>
 #include <xmltooling/soap/HTTPSOAPTransport.h>
+#include <xmltooling/util/NDC.h>
+#include <xmltooling/util/ParserPool.h>
 #include <xmltooling/util/XMLHelper.h>
 
-#include <xercesc/framework/Wrapper4InputSource.hpp>
-#include <xercesc/util/XMLUniDefs.hpp>
-
 using namespace shibsp;
 using namespace opensaml;
 using namespace xmltooling::logging;
@@ -135,7 +137,7 @@ saml2md::EntityDescriptor* DynamicMetadataProvider::resolve(const saml2md::Metad
         name = temp.get();
     }
     else if (criteria.artifact) {
-        throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");\r
+        throw saml2md::MetadataException("Unable to resolve metadata dynamically from an artifact.");
     }
 
     // Establish networking properties based on calling application.
index d0badc0..c9054c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 /**
  * @file shibsp/metadata/MetadataExt.h
  * 
- * XMLObjects representing Shibboleth metadata extensions
+ * XMLObjects representing Shibboleth metadata extensions.
  */
 
 #ifndef __shibsp_metaext_h__
 #define __shibsp_metaext_h__
 
 #include <shibsp/util/SPConstants.h>
-#include <xmltooling/XMLObjectBuilder.h>
-#include <xmltooling/signature/KeyInfo.h>
-#include <xercesc/util/XMLUniDefs.hpp>
+
+#include <xmltooling/AttributeExtensibleXMLObject.h>
+#include <xmltooling/ConcreteXMLObjectBuilder.h>
+#include <xmltooling/util/XMLObjectChildrenList.h>
 
 #define DECL_SHIBOBJECTBUILDER(cname) \
     DECL_XMLOBJECTBUILDER(SHIBSP_API,cname,shibspconstants::SHIBMD_NS,shibspconstants::SHIBMD_PREFIX)
 
+namespace xmlsignature {
+    class XMLTOOL_API KeyInfo;
+};
+
 namespace shibsp {
 
     BEGIN_XMLOBJECT(SHIBSP_API,Scope,xmltooling::XMLObject,Scope element);
index 71fb17a..7ae11c2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@
 #include <xmltooling/impl/AnyElement.h>
 #include <xmltooling/io/AbstractXMLObjectMarshaller.h>
 #include <xmltooling/io/AbstractXMLObjectUnmarshaller.h>
+#include <xmltooling/signature/KeyInfo.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
index f9b4472..7841539 100644 (file)
@@ -1,5 +1,5 @@
 /*
-*  Copyright 2001-2007 Internet2
+*  Copyright 2001-2009 Internet2
  * 
 * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
 /**
  * MetadataExtSchemaValidators.cpp
  * 
- * Schema-based validators for Shibboleth metadata extension classes
+ * Schema-based validators for Shibboleth metadata extension classes.
  */
 
 #include "internal.h"
@@ -26,6 +26,7 @@
 
 #include <saml/SAMLConfig.h>
 #include <saml/saml2/metadata/MetadataProvider.h>
+#include <xmltooling/validation/Validator.h>
 #include <xmltooling/validation/ValidatorSuite.h>
 
 using namespace shibsp;
diff --git a/shibsp/metadata/MetadataProviderCriteria.cpp b/shibsp/metadata/MetadataProviderCriteria.cpp
new file mode 100644 (file)
index 0000000..55ddffd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ *  Copyright 2001-2009 Internet2
+ *
+ * Licensed 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.
+ */
+
+/**
+ * MetadataProviderCriteria.cpp
+ *
+ * Extended criteria for metadata lookup for Shibboleth-aware metadata providers.
+ */
+
+#include "internal.h"
+#include "metadata/MetadataProviderCriteria.h"
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using opensaml::SAMLArtifact;
+using namespace xmltooling;
+
+MetadataProviderCriteria::MetadataProviderCriteria(const Application& app) : application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+    const Application& app, const XMLCh* id, const xmltooling::QName* q, const XMLCh* prot, bool valid
+    ) : MetadataProvider::Criteria(id, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+    const Application& app, const char* id, const xmltooling::QName* q, const XMLCh* prot, bool valid
+    ) : MetadataProvider::Criteria(id, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::MetadataProviderCriteria(
+    const Application& app, const SAMLArtifact* a, const xmltooling::QName* q, const XMLCh* prot, bool valid
+    ) : MetadataProvider::Criteria(a, q, prot, valid), application(app)
+{
+}
+
+MetadataProviderCriteria::~MetadataProviderCriteria()
+{
+}
index 286a4a0..d1a0d98 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2008 Internet2
+ *  Copyright 2001-2009 Internet2
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef __shibsp_metaprovcrit_h__
 #define __shibsp_metaprovcrit_h__
 
-#include <shibsp/Application.h>
+#include <shibsp/base.h>
+
 #include <saml/saml2/metadata/MetadataProvider.h>
 
 namespace shibsp {
 
+    class SHIBSP_API Application;
+
     /**
      * Extended criteria for metadata lookup for Shibboleth-aware metadata providers.
      */
@@ -38,8 +41,7 @@ namespace shibsp {
          *
          * @param app   application performing the lookup
          */
-        MetadataProviderCriteria(const Application& app) : application(app) {
-        }
+        MetadataProviderCriteria(const Application& app);
 
         /**
          * Constructor.
@@ -50,9 +52,9 @@ namespace shibsp {
          * @param prot  protocol support constant, if any
          * @param valid true iff stale metadata should be ignored
          */
-        MetadataProviderCriteria(const Application& app, const XMLCh* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
-            : opensaml::saml2md::MetadataProvider::Criteria(id, q, prot, valid), application(app) {
-        }
+        MetadataProviderCriteria(
+            const Application& app, const XMLCh* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+            );
 
         /**
          * Constructor.
@@ -63,9 +65,9 @@ namespace shibsp {
          * @param prot  protocol support constant, if any
          * @param valid true iff stale metadata should be ignored
          */
-        MetadataProviderCriteria(const Application& app, const char* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
-            : opensaml::saml2md::MetadataProvider::Criteria(id, q, prot, valid), application(app) {
-        }
+        MetadataProviderCriteria(
+            const Application& app, const char* id, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+            );
 
         /**
          * Constructor.
@@ -76,11 +78,13 @@ namespace shibsp {
          * @param prot  protocol support constant, if any
          * @param valid true iff stale metadata should be ignored
          */
-        MetadataProviderCriteria(const Application& app, const opensaml::SAMLArtifact* a, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true)
-            : opensaml::saml2md::MetadataProvider::Criteria(a, q, prot, valid), application(app) {
-        }
+        MetadataProviderCriteria(
+            const Application& app, const opensaml::SAMLArtifact* a, const xmltooling::QName* q=NULL, const XMLCh* prot=NULL, bool valid=true
+            );
+
+        ~MetadataProviderCriteria();
 
-        /** Controls whether stale metadata is ignored. */
+        /** The application performing the lookup. */
         const Application& application;
     };
 };
index 6eb507d..2f9ac99 100644 (file)
@@ -1,53 +1,53 @@
-/*\r
- *  Copyright 2001-2009 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * @file shibsp/paths.h\r
- * \r
- * Default configuration paths.\r
- */\r
-\r
-#ifndef __shibsp_paths_h__\r
-#define __shibsp_paths_h__\r
-\r
-/** Default schema catalogs. */\r
-#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/usr/share/xml/opensaml/saml20-catalog.xml:/usr/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"\r
-\r
-/** Default name of SP configuration file. */\r
-#define SHIBSP_CONFIG "shibboleth2.xml"\r
-\r
-/** Default name of SP console tool logging file. */\r
-#define SHIBSP_LOGGING "console.logger"\r
-\r
-/** Default prefix for installation (used to resolve relative paths). */\r
-#define SHIBSP_PREFIX  "/opt/shibboleth-sp"\r
-\r
-/** Library directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LIBDIR  "/opt/shibboleth-sp/lib"\r
-\r
-/** Log directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LOGDIR  "/opt/shibboleth-sp/var/log"\r
-\r
-/** Configuration directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_CFGDIR  "/opt/shibboleth-sp/etc"\r
-\r
-/** Runtime state directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_RUNDIR  "/opt/shibboleth-sp/var/run"\r
-\r
-/** XML directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_XMLDIR  "/opt/shibboleth-sp/share/xml"\r
-\r
-#endif /* __shibsp_paths_h__ */\r
+/*
+ *  Copyright 2001-2009 Internet2
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * @file shibsp/paths.h
+ * 
+ * Default configuration paths.
+ */
+
+#ifndef __shibsp_paths_h__
+#define __shibsp_paths_h__
+
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "/opt/shibboleth-sp/share/xml/xmltooling/catalog.xml:/opt/shibboleth-sp/share/xml/opensaml/saml20-catalog.xml:/opt/shibboleth-sp/share/xml/opensaml/saml11-catalog.xml:/opt/shibboleth-sp/share/xml/shibboleth/catalog.xml"
+
+/** Default name of SP configuration file. */
+#define SHIBSP_CONFIG "shibboleth2.xml"
+
+/** Default name of SP console tool logging file. */
+#define SHIBSP_LOGGING "console.logger"
+
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX  "/opt/shibboleth-sp"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR  "/opt/shibboleth-sp/lib"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR  "/opt/shibboleth-sp/var/log"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR  "/opt/shibboleth-sp/etc"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR  "/opt/shibboleth-sp/var/run"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR  "/opt/shibboleth-sp/share/xml"
+
+#endif /* __shibsp_paths_h__ */
index f35df0b..abd4f71 100644 (file)
@@ -1,53 +1,53 @@
-/*\r
- *  Copyright 2001-2009 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * @file shibsp/paths.h\r
- * \r
- * Default configuration paths.\r
- */\r
-\r
-#ifndef __shibsp_paths_h__\r
-#define __shibsp_paths_h__\r
-\r
-/** Default schema catalogs. */\r
-#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"\r
-\r
-/** Default name of SP configuration file. */\r
-#define SHIBSP_CONFIG "shibboleth2.xml"\r
-\r
-/** Default name of SP console tool logging file. */\r
-#define SHIBSP_LOGGING "console.logger"\r
-\r
-/** Default prefix for installation (used to resolve relative paths). */\r
-#define SHIBSP_PREFIX  "@-PREFIX-@"\r
-\r
-/** Library directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LIBDIR  "@-LIBDIR-@"\r
-\r
-/** Log directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_LOGDIR  "@-LOGDIR-@"\r
-\r
-/** Configuration directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_CFGDIR  "@-SYSCONFDIR-@"\r
-\r
-/** Runtime state directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_RUNDIR  "@-RUNDIR-@"\r
-\r
-/** XML directory for installation (used to resolve relative paths). */\r
-#define SHIBSP_XMLDIR  "@-XMLDIR-@"\r
-\r
-#endif /* __shibsp_paths_h__ */\r
+/*
+ *  Copyright 2001-2009 Internet2
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * @file shibsp/paths.h
+ * 
+ * Default configuration paths.
+ */
+
+#ifndef __shibsp_paths_h__
+#define __shibsp_paths_h__
+
+/** Default schema catalogs. */
+#define SHIBSP_SCHEMAS "@-XMLTOOLINGXMLDIR-@/catalog.xml:@-OPENSAMLXMLDIR-@/saml20-catalog.xml:@-OPENSAMLXMLDIR-@/saml11-catalog.xml:@-PKGXMLDIR-@/catalog.xml"
+
+/** Default name of SP configuration file. */
+#define SHIBSP_CONFIG "shibboleth2.xml"
+
+/** Default name of SP console tool logging file. */
+#define SHIBSP_LOGGING "console.logger"
+
+/** Default prefix for installation (used to resolve relative paths). */
+#define SHIBSP_PREFIX  "@-PREFIX-@"
+
+/** Library directory for installation (used to resolve relative paths). */
+#define SHIBSP_LIBDIR  "@-LIBDIR-@"
+
+/** Log directory for installation (used to resolve relative paths). */
+#define SHIBSP_LOGDIR  "@-LOGDIR-@"
+
+/** Configuration directory for installation (used to resolve relative paths). */
+#define SHIBSP_CFGDIR  "@-SYSCONFDIR-@"
+
+/** Runtime state directory for installation (used to resolve relative paths). */
+#define SHIBSP_RUNDIR  "@-RUNDIR-@"
+
+/** XML directory for installation (used to resolve relative paths). */
+#define SHIBSP_XMLDIR  "@-XMLDIR-@"
+
+#endif /* __shibsp_paths_h__ */
index c85af8c..60b5b7a 100644 (file)
@@ -39,9 +39,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(Remoted);
     protected:
-        Remoted() {}
+        Remoted();
     public:
-        virtual ~Remoted() {}
+        virtual ~Remoted();
 
         /**
          * Remoted classes implement this method to process incoming messages.
@@ -72,8 +72,10 @@ namespace shibsp {
      */
     class SHIBSP_API ListenerService : public virtual Remoted
     {
+    protected:
+        ListenerService();
     public:
-        virtual ~ListenerService() {}
+        virtual ~ListenerService();
 
         /**
          * Send a remoted message and return the response.
@@ -126,9 +128,7 @@ namespace shibsp {
          * @param force     true iff remnant network state should be forcibly cleared
          * @return true iff the service initialization was successful
          */
-        virtual bool init(bool force) {
-            return true;
-        }
+        virtual bool init(bool force);
 
         /**
          * OutOfProcess servers can implement server-side transport handling by
@@ -142,8 +142,7 @@ namespace shibsp {
         /**
          * OutOfProcess servers can implement server-side termination/cleanup.
          */
-        virtual void term() {
-        }
+        virtual void term();
 
     private:
         std::map<std::string,Remoted*> m_listenerMap;
index b361ec0..abcc045 100644 (file)
@@ -42,7 +42,7 @@ namespace shibsp {
     public:
         /// @cond OFF
         // constructors
-        DDF() : m_handle(NULL) {}
+        DDF();
         DDF(const char* n);
         DDF(const char* n, const char* val, bool safe=true);
         DDF(const char* n, long val);
@@ -77,13 +77,9 @@ namespace shibsp {
     
         // destructive node conversion methods
         DDF& empty();
-        DDF& string(const char* val) {
-            return string(const_cast<char*>(val), true);
-        }
-        DDF& unsafe_string(const char* val) {
-            return string(const_cast<char*>(val), true, false);
-        }
         DDF& string(char* val, bool copyit=true, bool safe=true);
+        DDF& string(const char* val);
+        DDF& unsafe_string(const char* val);
         DDF& string(long val);
         DDF& string(double val);
         DDF& integer(long val);
@@ -110,7 +106,7 @@ namespace shibsp {
         
         // indexed operators
         DDF operator[](unsigned long index) const;
-        DDF operator[](const char* path) const { return getmember(path); }
+        DDF operator[](const char* path) const;
     
         // named member access/creation
         DDF addmember(const char* path);
index f33b307..814db96 100644 (file)
@@ -48,6 +48,22 @@ void SHIBSP_API shibsp::registerListenerServices()
 #endif
 }
 
+Remoted::Remoted()
+{
+}
+
+Remoted::~Remoted()
+{
+}
+
+ListenerService::ListenerService()
+{
+}
+
+ListenerService::~ListenerService()
+{
+}
+
 Remoted* ListenerService::regListener(const char* address, Remoted* listener)
 {
     Remoted* ret=NULL;
@@ -96,3 +112,12 @@ void ListenerService::receive(DDF &in, ostream& out)
 
     dest->receive(in, out);
 }
+
+bool ListenerService::init(bool force)
+{
+    return true;
+}
+
+void ListenerService::term()
+{
+}
index ae44d4f..81122cf 100644 (file)
@@ -119,6 +119,10 @@ struct shibsp::ddf_body_t {
 
 // library implementation
 
+DDF::DDF() : m_handle(NULL)
+{
+}
+
 DDF::DDF(const char* n)
 {
     m_handle=new(nothrow) ddf_body_t;
@@ -365,6 +369,16 @@ DDF& DDF::string(char* val, bool copyit, bool safe)
     return *this;
 }
 
+DDF& DDF::string(const char* val)
+{
+    return string(const_cast<char*>(val), true);
+}
+
+DDF& DDF::unsafe_string(const char* val)
+{
+    return string(const_cast<char*>(val), true, false);
+}
+
 DDF& DDF::string(long val)
 {
     char buf[20];
@@ -600,6 +614,11 @@ DDF DDF::previous()
     return p;
 }
 
+DDF DDF::operator[](const char* path) const
+{
+    return getmember(path);
+}
+
 DDF DDF::operator[](unsigned long index) const
 {
     DDF d;
@@ -997,8 +1016,7 @@ DDF deserialize(DOMElement* root, bool lowercase)
             }
             else {
                 char* val = toUTF8(child->getNodeValue(), true);    // use malloc
-                if (val)
-                    obj.string(val, false); // don't re-copy the string
+                obj.string(val, false); // don't re-copy the string
             }
         }
     }
index 8df1c2f..79fe549 100644 (file)
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}\r
-// Microsoft Developer Studio generated include file.\r
-// Used by shibsp.rc\r
-//\r
-\r
-// Next default values for new objects\r
-// \r
-#ifdef APSTUDIO_INVOKED\r
-#ifndef APSTUDIO_READONLY_SYMBOLS\r
-#define _APS_NEXT_RESOURCE_VALUE        101\r
-#define _APS_NEXT_COMMAND_VALUE         40001\r
-#define _APS_NEXT_CONTROL_VALUE         1000\r
-#define _APS_NEXT_SYMED_VALUE           101\r
-#endif\r
-#endif\r
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by shibsp.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
index d52db86..8c4bea3 100644 (file)
@@ -31,6 +31,7 @@
 #include <xmltooling/security/AbstractPKIXTrustEngine.h>
 #include <xmltooling/security/KeyInfoResolver.h>
 #include <xmltooling/security/X509Credential.h>
+#include <xmltooling/util/Threads.h>
 
 using namespace shibsp;
 using namespace opensaml::saml2md;
index 8317554..e66c028 100644 (file)
@@ -43,6 +43,10 @@ SecurityPolicy::SecurityPolicy(const Application& application, const xmltooling:
     }
 }
 
+SecurityPolicy::~SecurityPolicy()
+{
+}
+
 opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProviderCriteria() const
 {
     if (!m_metadataCriteria)
@@ -51,3 +55,8 @@ opensaml::saml2md::MetadataProvider::Criteria& SecurityPolicy::getMetadataProvid
         m_metadataCriteria->reset();
     return *m_metadataCriteria;
 }
+
+const Application& SecurityPolicy::getApplication() const
+{
+    return m_application;
+}
index 29a3bf5..0357e82 100644 (file)
@@ -46,7 +46,7 @@ namespace shibsp {
          */
         SecurityPolicy(const Application& application, const xmltooling::QName* role=NULL, bool validate=true, const char* policyId=NULL);
 
-        virtual ~SecurityPolicy() {}
+        virtual ~SecurityPolicy();
 
         opensaml::saml2md::MetadataProvider::Criteria& getMetadataProviderCriteria() const;
 
@@ -55,9 +55,7 @@ namespace shibsp {
          *
          * @return the associated Application
          */
-        const Application& getApplication() const {
-            return m_application;
-        }
+        const Application& getApplication() const;
 
     private:
         const Application& m_application;
index e465154..a109bb8 100644 (file)
@@ -67,7 +67,7 @@
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xmltooling-lite1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1.lib xerces-c_3.lib xmltooling-lite1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                        RelativePath=".\attribute\ExtensibleAttribute.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\NameIDAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\ScopedAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\SimpleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath=".\attribute\XMLAttribute.cpp"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="handler"\r
index b39d484..d69080c 100644 (file)
@@ -28,8 +28,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
 //\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
- FILEVERSION 1,2,1,0\r
- PRODUCTVERSION 2,2,1,0\r
+ FILEVERSION 1,3,0,0\r
+ PRODUCTVERSION 2,3,0,0\r
  FILEFLAGSMASK 0x3fL\r
 #ifdef _DEBUG\r
  FILEFLAGS 0x1L\r
@@ -51,38 +51,38 @@ BEGIN
 #else\r
             VALUE "FileDescription", "Shibboleth SP Library\0"\r
 #endif\r
-            VALUE "FileVersion", "1, 2, 1, 0\0"\r
+            VALUE "FileVersion", "1, 3, 0, 0\0"\r
 #ifdef SHIBSP_LITE\r
 #ifdef _DEBUG\r
-            VALUE "InternalName", "shibsp-lite1_2D\0"\r
+            VALUE "InternalName", "shibsp-lite1_3D\0"\r
 #else\r
-            VALUE "InternalName", "shibsp-lite1_2\0"\r
+            VALUE "InternalName", "shibsp-lite1_3\0"\r
 #endif\r
 #else\r
 #ifdef _DEBUG\r
-            VALUE "InternalName", "shibsp1_2D\0"\r
+            VALUE "InternalName", "shibsp1_3D\0"\r
 #else\r
-            VALUE "InternalName", "shibsp1_2\0"\r
+            VALUE "InternalName", "shibsp1_3\0"\r
 #endif\r
 #endif\r
             VALUE "LegalCopyright", "Copyright Â© 2009 Internet2\0"\r
             VALUE "LegalTrademarks", "\0"\r
 #ifdef SHIBSP_LITE\r
 #ifdef _DEBUG\r
-            VALUE "OriginalFilename", "shibsp-lite1_2D.dll\0"\r
+            VALUE "OriginalFilename", "shibsp-lite1_3D.dll\0"\r
 #else\r
-            VALUE "OriginalFilename", "shibsp-lite1_2.dll\0"\r
+            VALUE "OriginalFilename", "shibsp-lite1_3.dll\0"\r
 #endif\r
 #else\r
 #ifdef _DEBUG\r
-            VALUE "OriginalFilename", "shibsp1_2D.dll\0"\r
+            VALUE "OriginalFilename", "shibsp1_3D.dll\0"\r
 #else\r
-            VALUE "OriginalFilename", "shibsp1_2.dll\0"\r
+            VALUE "OriginalFilename", "shibsp1_3.dll\0"\r
 #endif\r
 #endif\r
             VALUE "PrivateBuild", "\0"\r
-            VALUE "ProductName", "Shibboleth 2.2.1\0"\r
-            VALUE "ProductVersion", "2, 2, 1, 0\0"\r
+            VALUE "ProductName", "Shibboleth 2.3\0"\r
+            VALUE "ProductVersion", "2, 3, 0, 0\0"\r
             VALUE "SpecialBuild", "\0"\r
         END\r
     END\r
index cbd630d..72d6861 100644 (file)
@@ -67,7 +67,7 @@
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1D.lib xerces-c_3D.lib xsec_1D.lib saml2D.lib xmltooling1D.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2D.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3D.dll"\r
                                LinkIncremental="2"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(ConfigurationName);..\..\cpp-xmltooling\$(ConfigurationName)"\r
                                SubSystem="2"\r
                        <Tool\r
                                Name="VCLinkerTool"\r
                                AdditionalDependencies="log4shib1.lib xerces-c_3.lib xsec_1.lib saml2.lib xmltooling1.lib wsock32.lib"\r
-                               OutputFile="$(OutDir)\$(ProjectName)1_2.dll"\r
+                               OutputFile="$(OutDir)\$(ProjectName)1_3.dll"\r
                                LinkIncremental="1"\r
                                AdditionalLibraryDirectories="..\..\cpp-opensaml2\$(PlatformName)\$(ConfigurationName);..\..\cpp-xmltooling\$(PlatformName)\$(ConfigurationName)"\r
                                GenerateDebugInformation="true"\r
                                        RelativePath=".\metadata\MetadataExtSchemaValidators.cpp"\r
                                        >\r
                                </File>\r
+                               <File\r
+                                       RelativePath=".\metadata\MetadataProviderCriteria.cpp"\r
+                                       >\r
+                               </File>\r
                        </Filter>\r
                        <Filter\r
                                Name="remoting"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\NameIDAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\NameIDAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\ScopedAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\ScopedAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\SimpleAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\StringAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath=".\attribute\XMLAttribute.cpp"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath=".\attribute\XMLAttributeDecoder.cpp"\r
                                        >\r
                                </File>\r
                                                        >\r
                                                </File>\r
                                                <File\r
+                                                       RelativePath=".\attribute\filtering\impl\BasicFilteringContext.cpp"\r
+                                                       >\r
+                                               </File>\r
+                                               <File\r
                                                        RelativePath=".\attribute\filtering\impl\ChainingAttributeFilter.cpp"\r
                                                        >\r
                                                </File>\r
index d1cba90..0314896 100644 (file)
@@ -24,6 +24,7 @@
 #include "util/CGIParser.h"
 
 #include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/io/HTTPRequest.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
index c0e3371..66d133b 100644 (file)
 #define __shibsp_cgi_h__
 
 #include <shibsp/base.h>
-#include <xmltooling/io/HTTPRequest.h>
+
+#include <map>
+#include <string>
+
+namespace xmltooling {
+    class XMLTOOL_API HTTPRequest;
+};
 
 namespace shibsp {
 
index f2cb41a..0a5dadd 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -32,6 +32,18 @@ using namespace xmltooling;
 using namespace xercesc;
 using namespace std;
 
+PropertySet::PropertySet()
+{
+}
+
+PropertySet::~PropertySet()
+{
+}
+
+DOMPropertySet::DOMPropertySet() : m_parent(NULL), m_root(NULL)
+{
+}
+
 DOMPropertySet::~DOMPropertySet()
 {
     for (map<string,pair<char*,const XMLCh*> >::iterator i=m_map.begin(); i!=m_map.end(); i++)
@@ -39,6 +51,21 @@ DOMPropertySet::~DOMPropertySet()
     for_each(m_nested.begin(),m_nested.end(),cleanup_pair<string,DOMPropertySet>());
 }
 
+const PropertySet* DOMPropertySet::getParent() const
+{
+    return m_parent;
+}
+
+void DOMPropertySet::setParent(const PropertySet* parent)
+{
+    m_parent = parent;
+}
+
+const DOMElement* DOMPropertySet::getElement() const
+{
+    return m_root;
+}
+
 void DOMPropertySet::load(
     const DOMElement* e,
     Category* log,
@@ -70,7 +97,7 @@ void DOMPropertySet::load(
             if (remapper) {
                 remap=remapper->find(realname);
                 if (remap!=remapper->end()) {
-                    log->warn("remapping property (%s) to (%s)",realname,remap->second.c_str());
+                    log->warn("deprecation - remapping property (%s) to (%s)",realname,remap->second.c_str());
                     realname=remap->second.c_str();
                 }
             }
@@ -102,7 +129,7 @@ void DOMPropertySet::load(
         if (remapper) {
             remap=remapper->find(realname);
             if (remap!=remapper->end()) {
-                log->warn("remapping property set (%s) to (%s)",realname,remap->second.c_str());
+                log->warn("deprecation - remapping nested property set (%s) to (%s)",realname,remap->second.c_str());
                 realname=remap->second.c_str();
             }
         }
index d642615..a42294b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
 #define __shibsp_dompropset_h__
 
 #include <shibsp/util/PropertySet.h>
+
 #include <xmltooling/logging.h>
 
 namespace shibsp {
@@ -34,18 +35,12 @@ namespace shibsp {
     class SHIBSP_API DOMPropertySet : public virtual PropertySet
     {
     public:
-        DOMPropertySet() : m_parent(NULL), m_root(NULL) {}
+        DOMPropertySet();
         
         virtual ~DOMPropertySet();
 
-        const PropertySet* getParent() const {
-            return m_parent;
-        }
-
-        void setParent(const PropertySet* parent) {
-            m_parent = parent;
-        }
-
+        const PropertySet* getParent() const;
+        void setParent(const PropertySet* parent);
         std::pair<bool,bool> getBool(const char* name, const char* ns=NULL) const;
         std::pair<bool,const char*> getString(const char* name, const char* ns=NULL) const;
         std::pair<bool,const XMLCh*> getXMLString(const char* name, const char* ns=NULL) const;
@@ -53,10 +48,7 @@ namespace shibsp {
         std::pair<bool,int> getInt(const char* name, const char* ns=NULL) const;
         void getAll(std::map<std::string,const char*>& properties) const;
         const PropertySet* getPropertySet(const char* name, const char* ns=shibspconstants::ASCII_SHIB2SPCONFIG_NS) const;
-
-        const xercesc::DOMElement* getElement() const {
-            return m_root;
-        }
+        const xercesc::DOMElement* getElement() const;
 
         /**
          * Loads the property set from a DOM element.
index bfc7988..98c1091 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,7 +24,9 @@
 #define __shibsp_propset_h__
 
 #include <shibsp/util/SPConstants.h>
+
 #include <map>
+#include <string>
 #include <xercesc/dom/DOM.hpp>
 
 namespace shibsp {
@@ -36,9 +38,9 @@ namespace shibsp {
     {
         MAKE_NONCOPYABLE(PropertySet);
     protected:
-        PropertySet() {}
+        PropertySet();
     public:
-        virtual ~PropertySet() {}
+        virtual ~PropertySet();
 
         /**
          * Returns parent of this PropertySet, if any.
index 38f0a0a..6614bad 100644 (file)
-/*\r
- *  Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * SPConstants.cpp\r
- * \r
- * SP XML namespace constants \r
- */\r
-\r
-#include "internal.h"\r
-#include "util/SPConstants.h"\r
-#include <xercesc/util/XMLUniDefs.hpp>\r
-\r
-using namespace shibspconstants;\r
-\r
-const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);\r
-\r
-const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,\r
-  chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon,\r
-  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,\r
-  chLatin_m, chLatin_a, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,\r
-  chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
-  chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,\r
-  chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,\r
-    chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_u, chLatin_r, chLatin_i, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_n, chLatin_a, chLatin_m, chLatin_e,\r
-    chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull\r
-};\r
-\r
-const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest\r
-{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,\r
-  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,\r
-  chDigit_1, chPeriod, chDigit_0, chColon,\r
-  chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,\r
-  chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,\r
-  chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull\r
-};\r
-\r
-const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";\r
-\r
-const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";\r
-\r
-const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";\r
+/*
+ *  Copyright 2001-2007 Internet2
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * SPConstants.cpp
+ * 
+ * SP XML namespace constants 
+ */
+
+#include "internal.h"
+#include "util/SPConstants.h"
+#include <xercesc/util/XMLUniDefs.hpp>
+
+using namespace shibspconstants;
+
+const XMLCh shibspconstants::SHIB1_PROTOCOL_ENUM[] = // urn:mace:shibboleth:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_NS[] = // urn:mace:shibboleth:metadata:1.0
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chLatin_m, chLatin_e, chLatin_t, chLatin_a, chLatin_d, chLatin_a, chLatin_t, chLatin_a, chColon,
+  chDigit_1, chPeriod, chDigit_0, chNull
+};
+
+const XMLCh shibspconstants::SHIBMD_PREFIX[] = UNICODE_LITERAL_6(s,h,i,b,m,d);
+
+const XMLCh shibspconstants::SHIB2SPCONFIG_NS[] = // urn:mace:shibboleth:2.0:native:sp:config
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_n, chLatin_a, chLatin_t, chLatin_i, chLatin_v, chLatin_e, chColon,
+  chLatin_s, chLatin_p, chColon, chLatin_c, chLatin_o, chLatin_n, chLatin_f, chLatin_i, chLatin_g, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEMAP_NS[] = // urn:mace:shibboleth:2.0:attribute-map
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e, chDash,
+  chLatin_m, chLatin_a, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2SPNOTIFY_NS[] = // urn:mace:shibboleth:2.0:sp:notify
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_s, chLatin_p, chColon,
+  chLatin_n, chLatin_o, chLatin_t, chLatin_i, chLatin_f, chLatin_y, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_NS[] = // urn:mace:shibboleth:2.0:afp
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_BASIC_NS[] = // urn:mace:shibboleth:2.0:afp:mf:basic
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+  chLatin_b, chLatin_a, chLatin_s, chLatin_i, chLatin_c, chNull
+};
+
+const XMLCh shibspconstants::SHIB2ATTRIBUTEFILTER_MF_SAML_NS[] = // urn:mace:shibboleth:2.0:afp:mf:saml
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_2, chPeriod, chDigit_0, chColon, chLatin_a, chLatin_f, chLatin_p, chColon, chLatin_m, chLatin_f, chColon,
+  chLatin_s, chLatin_a, chLatin_m, chLatin_l, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_ATTRIBUTE_NAMESPACE_URI[] = // urn:mace:shibboleth:1.0:attributeNamespace:uri
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_a, chLatin_t, chLatin_t, chLatin_r, chLatin_i, chLatin_b, chLatin_u, chLatin_t, chLatin_e,
+    chLatin_N, chLatin_a, chLatin_m, chLatin_e, chLatin_s, chLatin_p, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_u, chLatin_r, chLatin_i, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_NAMEID_FORMAT_URI[] = // urn:mace:shibboleth:1.0:nameIdentifier
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_n, chLatin_a, chLatin_m, chLatin_e,
+    chLatin_I, chLatin_d, chLatin_e, chLatin_n, chLatin_t, chLatin_i, chLatin_f, chLatin_i, chLatin_e, chLatin_r, chNull
+};
+
+const XMLCh shibspconstants::SHIB1_AUTHNREQUEST_PROFILE_URI[] = // urn:mace:shibboleth:1.0:profiles:AuthnRequest
+{ chLatin_u, chLatin_r, chLatin_n, chColon, chLatin_m, chLatin_a, chLatin_c, chLatin_e, chColon,
+  chLatin_s, chLatin_h, chLatin_i, chLatin_b, chLatin_b, chLatin_o, chLatin_l, chLatin_e, chLatin_t, chLatin_h, chColon,
+  chDigit_1, chPeriod, chDigit_0, chColon,
+  chLatin_p, chLatin_r, chLatin_o, chLatin_f, chLatin_i, chLatin_l, chLatin_e, chLatin_s, chColon,
+  chLatin_A, chLatin_u, chLatin_t, chLatin_h, chLatin_n,
+  chLatin_R, chLatin_e, chLatin_q, chLatin_u, chLatin_e, chLatin_s, chLatin_t, chNull
+};
+
+const char shibspconstants::SHIB1_SESSIONINIT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:SessionInit";
+
+const char shibspconstants::SHIB1_LOGOUT_PROFILE_URI[] = "urn:mace:shibboleth:sp:1.3:Logout";
+
+const char shibspconstants::ASCII_SHIB2SPCONFIG_NS[] = "urn:mace:shibboleth:2.0:native:sp:config";
index dd730f9..20f9cc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #define __shibsp_constants_h__
 
 #include <shibsp/base.h>
-#ifndef SHIBSP_LITE
-# include <saml/util/SAMLConstants.h>
-#else
-# include <shibsp/lite/SAMLConstants.h>
-#endif
+#include <xercesc/util/XercesDefs.hpp>
 
 /**
  * Shibboleth SP XML constants.
index f83abd2..520dfc0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
  */
 
 #include "internal.h"
+#include "util/PropertySet.h"
 #include "util/TemplateParameters.h"
 
 #include <ctime>
@@ -31,6 +32,16 @@ using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
+TemplateParameters::TemplateParameters(const exception* e, const PropertySet* props)
+    : m_exception(e), m_toolingException(dynamic_cast<const XMLToolingException*>(e))
+{
+    setPropertySet(props);
+}
+
+TemplateParameters::~TemplateParameters()
+{
+}
+
 void TemplateParameters::setPropertySet(const PropertySet* props)
 {
     m_props = props;
@@ -48,6 +59,11 @@ void TemplateParameters::setPropertySet(const PropertySet* props)
 #endif
 }
 
+const XMLToolingException* TemplateParameters::getRichException() const
+{
+    return m_toolingException;
+}
+
 const char* TemplateParameters::getParameter(const char* name) const
 {
     if (m_exception) {
index f04f42a..783979c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2007 Internet2
+ *  Copyright 2001-2009 Internet2
  * 
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 #ifndef __shibsp_tempparams_h__
 #define __shibsp_tempparams_h__
 
-#include <shibsp/util/PropertySet.h>
+#include <shibsp/base.h>
+
 #include <xmltooling/util/TemplateEngine.h>
 
 namespace shibsp {
 
+    class SHIBSP_API PropertySet;
+
     /**
      * Supplies xmltooling TemplateEngine with additional parameters from a PropertySet.
      */
@@ -40,12 +43,9 @@ namespace shibsp {
          * @param e     an exception to supply additional parameters
          * @param props a PropertySet to supply additional parameters
          */
-        TemplateParameters(const std::exception* e=NULL, const PropertySet* props=NULL)
-            : m_exception(e), m_toolingException(dynamic_cast<const xmltooling::XMLToolingException*>(e)) {
-            setPropertySet(props);
-        }
+        TemplateParameters(const std::exception* e=NULL, const PropertySet* props=NULL);
 
-        virtual ~TemplateParameters() {}
+        virtual ~TemplateParameters();
         
         /**
          * Sets a PropertySet to supply additional parameters.
@@ -59,9 +59,7 @@ namespace shibsp {
          *
          * @return  an exception, or NULL
          */
-        const xmltooling::XMLToolingException* getRichException() const {
-            return m_toolingException;
-        }
+        const xmltooling::XMLToolingException* getRichException() const;
 
         const char* getParameter(const char* name) const;
         
index b08f76d..e8707e4 100644 (file)
@@ -38,8 +38,8 @@
  */
 
 #define SHIBSP_VERSION_MAJOR 1
-#define SHIBSP_VERSION_MINOR 2
-#define SHIBSP_VERSION_REVISION 1
+#define SHIBSP_VERSION_MINOR 3
+#define SHIBSP_VERSION_REVISION 0
 
 /** DO NOT MODIFY BELOW THIS LINE */
 
index b9ced07..7112067 100644 (file)
@@ -79,6 +79,8 @@ AMDEP_TRUE = @AMDEP_TRUE@
 AMTAR = @AMTAR@
 APR1_CONFIG = @APR1_CONFIG@
 APR_CONFIG = @APR_CONFIG@
+APU1_CONFIG = @APU1_CONFIG@
+APU_CONFIG = @APU_CONFIG@
 APXS = @APXS@
 APXS2 = @APXS2@
 APXS22 = @APXS22@
index 89cc34e..9b928a8 100644 (file)
-/*\r
- *  Copyright 2001-2007 Internet2\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-/**\r
- * mdquery.cpp\r
- * \r
- * SAML Metadata Query tool layered on SP configuration\r
- */\r
-\r
-#if defined (_MSC_VER) || defined(__BORLANDC__)\r
-# include "config_win32.h"\r
-#else\r
-# include "config.h"\r
-#endif\r
-\r
-#ifdef WIN32\r
-# define _CRT_NONSTDC_NO_DEPRECATE 1\r
-# define _CRT_SECURE_NO_DEPRECATE 1\r
-#endif\r
-\r
-#include <shibsp/Application.h>\r
-#include <shibsp/exceptions.h>\r
-#include <shibsp/SPConfig.h>\r
-#include <shibsp/ServiceProvider.h>\r
-#include <shibsp/metadata/MetadataProviderCriteria.h>\r
-#include <shibsp/util/SPConstants.h>\r
-#include <saml/saml2/metadata/Metadata.h>\r
-#include <xmltooling/logging.h>\r
-\r
-using namespace shibsp;\r
-using namespace opensaml::saml2md;\r
-using namespace opensaml;\r
-using namespace xmltooling::logging;\r
-using namespace xmltooling;\r
-using namespace std;\r
-\r
-void usage()\r
-{\r
-    cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;\r
-    cerr << "       mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;\r
-}\r
-\r
-int main(int argc,char* argv[])\r
-{\r
-    char* entityID = NULL;\r
-    char* appID = "default";\r
-    bool strict = true;\r
-    char* prot = NULL;\r
-    const XMLCh* protocol = NULL;\r
-    char* rname = NULL;\r
-    char* rns = NULL;\r
-\r
-    for (int i=1; i<argc; i++) {\r
-        if (!strcmp(argv[i],"-e") && i+1<argc)\r
-            entityID=argv[++i];\r
-        else if (!strcmp(argv[i],"-a") && i+1<argc)\r
-            appID=argv[++i];\r
-        else if (!strcmp(argv[i],"-p") && i+1<argc)\r
-            prot=argv[++i];\r
-        else if (!strcmp(argv[i],"-r") && i+1<argc)\r
-            rname=argv[++i];\r
-        else if (!strcmp(argv[i],"-ns") && i+1<argc)\r
-            rns=argv[++i];\r
-        else if (!strcmp(argv[i],"-saml10"))\r
-            protocol=samlconstants::SAML10_PROTOCOL_ENUM;\r
-        else if (!strcmp(argv[i],"-saml11"))\r
-            protocol=samlconstants::SAML11_PROTOCOL_ENUM;\r
-        else if (!strcmp(argv[i],"-saml2"))\r
-            protocol=samlconstants::SAML20P_NS;\r
-        else if (!strcmp(argv[i],"-idp"))\r
-            rname="IDPSSODescriptor";\r
-        else if (!strcmp(argv[i],"-aa"))\r
-            rname="AttributeAuthorityDescriptor";\r
-        else if (!strcmp(argv[i],"-pdp"))\r
-            rname="PDPDescriptor";\r
-        else if (!strcmp(argv[i],"-sp"))\r
-            rname="SPSSODescriptor";\r
-        else if (!strcmp(argv[i],"-nostrict"))\r
-            strict = false;\r
-    }\r
-\r
-    if (!entityID) {\r
-        usage();\r
-        return -10;\r
-    }\r
-\r
-    if (rname) {\r
-        if (!protocol) {\r
-            if (prot)\r
-                protocol = XMLString::transcode(prot);\r
-        }\r
-        if (!protocol) {\r
-            usage();\r
-            return -10;\r
-        }\r
-    }\r
-\r
-    SPConfig& conf=SPConfig::getConfig();\r
-    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);\r
-    if (!conf.init())\r
-        return -1;\r
-    if (!conf.instantiate()) {\r
-        conf.term();\r
-        return -2;\r
-    }\r
-\r
-    ServiceProvider* sp=conf.getServiceProvider();\r
-    sp->lock();\r
-\r
-    Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");\r
-\r
-    const Application* app = sp->getApplication(appID);\r
-    if (!app) {\r
-        log.error("unknown application ID (%s)", appID);\r
-        sp->unlock();\r
-        conf.term();\r
-        return -3;\r
-    }\r
-\r
-    app->getMetadataProvider()->lock();\r
-    MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);\r
-    if (rname) {\r
-        const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;\r
-        auto_ptr_XMLCh n(rname);\r
-        QName q(ns, n.get());\r
-        mc.role = &q;\r
-        mc.protocol = protocol;\r
-        const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;\r
-        if (role)\r
-            XMLHelper::serialize(role->marshall(), cout, true);\r
-        else\r
-            log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);\r
-    }\r
-    else {\r
-        const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;\r
-        if (entity)\r
-            XMLHelper::serialize(entity->marshall(), cout, true);\r
-        else\r
-            log.error("no metadata found for (%s)", entityID);\r
-    }\r
-\r
-    app->getMetadataProvider()->unlock();\r
-\r
-    sp->unlock();\r
-    conf.term();\r
-    return 0;\r
-}\r
+/*
+ *  Copyright 2001-2009 Internet2
+ * 
+ * Licensed 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.
+ */
+
+/**
+ * mdquery.cpp
+ * 
+ * SAML Metadata Query tool layered on SP configuration
+ */
+
+#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/Application.h>
+#include <shibsp/exceptions.h>
+#include <shibsp/SPConfig.h>
+#include <shibsp/ServiceProvider.h>
+#include <shibsp/metadata/MetadataProviderCriteria.h>
+#include <shibsp/util/SPConstants.h>
+#include <saml/saml2/metadata/Metadata.h>
+#include <xmltooling/logging.h>
+
+using namespace shibsp;
+using namespace opensaml::saml2md;
+using namespace opensaml;
+using namespace xmltooling::logging;
+using namespace xmltooling;
+using namespace std;
+
+using xercesc::XMLString;
+
+void usage()
+{
+    cerr << "usage: mdquery -e <entityID> [-a <app id> -nostrict]" << endl;
+    cerr << "       mdquery -e <entityID> -r <role> -p <protocol> [-a <app id> -ns <namespace> -nostrict]" << endl;
+}
+
+int main(int argc,char* argv[])
+{
+    char* entityID = NULL;
+    char* appID = "default";
+    bool strict = true;
+    char* prot = NULL;
+    const XMLCh* protocol = NULL;
+    char* rname = NULL;
+    char* rns = NULL;
+
+    for (int i=1; i<argc; i++) {
+        if (!strcmp(argv[i],"-e") && i+1<argc)
+            entityID=argv[++i];
+        else if (!strcmp(argv[i],"-a") && i+1<argc)
+            appID=argv[++i];
+        else if (!strcmp(argv[i],"-p") && i+1<argc)
+            prot=argv[++i];
+        else if (!strcmp(argv[i],"-r") && i+1<argc)
+            rname=argv[++i];
+        else if (!strcmp(argv[i],"-ns") && i+1<argc)
+            rns=argv[++i];
+        else if (!strcmp(argv[i],"-saml10"))
+            protocol=samlconstants::SAML10_PROTOCOL_ENUM;
+        else if (!strcmp(argv[i],"-saml11"))
+            protocol=samlconstants::SAML11_PROTOCOL_ENUM;
+        else if (!strcmp(argv[i],"-saml2"))
+            protocol=samlconstants::SAML20P_NS;
+        else if (!strcmp(argv[i],"-idp"))
+            rname="IDPSSODescriptor";
+        else if (!strcmp(argv[i],"-aa"))
+            rname="AttributeAuthorityDescriptor";
+        else if (!strcmp(argv[i],"-pdp"))
+            rname="PDPDescriptor";
+        else if (!strcmp(argv[i],"-sp"))
+            rname="SPSSODescriptor";
+        else if (!strcmp(argv[i],"-nostrict"))
+            strict = false;
+    }
+
+    if (!entityID) {
+        usage();
+        return -10;
+    }
+
+    if (rname) {
+        if (!protocol) {
+            if (prot)
+                protocol = XMLString::transcode(prot);
+        }
+        if (!protocol) {
+            usage();
+            return -10;
+        }
+    }
+
+    SPConfig& conf=SPConfig::getConfig();
+    conf.setFeatures(SPConfig::Metadata | SPConfig::Trust | SPConfig::OutOfProcess | SPConfig::Credentials);
+    if (!conf.init())
+        return -1;
+    if (!conf.instantiate()) {
+        conf.term();
+        return -2;
+    }
+
+    ServiceProvider* sp=conf.getServiceProvider();
+    sp->lock();
+
+    Category& log = Category::getInstance(SHIBSP_LOGCAT".Utility.MDQuery");
+
+    const Application* app = sp->getApplication(appID);
+    if (!app) {
+        log.error("unknown application ID (%s)", appID);
+        sp->unlock();
+        conf.term();
+        return -3;
+    }
+
+    app->getMetadataProvider()->lock();
+    MetadataProviderCriteria mc(*app, entityID, NULL, NULL, strict);
+    if (rname) {
+        const XMLCh* ns = rns ? XMLString::transcode(rns) : samlconstants::SAML20MD_NS;
+        auto_ptr_XMLCh n(rname);
+        QName q(ns, n.get());
+        mc.role = &q;
+        mc.protocol = protocol;
+        const RoleDescriptor* role = app->getMetadataProvider()->getEntityDescriptor(mc).second;
+        if (role)
+            XMLHelper::serialize(role->marshall(), cout, true);
+        else
+            log.error("compatible role %s not found for (%s)", q.toString().c_str(), entityID);
+    }
+    else {
+        const EntityDescriptor* entity = app->getMetadataProvider()->getEntityDescriptor(mc).first;
+        if (entity)
+            XMLHelper::serialize(entity->marshall(), cout, true);
+        else
+            log.error("no metadata found for (%s)", entityID);
+    }
+
+    app->getMetadataProvider()->unlock();
+
+    sp->unlock();
+    conf.term();
+    return 0;
+}
index 6fe35e2..9a1709d 100644 (file)
@@ -32,7 +32,6 @@
 #endif
 
 #include <shibsp/Application.h>
-#include <shibsp/exceptions.h>
 #include <shibsp/SPConfig.h>
 #include <shibsp/ServiceProvider.h>
 #include <shibsp/attribute/Attribute.h>
 #include <shibsp/metadata/MetadataProviderCriteria.h>
 #include <shibsp/util/SPConstants.h>
 
+#include <saml/exceptions.h>
 #include <saml/saml1/core/Assertions.h>
 #include <saml/saml2/core/Assertions.h>
 #include <saml/saml2/metadata/Metadata.h>
+#include <saml/saml2/metadata/MetadataProvider.h>
 #include <xercesc/util/XMLUniDefs.hpp>
 #include <xmltooling/XMLToolingConfig.h>
+#include <xmltooling/util/ParserPool.h>
 #include <xmltooling/util/XMLHelper.h>
 
 using namespace shibsp;
@@ -160,7 +162,8 @@ int main(int argc,char* argv[])
         SPConfig::Trust |
         SPConfig::AttributeResolution |
         SPConfig::Credentials |
-        SPConfig::OutOfProcess
+        SPConfig::OutOfProcess |
+        SPConfig::Caching
         );
     if (!conf.init())
         return -1;