/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright (c) 2005 Sun Microsystems Inc. All Rights Reserved * * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the License). You may not use this file except in * compliance with the License. * * You can obtain a copy of the License at * https://opensso.dev.java.net/public/CDDLv1.0.html or * opensso/legal/CDDLv1.0.txt * See the License for the specific language governing * permission and limitations under the License. * * When distributing Covered Code, include this CDDL * Header Notice in each file and include the License file * at opensso/legal/CDDLv1.0.txt. * If applicable, add the following below the CDDL Header, * with the fields enclosed by brackets [] replaced by * your own identifying information: * "Portions Copyrighted [year] [name of copyright owner]" * * $Id: SessionEncodeURL.java,v 1.7 2008/08/19 19:08:41 veiming Exp $ * * Portions Copyrighted 2011-2015 ForgeRock AS. */ package com.iplanet.dpro.session.share; import com.iplanet.am.util.SystemProperties; import com.sun.identity.shared.Constants; import com.sun.identity.shared.debug.Debug; import com.sun.identity.shared.encode.URLEncDec; import com.sun.identity.session.util.SessionUtils; import java.util.Hashtable; import javax.servlet.http.HttpServletRequest; /** * SessionEncodeURL class encodes the URL * with the cookie value as a query string * or extra path info based on the encoding scheme. *

* The cookie Value is written in the URL based on the encoding scheme * specified. The Cookie Value could be written as path info separated * by either a "/" OR ";" or as a query string. * *

* If the encoding scheme is SLASH then the cookie value would be * written in the URL as extra path info in the following format: * protocol://server:port/servletpath/<cookieName>=<cookieValue>? * queryString *

* Note that this format works only if the path is a servlet, if a * a JSP file is specified then web containers return with * "File Not found" error. To rewrite links which are JSP files with * cookie value use the SEMICOLON or QUERY encoding * scheme. * *

* If the encoding scheme is SEMICOLON then the cookie value would be * written in the URL as extra path info in the following format: * protocol://server:port/path;<cookieName=cookieValue> * ?queryString * Note that this is not supported in the servlet specification and * some web containers do not support this. * *

* If the encoding scheme is QUERY then the cookie value would be * written in the URL in the following format: *

 * protocol://server:port/path?<cookieName>=<cookieValue>
 * protocol://server:port/path?queryString&<cookieName>=<cookieValue>
 * 
*

* This is the default and OpenAM always encodes in this format * unless otherwise specified. If the URL passed in has query parameter then * entity escaping of ampersand will be done before appending the cookie * if the escape is true. Only the ampersand before appending cookie parameter * will be entity escaped. */ public class SessionEncodeURL { public static Debug debug; public final String delimiter = "_"; public static Hashtable sidHash = new Hashtable(); public static final String SESS_DELIMITER = ";"; // semicolon - ; public static final String SLASH_SESS_DELIMITER = "/"; public static final String QUERY = "?"; public static final String AMPERSAND = "&"; public static final String AMPERSAND_ESC = "&"; public static final String EQUAL = "="; private static SessionEncodeURL se = new SessionEncodeURL(); static boolean cookieEncoding = (SystemProperties .get(Constants.AM_COOKIE_ENCODE) != null && SystemProperties.get( Constants.AM_COOKIE_ENCODE).equalsIgnoreCase("true")); static { debug = Debug.getInstance("amSessionEncodeURL"); } /** * Constructs SessionEncodeURL * */ public SessionEncodeURL() { } /** * Encodes the URL with the cookie value as a query string or extra path * info based on the encoding scheme. if encoding scheme is QUERY , encoded * URL format will be : * protocol://server:port/path?cookieName=cookieValue * if escape is false then no entity escaping of ampersand. *

     * protocol://server:port/path?queryString&
     *         cookieName=cookieValue
     * 
* if escape is true then entity escaping of ampersand *
     * protocol://server:port/path?queryString&cookieName=cookieValue
     * 
*

* if encoding scheme is SLASH, encodedURL * format will be : * protocol://server:port/path/cookieName=cookieValue *

* if encoding scheme is SEMICOLON, encodedURL * format will be: * protocol://server:port/path;cookieName=cookieValue *

* * @param sidString Session ID. * @param url the URL to be encoded. * @param encodingScheme how the cookie will be encoded in as query string * or as extra path info (SLASH or * SEMICOLON) * @param escape true to escape ampersand. * @return the URL encoded with the session ID. */ public static String encodeURL(String sidString, String url, short encodingScheme, boolean escape) { String encodedURL = se.encodeSidURL(url, sidString, encodingScheme, escape); if (debug.messageEnabled()) { debug.message("URL recd.. " + url); debug.message("encodeURL .. " + encodedURL); debug.message("encodingScheme is.. " + encodingScheme); debug.message("escape is.. " + escape); } return encodedURL; } private static String getCookieName() { String name = System.getProperty("com.iplanet.am.cookie.name"); if (name == null) { name = SystemProperties.get("com.iplanet.am.cookie.name"); } return name; } /** * Checks whether the encoded URL has session id or not. And then extracts * the Session Id from it. * * @param request , * HTTPServletRequestObject * @return the extracted SessionID */ public static String getSidFromURL(HttpServletRequest request) { return getSidFromURL(request, getCookieName()); } /** * Checks whether the encoded URL has session id or not. And then extracts * the Session Id from it. * * @param request HTTP Servlet Request. * @param cookieName Cookie name. * @return the extracted Session ID */ public static String getSidFromURL(HttpServletRequest request, String cookieName) { String sidString = ""; if (request != null) { String url = request.getRequestURI(); if (url != null) { if ((url.indexOf(SLASH_SESS_DELIMITER + cookieName) != -1) || (url.indexOf(SESS_DELIMITER + cookieName) != -1)) { sidString = getSidFromURI(url, cookieName); } else { sidString = getSidFromQuery(request, cookieName); } } } if (debug.messageEnabled()) { debug.message("before decoding getSidFromURL:sidString=" + sidString); } if (cookieEncoding) { if (sidString != null) { sidString = URLEncDec.decode(sidString); } } if (debug.messageEnabled()) { debug.message("after decoding: getSidFromURL:sidString=" + sidString); } return sidString; } /* retrieves the session ID from the request URI */ private static String getSidFromURI(String url, String cookieName) { String sid = ""; if (url != null) { if (debug.messageEnabled()) { debug.message("getSidFromURI: url=" + url); } if ((url != null) && (url.length() > 0)) { int start = url.indexOf(cookieName); if (start != -1) { start = start + cookieName.length() + 1; int end = url.indexOf(QUERY, start); if (end != -1) { sid = url.substring(start, end - 1); } else { sid = url.substring(start); } } } } if (debug.messageEnabled()) { debug.message("getSidFromURL: sid =" + sid); } return sid; } /* extracts the sessionId from the request Query */ private static String getSidFromQuery(HttpServletRequest request, String cookieName) { String sid = ""; if (request != null) { sid = request.getParameter(cookieName); } if (debug.messageEnabled()) { debug.message("getSidFromQuery: request =" + request); debug.message("getSidFromQuery: sid =" + sid); } return sid; } /** * Encodes the specified URL by including the session ID in it. Similar to * javax.servlet.http.HttpServletResponse.encodeURL(). session * ID will be only be included if the client needs encoding. * * @param url URL to be rewritten with the session ID. * @param cookieStr Cookie value which will be append to the URL. * @param encodingScheme how the cookie will be encoded in as query string * or as extra path info (SLASH or * SEMICOLON) * @param escape true to escape ampersand. * @return the encoded URL. */ private String encodeSidURL(String url, String cookieStr, short encodingScheme, boolean escape) { // separate URI and Query String String uri = url; String qString = null; int index = url.indexOf(QUERY); if (index != -1) { uri = url.substring(0, index); qString = url.substring(index + 1); } String encodedURL = url; if (encodingScheme == SessionUtils.QUERY) { encodedURL = encodeSidInQueryString(uri, qString, cookieStr, escape); } else { encodedURL = encodeSidInURLPath(uri, qString, cookieStr, encodingScheme); } if (debug.messageEnabled()) { debug.message("encodeSidURL :: URI :" + uri); debug.message("encodeSidURL :: qString :" + qString); debug.message("encodeSidURL :: cookieStr:" + cookieStr); debug.message("encodeSidURL :: URL :" + encodedURL); } return encodedURL; } /** * Constructs the cookie string based on the URL and cookie String passed. * * @param url URL which needs to be rewritten. * @param cookieStr Cookie name and cookie value. * @param encodingScheme how the cookie will be encoded in as query string * or as extra path info (SLASH or * SEMICOLON). * @param escape true to escape ampersand. * @return encoded URL. */ public static String buildCookieString( String url, String cookieStr, short encodingScheme, boolean escape ) { return (encodingScheme == SessionUtils.QUERY) ? writeUrlInQuery(url, cookieStr, escape) : writeUrlInPath(url, cookieStr, encodingScheme); } /** * write the cookie string in the URL as extra path info */ private static String writeUrlInPath(String url, String cookieStr, short encodingScheme) { String sessionDelimiter = SLASH_SESS_DELIMITER; if (encodingScheme == SessionUtils.SEMICOLON) { sessionDelimiter = SESS_DELIMITER; } StringBuilder encodedURLBuf = new StringBuilder(); if (url.indexOf(cookieStr) == -1) { int i = url.indexOf(QUERY); if (i != -1) { String uri = url.substring(0, i); String query = url.substring(i, url.length()); encodedURLBuf.append(uri).append(sessionDelimiter).append( cookieStr).append(query); } else { encodedURLBuf.append(url).append(sessionDelimiter).append( cookieStr); } } else { encodedURLBuf.append(url); } String encodedURL = encodedURLBuf.toString(); if (debug.messageEnabled()) { debug.message("writeUrlInPath : encoded URL : " + encodedURL); } return encodedURL; } /** * write the cookie string in the URL as a query string */ private static String writeUrlInQuery(String url, String cookieStr, boolean escape) { StringBuffer encodedURLBuf = new StringBuffer().append(url); if (cookieStr != null && url.indexOf(cookieStr) == -1) { int i = url.indexOf(QUERY); if (i != -1) { if (escape) { encodedURLBuf.append(AMPERSAND_ESC).append(cookieStr); } else { encodedURLBuf.append(AMPERSAND).append(cookieStr); } } else { encodedURLBuf.append(QUERY).append(cookieStr); } } String encodedURL = encodedURLBuf.toString(); if (debug.messageEnabled()) { debug.message("writeUrlInQuery : encoded URL : " + encodedURL); } return encodedURL; } /* * Construct the cookie String. The cookie string is in the format * cookieName = cookieValue. @param sessionID which the is the cookie Value * @return the cookie String. */ public static String createCookieString(String cookieName, String sessionID) { StringBuilder cookieStrBuf = new StringBuilder(); cookieStrBuf.append(URLEncDec.encode(cookieName)).append(EQUAL); if (sessionID != null) { cookieStrBuf.append(URLEncDec.encode(sessionID)); } return cookieStrBuf.toString(); } /* Rewrites the URL with cookieString in the URI */ private static String encodeSidInURLPath(String uri, String qString, String cookieStr, short encodingScheme) { // remove any old sid's from the url String sessionDelimiter = SLASH_SESS_DELIMITER; if (encodingScheme == SessionUtils.SEMICOLON) { sessionDelimiter = SESS_DELIMITER; } int index = uri.indexOf(sessionDelimiter + getCookieName()); if (index != -1) { uri = uri.substring(0, index); } StringBuffer urlBuf = new StringBuffer(); if (cookieStr != null) { urlBuf = urlBuf.append(sessionDelimiter).append(cookieStr); } if ((qString != null) && (qString.length() > 0)) { urlBuf.append(QUERY).append(qString); } if (uri != null) { urlBuf.insert(0, uri); } return urlBuf.toString(); } /* * Rewrites the URL with cookieString in the Query Entity Escaping of * ampersand is done before appending query string if escape parameter * passed to this method is true */ private static String encodeSidInQueryString(String uri, String qString, String cookieStr, boolean escape) { // remove any old sid's from the url String escapeChar = AMPERSAND_ESC; if (!escape) { escapeChar = AMPERSAND; } StringBuilder urlBuf = new StringBuilder(); urlBuf.append(QUERY); if (qString != null) { int index = qString.indexOf(getCookieName()); String remQueryString = null; if (index != -1) { if (index > 0) { remQueryString = qString.substring(0, index - 1); } int ampIndex = qString.indexOf(AMPERSAND, index); if (ampIndex != -1) { String remString = qString.substring(ampIndex + 1, qString .length()); if (remQueryString != null && remQueryString.length() > 0) { remQueryString = remQueryString + escapeChar + remString; } else { remQueryString = remString; } } } else { remQueryString = qString; } if (debug.messageEnabled()) { debug.message("After extracting cookie from query: " + remQueryString); } if (remQueryString != null) { urlBuf.append(remQueryString).append(escapeChar); } } if ((cookieStr != null) && (cookieStr.length() > 0)) { urlBuf.append(cookieStr); } if (uri != null) { urlBuf.insert(0, uri); } return urlBuf.toString(); } }