OAuthLogout.jsp revision e8721886dbfd32e88cc7077cbee4b6bb1b44b443
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%--
3b4098640dd85040270f39b9a5ee5e22de99d3d6Mark Andrews DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75c0816e8295e180f4bc7f10db3d0d880383bc1cMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Copyright (c) 2011 ForgeRock Inc. All rights reserved.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein The contents of this file are subject to the terms
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein of the Common Development and Distribution License
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein (the License). You may not use this file except in
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein compliance with the License.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein You can obtain a copy of the License at
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein http://forgerock.org/license/CDDLv1.0.html
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein See the License for the specific language governing
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein permission and limitations under the License.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein When distributing Covered Code, include this CDDL
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews Header Notice in each file and include the License file
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein at http://forgerock.org/license/CDDLv1.0.html
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein If applicable, add the following below the CDDL Header,
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein with the fields enclosed by brackets [] replaced by
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein your own identifying information:
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews "Portions Copyrighted [year] [name of copyright owner]"
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein--%>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%--
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Portions Copyrighted 2012 Open Source Solution Technology Corporation
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein--%>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein "http://www.w3.org/TR/html4/loose.dtd">
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page language="java" pageEncoding="UTF-8" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="org.owasp.esapi.*" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="com.iplanet.am.util.SystemProperties" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="com.sun.identity.shared.Constants" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="static org.forgerock.openam.authentication.modules.oauth2.OAuthParam.*" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="java.io.IOException" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="java.util.ResourceBundle" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="java.util.Locale" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="java.util.MissingResourceException" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%@ page import="org.forgerock.openam.authentication.modules.oauth2.OAuthUtil" %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<%
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein // Internationalization stuff. You can use any internationalization framework
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews String lang = request.getParameter("lang");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein ResourceBundle resources;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Locale locale = null;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein try {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (lang != null && lang.length() != 0) {
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews locale = new Locale(lang);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein } else {
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews locale = request.getLocale();
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein resources = ResourceBundle.getBundle("amAuthOAuth", locale);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein OAuthUtil.debugMessage("OAuthLogout: obtained resource bundle with locale " + locale);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein } catch (MissingResourceException mr) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein OAuthUtil.debugError("OAuthLogout: Resource Bundle not found", mr);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein resources = ResourceBundle.getBundle("amAuthOAuth");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String logoutForm = ESAPI.encoder().encodeForHTML(LOGOUT_FORM);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String loggedoutParam = ESAPI.encoder().encodeForHTML(PARAM_LOGGEDOUT);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String gotoParam = ESAPI.encoder().encodeForHTML(PARAM_GOTO);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String logoutURLParam = ESAPI.encoder().encodeForHTML(PARAM_LOGOUT_URL);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String logmeoutValue = ESAPI.encoder().encodeForHTML(resources.getString("logmeout"));
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String donotValue = ESAPI.encoder().encodeForHTML(resources.getString("donot"));
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String doYouWantToLogout = resources.getString("doYouWantToLogout");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String youVeBeenLogedOut = resources.getString("youVeBeenLogedOut");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String loggingYouOut = resources.getString("loggingYouOut");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein // Getting and validating params
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String gotoURL = request.getParameter(PARAM_GOTO);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String gotoURLencAttr = "";
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String OAuth2IdP = "";
b05bdb520d83f7ecaad708fe305268c3420be01dMark Andrews
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String ServiceURI = SystemProperties.get(Constants.AM_SERVICES_DEPLOYMENT_DESCRIPTOR);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (gotoURL == null || gotoURL.isEmpty() ) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein gotoURL = ServiceURI + "/UI/Logout";
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein } else {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein boolean isValidURL = ESAPI.validator().
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein isValidInput("URLContext", gotoURL, "URL", 255, false);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews boolean isValidURI = ESAPI.validator().
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews isValidInput("HTTP URI: " + gotoURL, gotoURL, "HTTPURI", 2000, false);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews if (!isValidURL && !isValidURI) {
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews OAuthUtil.debugError("OAuthLogout: wrong goto URL attempted to be used "
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews + "in the Logout page: " + gotoURL);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews gotoURL = "wronggotoURL";
47012ae6dbf18a2503d7b33c1c9583dc38625cb7Mark Andrews }
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce }
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce String logoutURL = request.getParameter(PARAM_LOGOUT_URL);
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce if (logoutURL == null) {
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce logoutURL = "";
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce } else {
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce boolean isValidURL = ESAPI.validator().
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce isValidInput("URLContext", logoutURL, "URL", 255, false);
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce if (!isValidURL) {
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce OAuthUtil.debugError("OAuthLogout: wrong logoutURL URL attempted to be used "
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce + "in the Logout page: " + logoutURL);
47012ae6dbf18a2503d7b33c1c9583dc38625cb7Mark Andrews logoutURL = "wronglogoutURL";
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce } else {
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce int loc1 = logoutURL.indexOf("//") + 2;
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce OAuth2IdP = logoutURL.substring(loc1, logoutURL.indexOf("/", loc1));
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce doYouWantToLogout = doYouWantToLogout.replace("#IDP#", OAuth2IdP);
f293a69bcd1c1dd7bdac8f4102fc2398b9e475c8Eric Luce }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein String copyrightNotice = null;
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein try{
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein copyrightNotice = ResourceBundle.getBundle("amAuthUI", locale).getString("copyright.notice");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein } catch (MissingResourceException mr) {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews String loggedout = request.getParameter(PARAM_LOGGEDOUT);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews System.out.println("loggedout=" + loggedout);
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews%>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein<html xmlns="http://www.w3.org/1999/xhtml">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <head>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <link href="<%= ServiceURI%>/css/new_style.css" rel="stylesheet" type="text/css" />
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews <!--[if IE 9]> <link href="<%= ServiceURI %>/css/ie9.css" rel="stylesheet" type="text/css"> <![endif]-->
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <!--[if lte IE 7]> <link href="<%= ServiceURI %>/css/ie7.css" rel="stylesheet" type="text/css"> <![endif]-->
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews <script language="JavaScript" type="text/javascript">
b05bdb520d83f7ecaad708fe305268c3420be01dMark Andrews function adios() {
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews window.location = "<%= gotoURL %>";
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein function logoutAll() {
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein // Creates an iFrame to log out from the OAuth 2.0 IdP
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews var frame = document.getElementById('frame');
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein if (!frame){return};
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein var logMsg = document.getElementById('logoutMsg');
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein var logMsgVs = document.getElementById('logoutMsgVisible');
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein var main = document.getElementById('main');
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews logMsg.style.display = '';
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein main.style.display = 'none';
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein logMsgVs.style.display = 'none';
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein var iframe = document.createElement('iframe');
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein iframe.setAttribute('src', '<%= logoutURL %>');
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein iframe.setAttribute('width', 0);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein iframe.setAttribute('height', 0);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein iframe.setAttribute('frameborder', 0);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein frame.innerHTML = '';
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews iframe.onload = adios();
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein frame.appendChild(iframe);
47012ae6dbf18a2503d7b33c1c9583dc38625cb7Mark Andrews }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <% if (loggedout != null && loggedout.equalsIgnoreCase("logmeout")){
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out.println("window.onload = function() {");
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out.println("logoutAll(); }");
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews }
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews %>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </script>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <title>Logout</title>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </head>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <body>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="container_12">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="grid_4 suffix_8">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <a class="logo" href="<%= ServiceURI%>"></a>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="box box-spaced clear-float">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="grid_3">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="product-logo"></div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="grid_9">
47012ae6dbf18a2503d7b33c1c9583dc38625cb7Mark Andrews <div class="box-content clear-float">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="message">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <span class="icon info"></span>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div id="logoutMsg" style="display:none">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <h3><%= loggingYouOut %></h3>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews <div id="logoutMsgVisible">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <h3><%= doYouWantToLogout %></h3>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div id="frame">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <noscript>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein Your browser does not support scripts.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein This page needs javascript to be enabled in your browser.
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </noscript>
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews </div>
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews <div id="main">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <form name="<%= logoutForm %>" method="POST" action="">
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews <input name="<%= loggedoutParam %>" type="button" class="button" onClick="adios()" onmousedown="adios()" value="<%= donotValue %>" />
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews <input name="<%= loggedoutParam %>" type="button" class="button right" onClick="logoutAll()" onmousedown="adios()" value="<%= logmeoutValue %>" />
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews </form>
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews </div>
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews </div>
5a4557e8de2951a2796676b5ec4b6a90caa5be14Mark Andrews </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="footer alt-color">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <div class="grid_6 suffix_3">
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <p>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein <% if (copyrightNotice != null){
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein out.println(copyrightNotice);
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein }
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein %>
71c66a876ecca77923638d3f94cc0783152b2f03Mark Andrews </p>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </div>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein </body>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein</html>
60e5e10f8d2e2b0c41e8abad38cacd867caa6ab2Rob Austein