/* * Copyright (C) 2000-2015 aw2.0 LTD * * This file is part of Open BlueDragon (OpenBD) CFML Server Engine. * * OpenBD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * Free Software Foundation,version 3. * * OpenBD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenBD. If not, see http://www.gnu.org/licenses/ * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining * it with any of the JARS listed in the README.txt (or a modified version of * (that library), containing parts covered by the terms of that JAR, the * licensors of this Program grant you additional permission to convey the * resulting work. * README.txt @ http://www.openbluedragon.org/license/README.txt * * http://www.openbd.org/ * $Id: cfCookieData.java 2497 2015-02-02 01:53:48Z alan $ */ package com.naryx.tagfusion.cfm.cookie; import java.text.SimpleDateFormat; import java.util.Iterator; import java.util.Locale; import java.util.Map; import java.util.TimeZone; import javax.servlet.http.Cookie; import com.nary.net.http.urlEncoder; import com.naryx.tagfusion.cfm.engine.cfCatchData; import com.naryx.tagfusion.cfm.engine.cfData; import com.naryx.tagfusion.cfm.engine.cfEngine; import com.naryx.tagfusion.cfm.engine.cfSession; import com.naryx.tagfusion.cfm.engine.cfStringData; import com.naryx.tagfusion.cfm.engine.cfStructData; import com.naryx.tagfusion.cfm.engine.cfmRunTimeException; public class cfCookieData extends cfStructData implements java.io.Serializable { static final long serialVersionUID = 1; private transient cfSession session; private static SimpleDateFormat simpledateformat; static{ simpledateformat = new SimpleDateFormat("EEE, dd-MMM-yy HH:mm:ss", Locale.UK); simpledateformat.setTimeZone(TimeZone.getTimeZone("GMT")); }; public cfCookieData(cfSession _parent) { super(); session = _parent; //-- Build up the list of cookies if there are any Cookie[] cList = session.REQ.getCookies(); if (cList != null && cList.length > 0) { for (int x = 0; x < cList.length; x++) super.setData(cList[x].getName(), new cookieWrapper(cList[x], false, false)); } } /** * this function is called by the cfHttpServletResposne to add the cookies to the * outgoing stream. Once written, any further cookies can't be added. */ public void addCookies() { Map hashdata = getHashData(); synchronized (hashdata) { Iterator values = hashdata.values().iterator(); while (values.hasNext()) { cookieWrapper cW = (cookieWrapper) values.next(); if (cW.bOutgoing){ session.RES.addHeader("Set-Cookie", cW.getHeaderValue() ); } } } } public void deleteCookie(String _key) throws cfmRunTimeException { super.deleteData(_key); } public void setDomainCookie(cfSession _Session, String _key) { cookieWrapper cW = (cookieWrapper) super.getData(_key); if (cW != null && cW.bOutgoing) cW.cookie.setDomain(transferTopLevelDomain(_Session, cW.cookie.getDomain())); } /* * clear * * This method clears the cookie structure by setting all of the cookie * value's to an empty string and setting all of them to expire now. */ public void clear() { Map hashdata = getHashData(); synchronized (hashdata) { Iterator values = hashdata.values().iterator(); while (values.hasNext()) { cookieWrapper cW = (cookieWrapper) values.next(); cW.cookie.setValue(""); cW.cookie.setMaxAge(0); cW.bOutgoing = true; } } } /* * deleteData * * This method deletes a cookie by setting its value to an empty string and * setting it to expire now. */ public void deleteData(String _key) throws cfmRunTimeException { cookieWrapper cW = (cookieWrapper) super.getData(_key); if (cW != null) { cW.cookie.setValue(""); cW.cookie.setMaxAge(0); cW.bOutgoing = true; } } public void setData(String _key, cfData _data) { // this method overrides the setData method in cfStructData and // therefore can't throw an exception try { setData(new cfStringData(_key), _data); } catch (cfmRunTimeException exc) { cfEngine.log("ERROR: failed to set data in cookie structure."); } } public void setData(cfData _key, cfData _data) throws cfmRunTimeException { String cookieVal = urlEncoder.encode(_data.getString()); Cookie newCookie = new Cookie(_key.getString().toUpperCase(), cookieVal); newCookie.setPath(session.REQ.getContextPath() + "/"); setData( newCookie, false ); } public void setData(Cookie _cdata, boolean bHttpOnly ) throws cfmRunTimeException { if (session.isFlushed()) { cfCatchData catchData = new cfCatchData(); catchData.setType(cfCatchData.TYPE_TEMPLATE); catchData.setDetail("Unable to create Cookie because the page has been flushed"); catchData.setMessage("Cannot create Cookie"); throw new cfmRunTimeException(catchData); } super.setData(_cdata.getName(), new cookieWrapper(_cdata, true, bHttpOnly)); } public String getTypeString() { return "cookie"; } @SuppressWarnings("deprecation") public cfData getData(String _key) { cookieWrapper cW = (cookieWrapper) super.getData(_key); return (cW == null) ? null : new cfStringData(java.net.URLDecoder.decode(cW.cookie.getValue())); } protected cfData getForDump(String _key) { return getData(_key); } // used by Script Protect functionality public void overrideData(String _key, String _data) { cookieWrapper cW = (cookieWrapper) super.getData(_key); if (cW != null) { cW.cookie.setValue(_data); } } private static String transferTopLevelDomain(cfSession _Session, String _domain) { if (_domain == null) _domain = _Session.REQ.getServerName().toLowerCase(); int dotCount = 3; if (_domain.indexOf(".com") != -1 || _domain.indexOf(".net") != -1 || _domain.indexOf(".org") != -1) dotCount = 2; try { int c1 = _domain.length(); while (dotCount > 0) { c1 = _domain.lastIndexOf(".", c1 - 1); --dotCount; } _domain = _domain.substring(c1); } catch (Exception E) { } return _domain; } // ------------------------------------------------------------------ // --[ Inner class to wrap up the Cookie object in a cfData class cookieWrapper extends cfData implements java.io.Serializable { private static final long serialVersionUID = 1L; Cookie cookie; boolean bOutgoing = false; boolean bHttpOnly = false; public cookieWrapper(Cookie _cookie, boolean _bOutgoing, boolean _bHttpOnly ) { cookie = _cookie; bOutgoing = _bOutgoing; bHttpOnly = _bHttpOnly; } public String getHeaderValue(){ StringBuilder sb = new StringBuilder( 64 ); sb.append( cookie.getName() ); sb.append( "=" ); sb.append( cookie.getValue() ); if ( cookie.getMaxAge() >= 0 ){ if ( cookie.getMaxAge() == 0 ){ sb.append( "; expires=Thu, 01 Jan 1970 00:00:01 GMT" ); }else{ sb.append( "; expires=" + simpledateformat.format( System.currentTimeMillis() + (long)((long)cookie.getMaxAge() * 1000l) ) + " GMT" ); } } if ( cookie.getDomain() != null ) sb.append( "; domain=" + cookie.getDomain() ); if ( cookie.getPath() != null ) sb.append( "; path=" + cookie.getPath() ); if ( cookie.getSecure() ) sb.append( "; secure" ); if ( bHttpOnly ) sb.append( "; HttpOnly" ); return sb.toString(); } } }