/*
* 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://openbd.org/
*/
package com.naryx.tagfusion.cfm.engine;
/**
* Class represents the URL scope.
*/
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import com.nary.util.FastMap;
import com.nary.util.SequencedHashMap;
import com.naryx.tagfusion.util.RequestUtil;
public class cfUrlData extends cfStructData implements Serializable {
static final long serialVersionUID = 1;
protected String encoding;
public cfUrlData() {
super(new SequencedHashMap( cfEngine.isFormUrlCaseMaintained() ? FastMap.CASE_SENSITIVE :FastMap.CASE_INSENSITIVE ) );
}
public cfUrlData(cfSession _session) {
super(new SequencedHashMap( cfEngine.isFormUrlCaseMaintained() ? FastMap.CASE_SENSITIVE :FastMap.CASE_INSENSITIVE ));
try {
init(_session);
} catch (UnsupportedEncodingException e) {
cfEngine.log(e.getMessage()); // what should we do here?
}
}
// create a shallow copy
protected Map cloneHashdata() {
return new SequencedHashMap(getHashData(), cfEngine.isFormUrlCaseMaintained() ? FastMap.CASE_SENSITIVE :FastMap.CASE_INSENSITIVE );
}
public boolean isCaseSensitive() {
return false;
}
public void overrideData(String key, cfStringData value) {
super.setData(key, value);
}
public void setData(String key, cfData value) {
// -- This method is overriden to look for the __cfform__xxx variables from a <CFFORM>/<CFTREE> tag
if (key.startsWith("__cfform__")) {
String formField = key.substring(10);
String formData = "";
try {
formData = value.getString();
} catch (Exception ignoreException) {
}
if (formData.indexOf(";") == -1) {
super.setData(formField, new cfStringData(formData));
} else {
try {
String path = formData.substring(formData.indexOf("=") + 1, formData.indexOf(";NODE=")).trim();
String node = formData.substring(formData.indexOf(";NODE=") + 6).trim();
cfStructData s = new cfStructData();
s.setData("path", new cfStringData(path));
s.setData("node", new cfStringData(node));
super.setData(formField, s);
} catch (Exception E) {
// -- An error occurred with the parse; so just maintain the original field name
super.setData(formField, new cfStringData(formData));
}
}
}
// Convert FORM/URL keys to uppercase to match CFMX. This is important
// because applications (such as FuseTalk) might use the keys as JavaScript
// variables, which are case-sensitive.
if ( cfEngine.isFormUrlCaseMaintained() )
super.setData(key, value);
else
super.setData(key.toUpperCase(), value);
}
private void init(cfSession _session) throws UnsupportedEncodingException {
String enc = _session.REQ.getCharacterEncoding();
if (enc == null)
enc = cfEngine.getDefaultEncoding();
init(_session, enc);
}
private void init(cfSession _session, String _enc) throws UnsupportedEncodingException {
encoding = _enc;
decodeURIString(_session);
}
public static String getQueryString(cfSession _session) {
/*
* The following code handles this logic:
*
* If this is a direct request then just use the query string from the request object.
*
* If this is an include request then use the query string from the "javax.servlet.include.query_string"
* attribute. If it isn't present then use the query string from the request object. This causes a query
* string in an include statement to override the original query string.
*
* If this is a forward request then use the query string from the request object. If it isn't present
* then use the query string from the "javax.servlet.forward.query_string" attribute. This causes a
* query string in a forward statement to override the original query string.
*
* NOTE: This matches the behavior of CF8 and fixes bug #3238. It also backs out the fix for #2768 which wasn't correct.
*
* Other items/areas of interest: - these methods from SE's Request object [getQueryString(),
* addQueryParameters(), removeQueryParameters()] - The last 2 are used by SE's RequestDispatcher
* when forwarding a request so as to leave the original request intact while adding any extra Parameters
* to the request. - See section 2.13.6 of the Servlet 2.2 Specification. In the forwarded request, the new
* parameters have precedence over the old ones. - cfcServlet.doGet()
*/
String qs_include = (String) _session.REQ.getAttribute("javax.servlet.include.query_string");
String qs_request = _session.REQ.getQueryString(); // on Jetty this may be <forwarded params>&<original request params>
String qs_forward = (String) _session.REQ.getAttribute("javax.servlet.forward.query_string");
String qs = null;
String appEngineName = _session.CTX.getServerInfo().toLowerCase();
// Jetty fixup:
if ((appEngineName.startsWith("jetty") || appEngineName.startsWith("google")) && qs_forward != null && qs_request != null) {
/*
* Jetty Notes: request /Bug02840/testForward.cfm?var01=a&var02=b which forwards to index.cfm?var01=a&var02=c qs
* should be just "var01=a&var02=b" _session.REQ.qetQueryString should be just "var01=a&var02=c"
*
* Reality: Jetty 6.0.0 ----------- qs=var01=a&var02=c&var01=a&var02=b _session.REQ.getQueryString()=var01=a&var02=c&var01=a&var02=b
*
* Jetty 6.1.10 ------------ qs=var01=a&var02=b _session.REQ.getQueryString()=var01=a&var02=c&var01=a&var02=b
*
* Summary: Jetty concatenates the 2 query strings for us (even though we wish it would not since Tomcat
* and SE do not). Jetty appends the original request params to the forwarded ones and returns the result
* on calls to _session.REQ.getQueryString() So now that we no longer want them concatenated (after fixing
* bug #3238) we must extract what we need by removing the erroneously appended
* params. (Matt M.)
*/
int pos = qs_request.indexOf('&' + qs_forward);
if (pos > 0)
qs = qs_request.substring(0, pos); // remove unwanted params
// last ditch
if (qs == null)
qs = qs_request;
} else {
qs = qs_include;
if (qs == null)
qs = qs_request;
if (qs == null)
qs = qs_forward;
}
return qs;
}
/**
* This method has been pulled out to allow super classes the ability to call it. When the scopes ('form' and 'url')
* are combined the cfFormData calls this method to decode any variables that may have been passed in to the page via the URI.
*
* @param _session
*/
protected void decodeURIString(cfSession _session) throws UnsupportedEncodingException {
String qs = getQueryString(_session);
FastMap urlParms = new FastMap();
RequestUtil.parseParameters(urlParms, qs, encoding);
Iterator iter = urlParms.keySet().iterator();
while (iter.hasNext()) {
String key = (String) iter.next();
String[] valArray = (String[]) urlParms.get(key);
String value = valArray[0];
// create a comma-separated list for multiple values
if (valArray.length > 1) {
StringBuffer valBuffer = new StringBuffer();
for (int i = 0; i < valArray.length; i++) {
if (valArray[i].length() > 0) {
valBuffer.append(valArray[i]);
valBuffer.append(',');
}
}
if (valBuffer.length() > 0) {
// remove trailing ','
value = valBuffer.toString().substring(0, valBuffer.length() - 1);
}
}
this.setData(key, new cfStringData(value));
}
}
public void setEncoding(cfSession _session, String _encoding) throws UnsupportedEncodingException {
clear();
init(_session, _encoding);
}
public String getEncoding() {
return encoding;
}
}