[cpp-sp] branch main updated: Move HTTP request/response interfaces/impls out of xmltooling.

Scott Cantor cantor.2 at osu.edu
Mon Dec 2 16:16:17 UTC 2024


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

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

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

The following commit(s) were added to refs/heads/main by this push:
     new 33077df5 Move HTTP request/response interfaces/impls out of xmltooling.
33077df5 is described below

commit 33077df5ef8857c2a4f02f341e3abd5119d505d7
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Mon Dec 2 11:16:12 2024 -0500

    Move HTTP request/response interfaces/impls out of xmltooling.
---
 shibsp/Application.h                            |   4 +-
 shibsp/Makefile.am                              |  10 +
 shibsp/RequestMapper.h                          |   7 +-
 shibsp/SPRequest.h                              |  30 ++-
 shibsp/ServiceProvider.cpp                      |   2 +-
 shibsp/SessionCache.h                           |  39 +---
 shibsp/handler/AbstractHandler.h                |  20 +-
 shibsp/handler/AssertionConsumerService.h       |  12 +-
 shibsp/handler/Handler.h                        |  16 +-
 shibsp/handler/LogoutHandler.h                  |   8 +-
 shibsp/handler/RemotedHandler.h                 |  16 +-
 shibsp/handler/impl/AbstractHandler.cpp         |   2 +-
 shibsp/handler/impl/AttributeCheckerHandler.cpp |   2 +-
 shibsp/handler/impl/LogoutHandler.cpp           |   2 +-
 shibsp/handler/impl/RemotedHandler.cpp          |  22 --
 shibsp/impl/StorageServiceSessionCache.cpp      |   5 +-
 shibsp/impl/StorageServiceSessionCache.h        |  29 +--
 shibsp/impl/StoredSession.cpp                   |  12 +-
 shibsp/impl/XMLApplication.h                    |   2 +-
 shibsp/internal.h                               |   2 +-
 shibsp/io/GenericRequest.h                      | 221 ++++++++++++++++++++
 shibsp/io/GenericResponse.h                     |  78 +++++++
 shibsp/io/HTTPRequest.h                         | 128 ++++++++++++
 shibsp/io/HTTPResponse.h                        | 161 +++++++++++++++
 shibsp/io/impl/HTTPRequest.cpp                  | 259 ++++++++++++++++++++++++
 shibsp/io/impl/HTTPResponse.cpp                 | 172 ++++++++++++++++
 shibsp/util/CGIParser.cpp                       |   2 +-
 shibsp/util/CGIParser.h                         |   8 +-
 28 files changed, 1104 insertions(+), 167 deletions(-)

diff --git a/shibsp/Application.h b/shibsp/Application.h
index 5e80059d..b4f16ac9 100644
--- a/shibsp/Application.h
+++ b/shibsp/Application.h
@@ -34,7 +34,6 @@
 
 namespace xmltooling {
     class XMLTOOL_API CredentialResolver;
-    class XMLTOOL_API GenericRequest;
     class XMLTOOL_API RWLock;
     class XMLTOOL_API SOAPTransport;
     class XMLTOOL_API StorageService;
@@ -43,6 +42,7 @@ namespace xmltooling {
 namespace shibsp {
 
     class SHIBSP_API Attribute;
+    class SHIBSP_API GenericRequest;
     class SHIBSP_API Handler;
     class SHIBSP_API ServiceProvider;
     class SHIBSP_API SessionInitiator;
@@ -260,7 +260,7 @@ namespace shibsp {
          * @param request   the request leading to the redirect
          * @param url       an absolute URL to validate
          */
-        virtual void limitRedirect(const xmltooling::GenericRequest& request, const char* url) const;
+        virtual void limitRedirect(const GenericRequest& request, const char* url) const;
     };
 
 #if defined (_MSC_VER)
diff --git a/shibsp/Makefile.am b/shibsp/Makefile.am
index f5794045..a2eb0ebd 100644
--- a/shibsp/Makefile.am
+++ b/shibsp/Makefile.am
@@ -8,6 +8,8 @@ attrincludedir = $(includedir)/shibsp/attribute
 
 handincludedir = $(includedir)/shibsp/handler
 
+ioincludedir = $(includedir)/shibsp/io
+
 logincludedir = $(includedir)/shibsp/logging
 
 remincludedir = $(includedir)/shibsp/remoting
@@ -48,6 +50,12 @@ handinclude_HEADERS = \
 	handler/SecuredHandler.h \
 	handler/SessionInitiator.h
 
+ioinclude_HEADERS = \
+	io/GenericRequest.h \
+	io/GenericResponse.h \
+	io/HTTPRequest.h \
+	io/HTTPResponse.h
+
 loginclude_HEADERS = \
 	logging/Category.h \
 	logging/LoggingService.h \
@@ -119,6 +127,8 @@ libshibsp_la_SOURCES = \
 	impl/XMLApplication.cpp \
 	impl/XMLRequestMapper.cpp \
 	impl/XMLServiceProvider.cpp \
+	io/impl/HTTPRequest.cpp \
+	io/impl/HTTPResponse.cpp \
 	logging/impl/AbstractLoggingService.cpp \
 	logging/impl/Category.cpp \
 	logging/impl/ConsoleLoggingService.cpp \
diff --git a/shibsp/RequestMapper.h b/shibsp/RequestMapper.h
index 86513f6e..36c1e1fa 100644
--- a/shibsp/RequestMapper.h
+++ b/shibsp/RequestMapper.h
@@ -30,13 +30,10 @@
 #include <shibsp/base.h>
 #include <xmltooling/Lockable.h>
 
-namespace xmltooling {
-    class XMLTOOL_API HTTPRequest;
-};
-
 namespace shibsp {
 
     class SHIBSP_API AccessControl;
+    class SHIBSP_API HTTPRequest;
     class SHIBSP_API PropertySet;
 
     /**
@@ -62,7 +59,7 @@ namespace shibsp {
          * @param request   SP request
          * @return configuration settings and effective AccessControl plugin, if any
          */        
-        virtual Settings getSettings(const xmltooling::HTTPRequest& request) const=0;
+        virtual Settings getSettings(const HTTPRequest& request) const=0;
     };
 
     /**
diff --git a/shibsp/SPRequest.h b/shibsp/SPRequest.h
index 8764d796..4eeab88f 100644
--- a/shibsp/SPRequest.h
+++ b/shibsp/SPRequest.h
@@ -1,21 +1,15 @@
 /**
- * Licensed to the University Corporation for Advanced Internet
- * Development, Inc. (UCAID) under one or more contributor license
- * agreements. See the NOTICE file distributed with this work for
- * additional information regarding copyright ownership.
+ * 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
  *
- * UCAID licenses this file to you under the Apache License,
- * Version 2.0 (the "License"); you may not use this file except
- * in compliance with the License. You may obtain a copy of the
- * License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
  *
- * 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.
+ * 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.
  */
 
 /**
@@ -28,8 +22,8 @@
 #define __shibsp_req_h__
 
 #include <shibsp/RequestMapper.h>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
+#include <shibsp/io/HTTPRequest.h>
+#include <shibsp/io/HTTPResponse.h>
 
 namespace shibsp {
 
@@ -46,7 +40,7 @@ namespace shibsp {
      *
      * <p>This interface need not be threadsafe.
      */
-    class SHIBSP_API SPRequest : public virtual xmltooling::HTTPRequest, public virtual xmltooling::HTTPResponse
+    class SHIBSP_API SPRequest : public virtual HTTPRequest, public virtual HTTPResponse
     {
     protected:
         SPRequest();
diff --git a/shibsp/ServiceProvider.cpp b/shibsp/ServiceProvider.cpp
index 6ff684cd..c7e2f37b 100644
--- a/shibsp/ServiceProvider.cpp
+++ b/shibsp/ServiceProvider.cpp
@@ -715,7 +715,7 @@ pair<bool,long> ServiceProvider::doHandler(SPRequest& request) const
         Locker slocker(session, false); // pop existing lock on exit
         TemplateParameters tp(&e, nullptr, session);
         tp.m_map["requestURL"] = targetURL.substr(0, targetURL.find('?'));
-        tp.m_request = &request;
+        //stp.m_request = &request;
         return make_pair(true, sendError(log, request, app, "session", tp));
     }
 }
diff --git a/shibsp/SessionCache.h b/shibsp/SessionCache.h
index 4ca7cb88..4739b429 100644
--- a/shibsp/SessionCache.h
+++ b/shibsp/SessionCache.h
@@ -37,28 +37,12 @@
 #include <xercesc/util/XercesDefs.hpp>
 #include <xmltooling/Lockable.h>
 
-namespace xmltooling {
-    class XMLTOOL_API HTTPRequest;
-    class XMLTOOL_API HTTPResponse;
-};
-
-#ifndef SHIBSP_LITE
-# include <set>
-namespace opensaml {
-    class SAML_API Assertion;
-    namespace saml2 {
-        class SAML_API NameID;
-    };
-    namespace saml2md {
-        class SAML_API EntityDescriptor;
-    };
-};
-#endif
-
 namespace shibsp {
 
     class SHIBSP_API Application;
     class SHIBSP_API Attribute;
+    class SHIBSP_API HTTPRequest;
+    class SHIBSP_API HTTPResponse;
 
     /**
      * Encapsulates access to a user's security session.
@@ -131,17 +115,6 @@ namespace shibsp {
          */
         virtual const char* getAuthnInstant() const=0;
 
-#ifndef SHIBSP_LITE
-        /**
-         * Returns the NameID associated with a session.
-         *
-         * <p>SAML 1.x identifiers will be promoted to the 2.0 type.</p>
-         *
-         * @return a SAML 2.0 NameID associated with the session, if any
-         */
-        virtual const opensaml::saml2::NameID* getNameID() const=0;
-#endif
-
         /**
          * Returns the SessionIndex provided with the session.
          *
@@ -328,7 +301,7 @@ namespace shibsp {
          * @param request       request from client containing session, or a reference to it
          * @return  ID of session, if any known, or an empty string
          */
-        virtual std::string active(const Application& application, const xmltooling::HTTPRequest& request)=0;
+        virtual std::string active(const Application& application, const HTTPRequest& request)=0;
 
         /**
          * Locates an existing session bound to a request.
@@ -347,7 +320,7 @@ namespace shibsp {
          */
         virtual Session* find(
             const Application& application,
-            xmltooling::HTTPRequest& request,
+            HTTPRequest& request,
             const char* client_addr=nullptr,
             time_t* timeout=nullptr
             )=0;
@@ -364,8 +337,8 @@ namespace shibsp {
          */
         virtual void remove(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse* response=nullptr,
+            const HTTPRequest& request,
+            HTTPResponse* response=nullptr,
             time_t revocationExp=0
         )=0;
 
diff --git a/shibsp/handler/AbstractHandler.h b/shibsp/handler/AbstractHandler.h
index b25c0b01..60a29057 100644
--- a/shibsp/handler/AbstractHandler.h
+++ b/shibsp/handler/AbstractHandler.h
@@ -135,8 +135,8 @@ namespace shibsp {
          */
         virtual void preservePostData(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             const char* relayState
             ) const;
 
@@ -154,8 +154,8 @@ namespace shibsp {
          */
         virtual DDF recoverPostData(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             const char* relayState
             ) const;
 
@@ -169,7 +169,7 @@ namespace shibsp {
          */
         virtual long sendPostResponse(
             const Application& application,
-            xmltooling::HTTPResponse& response,
+            HTTPResponse& response,
             const char* url,
             DDF& postData
             ) const;
@@ -198,7 +198,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,bool> getBool(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,bool> getBool(const char* name, const HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns a string-valued property.
@@ -208,7 +208,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,const char*> getString(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,const char*> getString(const char* name, const HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns an unsigned integer-valued property.
@@ -218,7 +218,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,unsigned int> getUnsignedInt(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,unsigned int> getUnsignedInt(const char* name, const HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /**
          * Returns an integer-valued property.
@@ -228,7 +228,7 @@ namespace shibsp {
          * @param type      bitmask of property sources to use
          * @return a pair consisting of a nullptr indicator and the property value iff the indicator is true
          */
-        std::pair<bool,int> getInt(const char* name, const xmltooling::HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
+        std::pair<bool,int> getInt(const char* name, const HTTPRequest& request, unsigned int type=HANDLER_PROPERTY_ALL) const;
 
         /** Logging object. */
         Category& m_log;
@@ -238,7 +238,7 @@ namespace shibsp {
 
     private:
         std::string getPostCookieName(const Application& app, const char* relayState) const;
-        DDF getPostData(const Application& application, const xmltooling::HTTPRequest& request) const;
+        DDF getPostData(const Application& application, const HTTPRequest& request) const;
     };
 
 #if defined (_MSC_VER)
diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h
index de531b32..a3c1255b 100644
--- a/shibsp/handler/AssertionConsumerService.h
+++ b/shibsp/handler/AssertionConsumerService.h
@@ -81,7 +81,7 @@ namespace shibsp {
          * @param httpRequest   client request that initiated session
          * @param issuedTo      address for which security assertion was issued
          */
-        void checkAddress(const Application& application, const xmltooling::HTTPRequest& httpRequest, const char* issuedTo) const;
+        void checkAddress(const Application& application, const HTTPRequest& httpRequest, const char* issuedTo) const;
 
 
         /**
@@ -94,8 +94,8 @@ namespace shibsp {
          */
         virtual std::pair<bool,long> finalizeResponse(
             const Application& application,
-            const xmltooling::HTTPRequest& httpRequest,
-            xmltooling::HTTPResponse& httpResponse,
+            const HTTPRequest& httpRequest,
+            HTTPResponse& httpResponse,
             std::string& relayState
             ) const;
 
@@ -182,13 +182,13 @@ namespace shibsp {
 #endif
     private:
         std::pair<bool,long> processMessage(
-            const Application& application, const xmltooling::HTTPRequest& httpRequest, xmltooling::HTTPResponse& httpResponse
+            const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse
             ) const;
         
         std::pair<bool,long> sendRedirect(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             const char* entityID,
             const char* relayState
             ) const;                
diff --git a/shibsp/handler/Handler.h b/shibsp/handler/Handler.h
index 49652a1d..c9e1d742 100644
--- a/shibsp/handler/Handler.h
+++ b/shibsp/handler/Handler.h
@@ -30,13 +30,11 @@
 #include <shibsp/SPRequest.h>
 #include <shibsp/util/PropertySet.h>
 
-namespace xmltooling {
-    class XMLTOOL_API HTTPRequest;
-    class XMLTOOL_API HTTPResponse;
-};
-
 namespace shibsp {
 
+    class SHIBSP_API HTTPRequest;
+    class SHIBSP_API HTTPResponse;
+
     /**
      * Pluggable runtime functionality that implement protocols and services
      */
@@ -65,7 +63,7 @@ namespace shibsp {
          * @param response      outgoing HTTP response
          */
         virtual void cleanRelayState(
-            const Application& application, const xmltooling::HTTPRequest& request, xmltooling::HTTPResponse& response
+            const Application& application, const HTTPRequest& request, HTTPResponse& response
             ) const;
 
         /**
@@ -80,7 +78,7 @@ namespace shibsp {
          * @param relayState    RelayState token to supply with message
          */
         virtual void preserveRelayState(
-            const Application& application, xmltooling::HTTPResponse& response, std::string& relayState
+            const Application& application, HTTPResponse& response, std::string& relayState
             ) const;
 
         /**
@@ -98,8 +96,8 @@ namespace shibsp {
          */
         virtual void recoverRelayState(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             std::string& relayState,
             bool clear=true
             ) const;
diff --git a/shibsp/handler/LogoutHandler.h b/shibsp/handler/LogoutHandler.h
index 79c60e38..5658f62b 100644
--- a/shibsp/handler/LogoutHandler.h
+++ b/shibsp/handler/LogoutHandler.h
@@ -91,8 +91,8 @@ namespace shibsp {
          */
         std::pair<bool,long> notifyFrontChannel(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             const std::map<std::string,std::string>* params=nullptr
             ) const;
 
@@ -119,8 +119,8 @@ namespace shibsp {
          */
         std::pair<bool,long> sendLogoutPage(
             const Application& application,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse& response,
+            const HTTPRequest& request,
+            HTTPResponse& response,
             const char* type
             ) const;
     };
diff --git a/shibsp/handler/RemotedHandler.h b/shibsp/handler/RemotedHandler.h
index a22a5ec5..728cd4ca 100644
--- a/shibsp/handler/RemotedHandler.h
+++ b/shibsp/handler/RemotedHandler.h
@@ -32,13 +32,11 @@
 
 #include <set>
 
-namespace xmltooling {
-    class XMLTOOL_API HTTPRequest;
-    class XMLTOOL_API HTTPResponse;
-};
-
 namespace shibsp {
 
+    class SHIBSP_API HTTPRequest;
+    class SHIBSP_API HTTPResponse;
+
     /**
      * Base class for handlers that need HTTP request/response layer to be remoted.
      */
@@ -102,7 +100,7 @@ namespace shibsp {
          * @param in    the dataflow object containing the remoted request
          * @return  a call-specific request object based on the input, to be freed by the caller 
          */
-        xmltooling::HTTPRequest* getRequest(const Application& app, DDF& in) const;
+        HTTPRequest* getRequest(const Application& app, DDF& in) const;
         
         /**
          * Builds a new response instance around an outgoing data object.
@@ -111,7 +109,7 @@ namespace shibsp {
          * @param out   the dataflow object to be returned by the caller
          * @return  a call-specific response object, to be freed by the caller 
          */
-        xmltooling::HTTPResponse* getResponse(const Application& app, DDF& out) const;
+        HTTPResponse* getResponse(const Application& app, DDF& out) const;
 
         /**
         * @Deprecated
@@ -122,7 +120,7 @@ namespace shibsp {
         * @param in    the dataflow object containing the remoted request
         * @return  a call-specific request object based on the input, to be freed by the caller 
         */
-        xmltooling::HTTPRequest* getRequest(DDF& in) const;
+        HTTPRequest* getRequest(DDF& in) const;
 
         /**
         * @Deprecated
@@ -133,7 +131,7 @@ namespace shibsp {
         * @param out   the dataflow object to be returned by the caller
         * @return  a call-specific response object, to be freed by the caller 
         */
-        xmltooling::HTTPResponse* getResponse(DDF& out) const;
+        HTTPResponse* getResponse(DDF& out) const;
 
         /** Message address for remote half. */
         std::string m_address;
diff --git a/shibsp/handler/impl/AbstractHandler.cpp b/shibsp/handler/impl/AbstractHandler.cpp
index 000854ac..ccb22612 100644
--- a/shibsp/handler/impl/AbstractHandler.cpp
+++ b/shibsp/handler/impl/AbstractHandler.cpp
@@ -128,7 +128,7 @@ void Handler::log(SPRequest::SPLogLevel level, const string& msg) const
 }
 
 void Handler::cleanRelayState(
-    const Application& application, const xmltooling::HTTPRequest& request, xmltooling::HTTPResponse& response
+    const Application& application, const HTTPRequest& request, HTTPResponse& response
     ) const
 {
     pair<bool,const char*> mech = getString("relayState");
diff --git a/shibsp/handler/impl/AttributeCheckerHandler.cpp b/shibsp/handler/impl/AttributeCheckerHandler.cpp
index 548b870e..910870d3 100644
--- a/shibsp/handler/impl/AttributeCheckerHandler.cpp
+++ b/shibsp/handler/impl/AttributeCheckerHandler.cpp
@@ -195,7 +195,7 @@ pair<bool,long> AttributeCheckerHandler::run(SPRequest& request, bool isHandler)
         pair<bool,bool> externalParameters =
                 props ? props->getBool("externalParameters") : pair<bool,bool>(false,false);
         if (externalParameters.first && externalParameters.second) {
-            tp.m_request = &request;
+            //tp.m_request = &request;
         }
 
         stringstream str;
diff --git a/shibsp/handler/impl/LogoutHandler.cpp b/shibsp/handler/impl/LogoutHandler.cpp
index e5d41019..c38bb0ac 100644
--- a/shibsp/handler/impl/LogoutHandler.cpp
+++ b/shibsp/handler/impl/LogoutHandler.cpp
@@ -77,7 +77,7 @@ pair<bool,long> LogoutHandler::sendLogoutPage(
     pair<bool,bool> externalParameters =
             props ? props->getBool("externalParameters") : pair<bool,bool>(false,false);
     if (externalParameters.first && externalParameters.second) {
-        tp.m_request = &request;
+        //tp.m_request = &request;
     }
 
     tp.setPropertySet(props);
diff --git a/shibsp/handler/impl/RemotedHandler.cpp b/shibsp/handler/impl/RemotedHandler.cpp
index 6c3a2651..20290c06 100644
--- a/shibsp/handler/impl/RemotedHandler.cpp
+++ b/shibsp/handler/impl/RemotedHandler.cpp
@@ -357,28 +357,6 @@ DDF RemotedHandler::wrap(const SPRequest& request, const vector<string>* headers
         }
     }
 
-    if (certs) {
-#ifndef SHIBSP_LITE
-        const vector<XSECCryptoX509*>& xvec = request.getClientCertificates();
-        if (!xvec.empty()) {
-            DDF clist = in.addmember("certificates").list();
-            for (vector<XSECCryptoX509*>::const_iterator x = xvec.begin(); x!=xvec.end(); ++x) {
-                DDF x509 = DDF(nullptr).string((*x)->getDEREncodingSB().rawCharBuffer());
-                clist.add(x509);
-            }
-        }
-#else
-        const vector<string>& xvec = request.getClientCertificates();
-        if (!xvec.empty()) {
-            DDF clist = in.addmember("certificates").list();
-            for (vector<string>::const_iterator x = xvec.begin(); x!=xvec.end(); ++x) {
-                DDF x509 = DDF(nullptr).string(x->c_str());
-                clist.add(x509);
-            }
-        }
-#endif
-    }
-
     return in;
 }
 
diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp
index dc5fa796..8531344e 100644
--- a/shibsp/impl/StorageServiceSessionCache.cpp
+++ b/shibsp/impl/StorageServiceSessionCache.cpp
@@ -41,16 +41,15 @@
 #include "handler/RemotedHandler.h"
 #include "impl/StoredSession.h"
 #include "impl/StorageServiceSessionCache.h"
+#include "io/HTTPRequest.h"
+#include "io/HTTPResponse.h"
 #include "util/IPRange.h"
 #include "util/SPConstants.h"
 
 #include <algorithm>
 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
 #include <boost/bind.hpp>
-#include <xmltooling/io/HTTPRequest.h>
-#include <xmltooling/io/HTTPResponse.h>
 #include <xmltooling/security/DataSealer.h>
-#include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
 #include <xmltooling/util/URLEncoder.h>
 #include <xmltooling/util/XMLHelper.h>
diff --git a/shibsp/impl/StorageServiceSessionCache.h b/shibsp/impl/StorageServiceSessionCache.h
index d67915f1..65eb1453 100644
--- a/shibsp/impl/StorageServiceSessionCache.h
+++ b/shibsp/impl/StorageServiceSessionCache.h
@@ -28,11 +28,11 @@
 #define __shibsp_sscache_h__
 
 #include "SessionCache.h"
+#include "io/HTTPResponse.h"
 #include "remoting/ListenerService.h"
 
 #include <ctime>
 #include <boost/shared_ptr.hpp>
-#include <xmltooling/io/HTTPResponse.h>
 
 namespace xmltooling {
     class CondWait;
@@ -40,28 +40,11 @@ namespace xmltooling {
     class Thread;
 }
 
-#ifndef SHIBSP_LITE
-namespace opensaml {
-    class Assertion;
-
-    namespace saml2 {
-        class NameID;
-    };
-
-    namespace saml2md {
-        class EntityDescriptor;
-    };
-};
-#endif
-
 namespace shibsp {
 
     class IPRange;
     class StoredSession;
     class SHIBSP_DLLLOCAL SSCache : public SessionCache
-#ifndef SHIBSP_LITE
-        ,public virtual Remoted
-#endif
     {
     public:
         SSCache(const xercesc::DOMElement* e, bool deprecationSupport);
@@ -104,13 +87,13 @@ namespace shibsp {
             const std::set<std::string>* indexes
             );
 #endif
-        std::string active(const Application& app, const xmltooling::HTTPRequest& request);
-        Session* find(const Application& app, xmltooling::HTTPRequest& request, const char* client_addr=nullptr, time_t* timeout=nullptr);
+        std::string active(const Application& app, const HTTPRequest& request);
+        Session* find(const Application& app, HTTPRequest& request, const char* client_addr=nullptr, time_t* timeout=nullptr);
 
         void remove(
             const Application& app,
-            const xmltooling::HTTPRequest& request,
-            xmltooling::HTTPResponse* response=nullptr,
+            const HTTPRequest& request,
+            HTTPResponse* response=nullptr,
             time_t revocationExp=0
             );
 
@@ -165,7 +148,7 @@ namespace shibsp {
         // handle potentially inexact address comparisons
         bool compareAddresses(const char* client_addr, const char* session_addr) const;
 
-        xmltooling::HTTPResponse::samesite_t getSameSitePolicy(const Application& app) const;
+        HTTPResponse::samesite_t getSameSitePolicy(const Application& app) const;
 
         // management of buffered sessions
         void dormant(const char* key);
diff --git a/shibsp/impl/StoredSession.cpp b/shibsp/impl/StoredSession.cpp
index eab517f3..490cdf7d 100644
--- a/shibsp/impl/StoredSession.cpp
+++ b/shibsp/impl/StoredSession.cpp
@@ -34,17 +34,7 @@
 #include <xmltooling/util/NDC.h>
 #include <xmltooling/util/Threads.h>
 
-#ifndef SHIBSP_LITE
-# include <saml/exceptions.h>
-# include <saml/saml2/core/Assertions.h>
-# include <xmltooling/XMLToolingConfig.h>
-# include <xmltooling/util/ParserPool.h>
-# include <xmltooling/util/StorageService.h>
-# include <xercesc/util/XMLStringTokenizer.hpp>
-using namespace opensaml::saml2md;
-#else
-# include <xercesc/util/XMLDateTime.hpp>
-#endif
+#include <xercesc/util/XMLDateTime.hpp>
 
 using namespace shibsp;
 using namespace xmltooling;
diff --git a/shibsp/impl/XMLApplication.h b/shibsp/impl/XMLApplication.h
index a12c80f6..a0a44801 100644
--- a/shibsp/impl/XMLApplication.h
+++ b/shibsp/impl/XMLApplication.h
@@ -95,7 +95,7 @@ namespace shibsp {
         const Handler* getAssertionConsumerServiceByProtocol(const XMLCh* protocol, const char* binding=nullptr) const;
         const Handler* getHandler(const char* path) const;
         void getHandlers(std::vector<const Handler*>& handlers) const;
-        void limitRedirect(const xmltooling::GenericRequest& request, const char* url) const;
+        void limitRedirect(const GenericRequest& request, const char* url) const;
 
         void receive(DDF& in, std::ostream& out);
 
diff --git a/shibsp/internal.h b/shibsp/internal.h
index 35f052cc..c3c01dc9 100644
--- a/shibsp/internal.h
+++ b/shibsp/internal.h
@@ -45,8 +45,8 @@
 #include "logging/Category.h"
 
 #include <memory>
-#include <xmltooling/io/HTTPRequest.h>
 #include <shibsp/Application.h>
+#include <shibsp/io/HTTPRequest.h>
 
 using namespace xercesc;
 
diff --git a/shibsp/io/GenericRequest.h b/shibsp/io/GenericRequest.h
new file mode 100644
index 00000000..a51e8581
--- /dev/null
+++ b/shibsp/io/GenericRequest.h
@@ -0,0 +1,221 @@
+/**
+ * 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/io/GenericRequest.h
+ *
+ * Interface to generic protocol requests handled by agents.
+ */
+
+#ifndef __shibsp_genreq_h__
+#define __shibsp_genreq_h__
+
+#include <xmltooling/unicode.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * Interface to generic protocol requests handled by agents.
+     *
+     * <p>This interface need not be threadsafe.</p>
+     */
+    class SHIBSP_API GenericRequest {
+        MAKE_NONCOPYABLE(GenericRequest);
+    protected:
+        GenericRequest();
+    public:
+        virtual ~GenericRequest();
+
+        /**
+         * Returns the URL scheme of the request (http, https, ftp, ldap, etc.)
+         *
+         * @return the URL scheme
+         */
+        virtual const char* getScheme() const=0;
+
+        /**
+         * Returns true iff the request is over a confidential channel.
+         *
+         * @return confidential channel indicator
+         */
+        virtual bool isSecure() const=0;
+
+        /**
+         * Returns hostname of service that received request.
+         *
+         * @return hostname of service
+         */
+        virtual const char* getHostname() const=0;
+
+        /**
+         * Returns incoming port.
+         *
+         * @return  incoming port
+         */
+        virtual int getPort() const=0;
+
+        /**
+         * Returns true iff the request port is the default port for the request protocol.
+         *
+         * @return  default port indicator
+         */
+        virtual bool isDefaultPort() const;
+
+        /**
+         * Returns the MIME type of the request, if known.
+         *
+         * @return the MIME type, or an empty string
+         */
+        virtual std::string getContentType() const=0;
+
+        /**
+         * Returns the length of the request body, if known.
+         *
+         * @return the content length, or -1 if unknown
+         */
+        virtual long getContentLength() const=0;
+
+        /**
+         * Returns the raw request body.
+         *
+         * @return the request body, or nullptr
+         */
+        virtual const char* getRequestBody() const=0;
+
+        /**
+         * Returns a decoded named parameter value from the request.
+         * If a parameter has multiple values, only one will be returned.
+         *
+         * @param name  the name of the parameter to return
+         * @return a single parameter value or nullptr
+         */
+        virtual const char* getParameter(const char* name) const=0;
+
+        /**
+         * Returns all of the decoded values of a named parameter from the request.
+         * All values found will be returned.
+         *
+         * @param name      the name of the parameter to return
+         * @param values    a vector in which to return pointers to the decoded values
+         * @return  the number of values returned
+         */
+        virtual std::vector<const char*>::size_type getParameters(
+            const char* name, std::vector<const char*>& values
+            ) const=0;
+
+        /**
+         * Returns the transport-authenticated identity associated with the request,
+         * if authentication is solely handled by the transport.
+         *
+         * @return the authenticated username or an empty string
+         */
+        virtual std::string getRemoteUser() const=0;
+
+        /**
+         * Gets the authentication type associated with the request.
+         *
+         * @return  the authentication type or nullptr
+         */
+        virtual std::string getAuthType() const {
+            return "";
+        }
+
+        /**
+         * Returns the IP address of the client.
+         *
+         * @return the client's IP address
+         */
+        virtual std::string getRemoteAddr() const=0;
+
+        /**
+         * Converts a relative URL into an absolute one based on the properties of the request.
+         *
+         * @param url   input URL to convert, will be modified in place
+         */
+        virtual void absolutize(std::string& url) const;
+
+        /**
+         * Returns a language range to use in selecting language-specific
+         * content for this request.
+         * <p>The syntax is that of the HTTP 1.1 Accept-Language header, even
+         * if the underlying request is not HTTP.
+         *
+         * @return an HTTP 1.1 syntax language range specifier
+         */
+        virtual std::string getLanguageRange() const {
+            return "";
+        }
+
+        /**
+         * Initializes the language matching process; call this method to begin the
+         * matching process by calling the matchLang method.
+         * <p>The language matching process is not thread-safe and must be externally
+         * syncronized.
+         *
+         * @return  true iff language matching is possible
+         */
+        bool startLangMatching() const;
+
+        /**
+         * Continues the language matching process; additional calls to matchLang can
+         * be done as long as this method returns true.
+         * <p>The language matching process is not thread-safe and must be externally
+         * syncronized.
+         *
+         * @return  true iff more ranges are available to match against
+         */
+        bool continueLangMatching() const;
+
+        /**
+         * Matches a language tag against the currently active range.
+         * <p>The language matching process is not thread-safe and must be externally
+         * syncronized.
+         * 
+         * @param tag   a language tag (e.g., an xml:lang value)
+         * @return  true iff the tag matches the active range
+         */
+        bool matchLang(const XMLCh* tag) const;
+
+        /**
+         * Establish default handling of language ranges.
+         * 
+         * @param langFromClient    honor client's language preferences if any
+         * @param defaultRange      priority list of space-delimited language tags to use by default
+         */
+        static void setLangDefaults(bool langFromClient, const XMLCh* defaultRange);
+
+    private:
+        typedef std::multimap< float,std::vector<xmltooling::xstring> > langrange_t;
+        mutable langrange_t m_langRange;
+        mutable langrange_t::const_reverse_iterator m_langRangeIter;
+        static langrange_t m_defaultRange;
+        static bool m_langFromClient;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+};
+
+#endif /* __shibsp_genreq_h__ */
diff --git a/shibsp/io/GenericResponse.h b/shibsp/io/GenericResponse.h
new file mode 100644
index 00000000..94cadf2b
--- /dev/null
+++ b/shibsp/io/GenericResponse.h
@@ -0,0 +1,78 @@
+/**
+ * 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/io/GenericResponse.h
+ * 
+ * Interface to generic protocol responses issued by agents.
+ */
+
+#ifndef __shibsp_genres_h__
+#define __shibsp_genres_h__
+
+#include <shibsp/base.h>
+
+#include <iostream>
+
+namespace shibsp {
+    
+    /**
+     * Interface to generic protocol responses issued by agents.
+     * 
+     * <p>This interface need not be threadsafe.</p>
+     */
+    class SHIBSP_API GenericResponse {
+        MAKE_NONCOPYABLE(GenericResponse);
+    protected:
+        GenericResponse();
+    public:
+        virtual ~GenericResponse();
+
+        /**
+         * Sets or clears the MIME type of the response.
+         * 
+         * @param type the MIME type, or nullptr to clear
+         */
+        virtual void setContentType(const char* type=nullptr)=0;
+
+        /**
+         * Sends a completed response to the client along with a
+         * transport-specific "OK" indication. Used for "normal" responses.
+         * 
+         * @param inputStream   reference to source of response data
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendResponse(std::istream& inputStream)=0;
+
+        /**
+         * Sends an "error" response to the client along with a
+         * transport-specific error indication.
+         * 
+         * @param inputStream   reference to source of response data
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendError(std::istream& inputStream)=0;
+
+        /**
+         * Sends a completed response to the client.
+         * 
+         * @param inputStream   reference to source of response data
+         * @param status        transport-specific status to return
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendResponse(std::istream& inputStream, long status)=0;
+    };
+};
+
+#endif /* __shibsp_genres_h__ */
diff --git a/shibsp/io/HTTPRequest.h b/shibsp/io/HTTPRequest.h
new file mode 100644
index 00000000..a37e44ba
--- /dev/null
+++ b/shibsp/io/HTTPRequest.h
@@ -0,0 +1,128 @@
+/**
+ * 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/io/HTTPRequest.h
+ * 
+ * Interface to HTTP requests handled by agents.
+ */
+
+#ifndef __shibsp_httpreq_h__
+#define __shibsp_httpreq_h__
+
+#include <shibsp/io/GenericRequest.h>
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * Interface to HTTP requests handled by agents.
+     * 
+     * <p>To supply information from the surrounding web server environment,
+     * a shim must be supplied in the form of this interface to adapt the
+     * library to different proprietary server APIs.</p>
+     * 
+     * <p>This interface need not be threadsafe.</p>
+     */
+    class SHIBSP_API HTTPRequest : public GenericRequest {
+    protected:
+        HTTPRequest();
+    public:
+        virtual ~HTTPRequest();
+
+        bool isSecure() const;
+        bool isDefaultPort() const;
+        std::string getLanguageRange() const;
+          
+        /**
+         * Returns the HTTP method of the request (GET, POST, etc.)
+         * 
+         * @return the HTTP method
+         */
+        virtual const char* getMethod() const=0;
+        
+        /**
+         * Returns the request URI.
+         * 
+         * @return the request URI
+         */
+        virtual const char* getRequestURI() const=0;
+        
+        /**
+         * Returns the complete request URL, including scheme, host, port, and URI.
+         * 
+         * @return the request URL
+         */
+        virtual const char* getRequestURL() const=0;
+
+        /**
+         * Returns the HTTP query string appened to the request. The query
+         * string is returned without any decoding applied, everything found
+         * after the ? delimiter. 
+         * 
+         * @return the query string
+         */
+        virtual const char* getQueryString() const=0;
+
+        /**
+         * Returns a request header value.
+         * 
+         * @param name  the name of the header to return
+         * @return the header's value, or an empty string
+         */
+        virtual std::string getHeader(const char* name) const=0;
+
+        /**
+        * Get a cookie value supplied by the client.
+        * 
+        * @param name  name of cookie
+        * @return  cookie value or nullptr
+        */
+        virtual const char* getCookie(const char* name) const;
+
+        /**
+         * Get a cookie value supplied by the client.
+         *
+         * The boolean flag enables the workaround for older clients with
+         * broken SameSite support by looking for a second cookie with
+         * a decorated name that would not carry the SameSite flag.
+         * 
+         * @param name  name of cookie
+         * @param sameSiteFallback enables lookaside to fallback cookie name
+         * @return  cookie value or nullptr
+         */
+        virtual const char* getCookie(const char* name, bool sameSiteFallback) const;
+
+        /**
+         * Gets all the cookies supplied by the client.
+         *
+         * @return  a map of cookie name/value pairs
+         */
+        virtual const std::map<std::string,std::string>& getCookies() const;
+
+    private:
+        mutable std::map<std::string,std::string> m_cookieMap;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+
+};
+
+#endif /* __shibsp_httpreq_h__ */
diff --git a/shibsp/io/HTTPResponse.h b/shibsp/io/HTTPResponse.h
new file mode 100644
index 00000000..56afe511
--- /dev/null
+++ b/shibsp/io/HTTPResponse.h
@@ -0,0 +1,161 @@
+/**
+ * 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/io/HTTPResponse.h
+ * 
+ * Interface to HTTP responses issued by agents.
+ */
+
+#ifndef __shibsp_httpres_h__
+#define __shibsp_httpres_h__
+
+#include <shibsp/io/GenericResponse.h>
+
+#include <string>
+#include <vector>
+
+namespace shibsp {
+
+#if defined (_MSC_VER)
+    #pragma warning( push )
+    #pragma warning( disable : 4251 )
+#endif
+
+    /**
+     * Interface to HTTP response issued by agents.
+     * 
+     * <p>To supply information to the surrounding web server environment,
+     * a shim must be supplied in the form of this interface to adapt the
+     * library to different proprietary server APIs.</p>
+     * 
+     * <p>This interface need not be threadsafe.</p>
+     */
+    class SHIBSP_API HTTPResponse : public GenericResponse {
+    protected:
+        HTTPResponse();
+    public:
+        virtual ~HTTPResponse();
+        
+        void setContentType(const char* type);
+        
+        /**
+         * Sets, adds, or clears a response header.
+         * 
+         * @param name  header name
+         * @param value value to set, or nullptr to clear
+         * @param replace true iff this should replace existing header(s)
+         */
+        virtual void setResponseHeader(const char* name, const char* value, bool replace = false);
+
+        /** Cookie SameSite values. */
+        enum samesite_t {
+            SAMESITE_ABSENT = 0,
+            SAMESITE_NONE = 1,
+            SAMESITE_LAX = 2,
+            SAMESITE_STRICT = 3
+        };
+
+        /**
+        * Sets or unsets a client cookie.
+        * 
+        * <p>The boolean flag enables the workaround for older clients with
+        * broken SameSite support by setting a second cookie with
+        * a decorated name that would not carry the SameSite flag.</p>
+        *
+        * @param name  cookie name
+        * @param value value to set, or nullptr to clear
+        * @param expires optional expiration time for the cookie, 0 means session
+        * @param sameSiteValue the SameSite value to apply to the cookie
+        * @param sameSiteFallback enables setting of a fallback cookie
+        */
+        virtual void setCookie(
+            const char* name,
+            const char* value,
+            time_t expires,
+            samesite_t sameSiteValue,
+            bool sameSiteFallback);
+
+        /**
+         * Sets or unsets a client cookie.
+         *
+         * <p>Now defaults to calling the new version with a false flag.</p>
+         *
+         * @param name  cookie name
+         * @param value value to set, or nullptr to clear
+         * @param expires optional expiration time for the cookie, 0 means session
+         * @param sameSiteValue the SameSite value to apply to the cookie
+         */
+        virtual void setCookie(
+            const char* name,
+            const char* value,
+            time_t expires = 0,
+            samesite_t sameSiteValue = SAMESITE_ABSENT);
+
+        /**
+         * Redirect the client to the specified URL and complete the response.
+         * 
+         * <p>Any headers previously set will be sent ahead of the redirect.
+         *
+         * <p>The URL will be validated with the sanitizeURL method below.
+         *
+         * @param url   location to redirect client
+         * @return a result code to return from the calling MessageEncoder
+         */
+        virtual long sendRedirect(const char* url);
+        
+        /** Some common HTTP status codes. */
+        enum status_t {
+            XMLTOOLING_HTTP_STATUS_OK = 200,
+            XMLTOOLING_HTTP_STATUS_MOVED = 302,
+            XMLTOOLING_HTTP_STATUS_NOTMODIFIED = 304,
+            XMLTOOLING_HTTP_STATUS_BADREQUEST = 400,
+            XMLTOOLING_HTTP_STATUS_UNAUTHORIZED = 401,
+            XMLTOOLING_HTTP_STATUS_FORBIDDEN = 403,
+            XMLTOOLING_HTTP_STATUS_NOTFOUND = 404,
+            XMLTOOLING_HTTP_STATUS_ERROR = 500
+        };
+        
+        long sendError(std::istream& inputStream);
+
+        using GenericResponse::sendResponse;
+        long sendResponse(std::istream& inputStream);
+
+        /**
+         * Returns a modifiable array of schemes to permit in sanitized URLs.
+         *
+         * <p>Updates to this array must be externally synchronized with any use
+         * of this class or its subclasses.
+         *
+         * @return  a mutable array of strings containing the schemes to permit
+         */
+        static std::vector<std::string>& getAllowedSchemes();
+
+        /**
+         * Manually check for unsafe URLs vulnerable to injection attacks.
+         *
+         * @param url   location to check
+         */
+        static void sanitizeURL(const char* url);
+
+    private:
+        static std::vector<std::string> m_allowedSchemes;
+    };
+
+#if defined (_MSC_VER)
+    #pragma warning( pop )
+#endif
+};
+
+#endif /* __shibsp_httpres_h__ */
diff --git a/shibsp/io/impl/HTTPRequest.cpp b/shibsp/io/impl/HTTPRequest.cpp
new file mode 100644
index 00000000..1f147750
--- /dev/null
+++ b/shibsp/io/impl/HTTPRequest.cpp
@@ -0,0 +1,259 @@
+/**
+ * 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.
+ */
+
+/**
+ * io/impl/HTTPRequest.cpp
+ * 
+ * Interface to HTTP requests handled by agents.
+ */
+
+#include "internal.h"
+
+#include "io/HTTPRequest.h"
+
+#include <cstring>
+#include <boost/algorithm/string.hpp>
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS
+#include <boost/bind.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/tokenizer.hpp>
+#include <xercesc/util/XMLStringTokenizer.hpp>
+#include <xercesc/util/XMLUniDefs.hpp>
+#include <xmltooling/util/Threads.h>
+
+using namespace shibsp;
+using namespace xmltooling;
+using namespace xercesc;
+using namespace boost;
+using namespace std;
+
+bool GenericRequest::m_langFromClient = true;
+GenericRequest::langrange_t GenericRequest::m_defaultRange;
+
+GenericRequest::GenericRequest() : m_langRangeIter(m_langRange.rend())
+{
+}
+
+GenericRequest::~GenericRequest()
+{
+}
+
+bool GenericRequest::isDefaultPort() const
+{
+    return false;
+}
+
+void GenericRequest::absolutize(string& url) const
+{
+    if (url.empty())
+        url = '/';
+    if (url[0] == '/') {
+        // Compute a URL to the root of the site.
+        const char* scheme = getScheme();
+        string root = string(scheme) + "://" + getHostname();
+        if (!isDefaultPort())
+            root += ":" + lexical_cast<string>(getPort());
+        url = root + url;
+    }
+}
+
+void GenericRequest::setLangDefaults(bool langFromClient, const XMLCh* defaultRange)
+{
+    m_langFromClient = langFromClient;
+    m_defaultRange.clear();
+    if (!defaultRange)
+        return;
+    float q = 0.0f;
+    XMLStringTokenizer tokens(defaultRange);
+    while (tokens.hasMoreTokens()) {
+        const XMLCh* t = tokens.nextToken();
+        if (t && *t) {
+            vector<xstring> tagArray;
+            static const XMLCh delims[] = {chDash, chNull};
+            XMLStringTokenizer tags(t, delims);
+            while (tags.hasMoreTokens())
+                tagArray.push_back(tags.nextToken());
+            m_defaultRange.insert(langrange_t::value_type(q, tagArray));
+            q -= 0.0001f;
+        }
+    }
+}
+
+bool GenericRequest::startLangMatching() const
+{
+    // This is a no-op except on the first call, to populate the
+    // range information to use in matching.
+    if (m_langRange.empty()) {
+        if (m_langFromClient) {
+            string hdr(getLanguageRange());
+            char_separator<char> sep1(", "); // tags are split by commas or spaces
+            char_separator<char> sep2("; "); // quality is separated by semicolon
+            tokenizer< char_separator<char> > tokens(hdr, sep1);
+            for (tokenizer< char_separator<char> >::iterator t = tokens.begin(); t != tokens.end(); ++t) {
+                string tag = trim_copy(*t);   // handle any surrounding ws
+                tokenizer< char_separator<char> > subtokens(tag, sep2);
+                tokenizer< char_separator<char> >::iterator s = subtokens.begin();
+                if (s != subtokens.end() && *s != "*") {
+                    float q = 1.0f;
+                    auto_ptr_XMLCh lang((s++)->c_str());
+
+                    // Check for quality tag
+                    if (s != subtokens.end() && starts_with(*s, "q=")) {
+                        try {
+                            q = lexical_cast<float,string>(s->c_str() + 2);
+                        }
+                        catch (bad_lexical_cast&) {
+                            q = 0.0f;
+                        }
+                    }
+
+                    // Split range into tokens.
+                    vector<xstring> tagArray;
+                    static const XMLCh delims[] = {chDash, chNull};
+                    XMLStringTokenizer tags(lang.get(), delims);
+                    const XMLCh* tag;
+                    while (tags.hasMoreTokens()) {
+                        tag = tags.nextToken();
+                        if (*tag != chAsterisk)
+                            tagArray.push_back(tag);
+                    }
+
+                    if (tagArray.empty())
+                        continue;
+
+                    // Adjust q using the server priority list. As long as the supplied q deltas are larger than
+                    // factors like .0001, the client settings will always trump ours.
+                    if (!m_defaultRange.empty()) {
+                        float adj = (m_defaultRange.size() + 1) * 0.0001f;
+                        for (langrange_t::const_iterator prio = m_defaultRange.begin(); prio != m_defaultRange.end(); ++prio) {
+                            if (prio->second == tagArray) {
+                                adj = prio->first;
+                                break;
+                            }
+                        }
+                        q -= adj;
+                    }
+                    m_langRange.insert(langrange_t::value_type(q, tagArray));
+                }
+            }
+        }
+        else {
+            m_langRange = m_defaultRange;
+        }
+    }
+    
+    m_langRangeIter = m_langRange.rbegin();
+    return (m_langRangeIter != const_cast<const langrange_t&>(m_langRange).rend());
+}
+
+bool GenericRequest::continueLangMatching() const
+{
+    return (++m_langRangeIter != const_cast<const langrange_t&>(m_langRange).rend());
+}
+
+bool GenericRequest::matchLang(const XMLCh* tag) const
+{
+    if (m_langRangeIter == const_cast<const langrange_t&>(m_langRange).rend())
+        return false;
+
+    // To match against a given range, the range has to be built up and then
+    // truncated segment by segment to look for a match against the tag.
+    // That allows more specific ranges like en-US to match the tag en.
+    // The "end" fence tells us how much of the original range to recompose
+    // into a hyphenated string, and we stop on a match, or when the fence
+    // moves back to the beginning of the array.
+    bool match = false;
+    vector<xstring>::size_type end = m_langRangeIter->second.size();
+    do {
+        // Skip single-character private extension separators.
+        while (end > 1 && m_langRangeIter->second[end-1].length() <= 1)
+            --end;
+        // Build a range from 0 to end - 1 of segments.
+        xstring compareTo(m_langRangeIter->second[0]);
+        for (vector<xstring>::size_type ix = 1; ix <= end - 1; ++ix)
+            compareTo = compareTo + chDash + m_langRangeIter->second[ix];
+        match = (compareTo.length() > 1 && XMLString::compareIStringASCII(compareTo.c_str(), tag) == 0);
+    } while (!match && --end > 0);
+    return match;
+}
+
+HTTPRequest::HTTPRequest()
+{
+}
+
+HTTPRequest::~HTTPRequest()
+{
+}
+
+bool HTTPRequest::isSecure() const
+{
+    return strcmp(getScheme(),"https")==0;
+}
+
+bool HTTPRequest::isDefaultPort() const
+{
+    if (isSecure())
+        return getPort() == 443;
+    else
+        return getPort() == 80;
+}
+
+string HTTPRequest::getLanguageRange() const
+{
+    return getHeader("Accept-Language");
+}
+
+namespace {
+    void handle_cookie_fn(map<string,string>& cookieMap, vector<string>& nvpair, const string& s) {
+        nvpair.clear();
+        split(nvpair, s, is_any_of("="));
+        if (nvpair.size() == 2) {
+            trim(nvpair[0]);
+            if (ends_with(nvpair[0], "_fgwars")) {
+                nvpair[0].erase(nvpair[0].end() - 7, nvpair[0].end());
+            }
+            cookieMap[nvpair[0]] = nvpair[1];
+        }
+    }
+}
+
+const map<string,string>& HTTPRequest::getCookies() const
+{
+    if (m_cookieMap.empty()) {
+        string cookies=getHeader("Cookie");
+        vector<string> nvpair;
+        tokenizer< char_separator<char> > nvpairs(cookies, char_separator<char>(";"));
+        for_each(nvpairs.begin(), nvpairs.end(),
+            boost::bind(handle_cookie_fn, boost::ref(m_cookieMap), boost::ref(nvpair), _1));
+    }
+    return m_cookieMap;
+}
+
+const char* HTTPRequest::getCookie(const char* name) const
+{
+    return getCookie(name, false);
+}
+
+const char* HTTPRequest::getCookie(const char* name, bool) const
+{
+    // The fallback support is implemented via the getCookies() load above
+    // so we ignore it here.
+
+    map<string,string>::const_iterator lookup = getCookies().find(name);
+    if (lookup != m_cookieMap.end()) {
+        return lookup->second.c_str();
+    }
+
+    return nullptr;
+}
diff --git a/shibsp/io/impl/HTTPResponse.cpp b/shibsp/io/impl/HTTPResponse.cpp
new file mode 100644
index 00000000..cdada70c
--- /dev/null
+++ b/shibsp/io/impl/HTTPResponse.cpp
@@ -0,0 +1,172 @@
+/**
+ * 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.
+ */
+
+/**
+ * io/impl/HTTPResponse.cpp
+ * 
+ * Interface to HTTP responses issued by agents.
+ */
+
+#include "internal.h"
+#include "io/HTTPResponse.h"
+
+#include <stdexcept>
+
+#include <boost/algorithm/string/predicate.hpp>
+#define BOOST_BIND_GLOBAL_PLACEHOLDERS
+#include <boost/bind.hpp>
+
+using namespace shibsp;
+using namespace boost;
+using namespace std;
+
+GenericResponse::GenericResponse()
+{
+}
+
+GenericResponse::~GenericResponse()
+{
+}
+
+vector<string> HTTPResponse::m_allowedSchemes;
+
+vector<string>& HTTPResponse::getAllowedSchemes()
+{
+    return m_allowedSchemes;
+}
+
+void HTTPResponse::sanitizeURL(const char* url)
+{
+    // predicate for checking scheme below
+    static bool (*fn)(const string&, const string&, const std::locale&) = iequals;
+
+    const char* ch;
+    for (ch=url; *ch; ++ch) {
+        if (iscntrl((unsigned char)(*ch)))  // convert to unsigned to allow full range from 00-FF
+            throw domain_error("URL contained a control character.");
+    }
+
+    ch = strchr(url, ':');
+    if (!ch)
+        throw domain_error("URL is missing a colon where expected; improper URL encoding?");
+    string s(url, ch - url);
+    std::locale loc;
+    vector<string>::const_iterator i =
+        find_if(m_allowedSchemes.begin(), m_allowedSchemes.end(), boost::bind(fn, boost::cref(s), _1, boost::cref(loc)));
+    if (i != m_allowedSchemes.end())
+        return;
+
+    throw domain_error("URL contains invalid scheme.");
+}
+
+HTTPResponse::HTTPResponse()
+{
+}
+
+HTTPResponse::~HTTPResponse()
+{
+}
+
+void HTTPResponse::setContentType(const char* type)
+{
+    setResponseHeader("Content-Type", type);
+}
+
+void HTTPResponse::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSiteValue)
+{
+    setCookie(name, value, expires, sameSiteValue, false);
+}
+
+void HTTPResponse::setCookie(const char* name, const char* value, time_t expires, samesite_t sameSiteValue, bool sameSiteFallback)
+{
+    string decoratedValue;
+    if (!value) {
+        decoratedValue += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
+    }
+    else {
+        decoratedValue = value;
+        if (expires > 0) {
+            expires += time(nullptr);
+#ifndef HAVE_GMTIME_R
+            struct tm* ptime = gmtime(&expires);
+#else
+            struct tm res;
+            struct tm* ptime = gmtime_r(&expires, &res);
+#endif
+            char cookietimebuf[64];
+            strftime(cookietimebuf, 64, "; expires=%a, %d %b %Y %H:%M:%S GMT", ptime);
+            decoratedValue.append(cookietimebuf);
+        }
+    }
+
+    if (sameSiteValue != SAMESITE_ABSENT) {
+        // Add SameSite to the primary cookie and optionally set a fallback cookie without SameSite.
+        switch (sameSiteValue) {
+            case SAMESITE_NONE:
+                if (sameSiteFallback) {
+                    string hackedName(name);
+                    setResponseHeader("Set-Cookie", hackedName.append("_fgwars=").append(decoratedValue).c_str());
+                }
+                decoratedValue.append("; SameSite=None");
+                break;
+            case SAMESITE_LAX:
+                decoratedValue.append("; SameSite=Lax");
+                break;
+            case SAMESITE_STRICT:
+                decoratedValue.append("; SameSite=Strict");
+                break;
+            default:
+                throw invalid_argument("Invalid SameSite value supplied");
+        }
+        string header(name);
+        setResponseHeader("Set-Cookie", header.append("=").append(decoratedValue).c_str());
+    }
+    else {
+        string header(name);
+        setResponseHeader("Set-Cookie", header.append("=").append(decoratedValue).c_str());
+    }
+}
+
+void HTTPResponse::setResponseHeader(const char* name, const char* value, bool)
+{
+    if (name) {
+        for (const char* ch=name; *ch; ++ch) {
+            if (iscntrl(*ch))
+                throw domain_error("Response header name contained a control character.");
+        }
+    }
+
+    if (value) {
+        for (const char* ch=value; *ch; ++ch) {
+            if (iscntrl(*ch))
+                throw domain_error("Value for response header contained a control character.");
+        }
+    }
+}
+
+long HTTPResponse::sendRedirect(const char* url)
+{
+    sanitizeURL(url);
+    return XMLTOOLING_HTTP_STATUS_MOVED;
+}
+
+long HTTPResponse::sendError(istream& inputStream)
+{
+    return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_ERROR);
+}
+
+long HTTPResponse::sendResponse(istream& inputStream)
+{
+    return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_OK);
+}
diff --git a/shibsp/util/CGIParser.cpp b/shibsp/util/CGIParser.cpp
index 85d999bf..8c767226 100644
--- a/shibsp/util/CGIParser.cpp
+++ b/shibsp/util/CGIParser.cpp
@@ -25,12 +25,12 @@
  */
 
 #include "internal.h"
+#include "io/HTTPRequest.h"
 #include "util/CGIParser.h"
 
 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
 #include <boost/bind.hpp>
 #include <xmltooling/XMLToolingConfig.h>
-#include <xmltooling/io/HTTPRequest.h>
 #include <xmltooling/util/URLEncoder.h>
 
 using namespace shibsp;
diff --git a/shibsp/util/CGIParser.h b/shibsp/util/CGIParser.h
index 3e8c1c20..7dd3036f 100644
--- a/shibsp/util/CGIParser.h
+++ b/shibsp/util/CGIParser.h
@@ -32,12 +32,10 @@
 #include <map>
 #include <string>
 
-namespace xmltooling {
-    class XMLTOOL_API HTTPRequest;
-};
-
 namespace shibsp {
 
+    class SHIBSP_API HTTPRequest;
+
 #if defined (_MSC_VER)
     #pragma warning( push )
     #pragma warning( disable : 4251 )
@@ -56,7 +54,7 @@ namespace shibsp {
          * @param request   HTTP request interface
          * @param queryOnly true iff the POST body should be ignored
          */
-        CGIParser(const xmltooling::HTTPRequest& request, bool queryOnly=false);
+        CGIParser(const HTTPRequest& request, bool queryOnly=false);
 
         ~CGIParser();
 

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


More information about the commits mailing list