Moved logout templates to Errors tag.
[shibboleth/sp.git] / shibsp / handler / impl / LogoutHandler.cpp
index 695db99..8bd3d56 100644 (file)
@@ -36,9 +36,12 @@ using namespace shibsp;
 using namespace xmltooling;
 using namespace std;
 
-pair<bool,long> LogoutHandler::sendLogoutPage(const Application& application, HTTPResponse& response, bool local, const char* status) const
+pair<bool,long> LogoutHandler::sendLogoutPage(
+    const Application& application, const HTTPRequest& request, HTTPResponse& response, bool local, const char* status
+    ) const
 {
-    pair<bool,const char*> prop = application.getString(local ? "localLogout" : "globalLogout");
+    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");
@@ -47,7 +50,8 @@ pair<bool,long> LogoutHandler::sendLogoutPage(const Application& application, HT
         if (!infile)
             throw ConfigurationException("Unable to access $1 HTML template.", params(1,local ? "localLogout" : "globalLogout"));
         TemplateParameters tp;
-        tp.setPropertySet(application.getPropertySet("Errors"));
+        tp.m_request = &request;
+        tp.setPropertySet(props);
         if (status)
             tp.m_map["logoutStatus"] = status;
         stringstream str;
@@ -62,7 +66,7 @@ pair<bool,long> LogoutHandler::sendLogoutPage(const Application& application, HT
 
 pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
 {
-    // If we're inside a chain, so do nothing.
+    // If we're inside a chain, do nothing.
     if (getParent())
         return make_pair(false,0L);
     
@@ -71,11 +75,7 @@ pair<bool,long> LogoutHandler::run(SPRequest& request, bool isHandler) const
         return make_pair(false,0L);
 
     // Try another front-channel notification. No extra parameters and the session is implicit.
-    pair<bool,long> ret = notifyFrontChannel(request.getApplication(), request, request);
-    if (ret.first)
-        return ret;
-
-    return make_pair(false,0L);
+    return notifyFrontChannel(request.getApplication(), request, request);
 }
 
 void LogoutHandler::receive(DDF& in, ostream& out)
@@ -120,6 +120,9 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
     if (param)
         index = atoi(param);
 
+    // "return" is a backwards-compatible "eventual destination" to go back to after logout completes.
+    param = request.getParameter("return");
+
     // Fetch the next front notification URL and bump the index for the next round trip.
     string loc = application.getNotificationURL(request.getRequestURL(), true, index++);
     if (loc.empty())
@@ -139,6 +142,10 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
     // Add a signal that we're coming back from notification and the next index.
     locstr << "?notifying=1&index=" << index;
 
+    // Add return if set.
+    if (param)
+        locstr << "&return=" << encoder->encode(param);
+
     // We preserve anything we're instructed to directly.
     if (params) {
         for (map<string,string>::const_iterator p = params->begin(); p!=params->end(); ++p)
@@ -152,7 +159,8 @@ pair<bool,long> LogoutHandler::notifyFrontChannel(
         }
     }
 
-    // Add the return parameter to the destination location and redirect.
+    // Add the notifier's return parameter to the destination location and redirect.
+    // This is NOT the same as the return parameter that might be embedded inside it ;-)
     loc = loc + "&return=" + encoder->encode(locstr.str().c_str());
     return make_pair(true,response.sendRedirect(loc.c_str()));
 }