Attribute lookup, port ACL code and mainline SP code to Session/Attribute API.
[shibboleth/cpp-sp.git] / shibsp / AbstractSPRequest.cpp
index bfa6125..85dfe25 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright 2001-2006 Internet2
+ *  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.
@@ -23,6 +23,8 @@
 #include "internal.h"
 #include "AbstractSPRequest.h"
 #include "Application.h"
+#include "ServiceProvider.h"
+#include "SessionCache.h"
 #include "util/CGIParser.h"
 
 #include <log4cpp/Category.hh>
@@ -32,18 +34,99 @@ using namespace xmltooling;
 using namespace log4cpp;
 using namespace std;
 
-AbstractSPRequest::AbstractSPRequest(const Application* app)
-    : m_app(app), m_log(&Category::getInstance(SHIBSP_LOGCAT)), m_parser(NULL)
+AbstractSPRequest::AbstractSPRequest()
+    : m_sp(NULL), m_mapper(NULL), m_app(NULL), m_sessionTried(false), m_session(NULL),
+        m_log(&Category::getInstance(SHIBSP_LOGCAT)), m_parser(NULL)
 {
-    if (m_app)
-        return;
+    m_sp=SPConfig::getConfig().getServiceProvider();
+    m_sp->lock();
 }
 
 AbstractSPRequest::~AbstractSPRequest()
 {
+    if (m_session)
+        m_session->unlock();
+    if (m_mapper)
+        m_mapper->unlock();
+    if (m_sp)
+        m_sp->unlock();
     delete m_parser;
 }
 
+RequestMapper::Settings AbstractSPRequest::getRequestSettings() const
+{
+    if (m_mapper)
+        return m_settings;
+
+    // Map request to application and content settings.
+    m_mapper=m_sp->getRequestMapper();
+    m_mapper->lock();
+    return m_settings = m_mapper->getSettings(*this);
+
+}
+
+const Application& AbstractSPRequest::getApplication() const
+{
+    if (!m_app) {
+        // Now find the application from the URL settings
+        m_app=m_sp->getApplication(getRequestSettings().first->getString("applicationId").second);
+        if (!m_app)
+            throw ConfigurationException("Unable to map request to application settings, check configuration.");
+    }    
+    return *m_app;
+}
+
+Session* AbstractSPRequest::getSession() const
+{
+    // Only attempt this once.
+    if (m_sessionTried)
+        return m_session;
+    m_sessionTried = true;
+
+    // Get session ID from cookie.
+    const Application& app = getApplication();
+    pair<string,const char*> shib_cookie = app.getCookieNameProps("_shibsession_");
+    const char* session_id = getCookie(shib_cookie.first.c_str());
+    if (!session_id || !*session_id)
+        return NULL;
+
+    // Need address checking and timeout settings.
+    int timeout=0;
+    bool consistent=true;
+    const PropertySet* props=app.getPropertySet("Sessions");
+    if (props) {
+        pair<bool,unsigned int> p=props->getUnsignedInt("timeout");
+        if (p.first)
+            timeout = p.second;
+        pair<bool,bool> pcheck=props->getBool("consistentAddress");
+        if (pcheck.first)
+            consistent = pcheck.second;
+    }
+
+    // The cache will either silently pass a session or NULL back, or throw an exception out.
+    return m_session = getServiceProvider().getSessionCache()->find(
+        session_id, app, consistent ? getRemoteAddr().c_str() : NULL, timeout
+        );
+}
+
+const char* AbstractSPRequest::getRequestURL() const {
+    if (m_url.empty()) {
+        // Compute the full target URL
+        int port = getPort();
+        const char* scheme = getScheme();
+        m_url = string(scheme) + "://" + getHostname();
+        if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) { 
+            ostringstream portstr;
+            portstr << port;
+            m_url += ":" + portstr.str();
+        }
+        scheme = getRequestURI();
+        if (scheme)
+            m_url += scheme;
+    }
+    return m_url.c_str();
+}
+
 const char* AbstractSPRequest::getParameter(const char* name) const
 {
     if (!m_parser)