/*
* Copyright (C) 2000 - 2012 TagServlet 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/
* $Id: variableStore.java 2374 2013-06-10 22:14:24Z alan $
*/
package com.naryx.tagfusion.cfm.engine;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Stack;
import com.nary.security.SecurityCache;
import com.nary.util.FastMap;
import com.naryx.tagfusion.cfm.application.cfJ2EERequestStructData;
import com.naryx.tagfusion.cfm.cookie.cfCookieData;
public class variableStore implements java.io.Serializable {
private static final long serialVersionUID = 1L;
// make sure numerical order matches alphabetical order (for CFDUMP)
public static final int APPLICATION_SCOPE = 0;
// public static final int ARGUMENTS_SCOPE = 1;
public static final int ATTRIBUTES_SCOPE = 2;
public static final int CALLER_SCOPE = 3;
public static final int CGI_SCOPE = 4;
public static final int CLIENT_SCOPE = 5;
public static final int COOKIE_SCOPE = 6;
public static final int FILE_SCOPE = 7;
public static final int FORM_SCOPE = 8;
public static final int REQUEST_SCOPE = 9;
public static final int SERVER_SCOPE = 10;
public static final int SESSION_SCOPE = 11;
public static final int SUPER_SCOPE = 12;
public static final int URL_SCOPE = 13;
public static final int VARIABLES_SCOPE = 14;
public static final int CFTHREAD_SCOPE = 15;
private static final int NUM_SCOPES = 16;
// we still need the names to be public in a few cases
private static final String APPLICATION_SCOPE_NAME = "application";
// public static final String ARGUMENTS_SCOPE_NAME = "arguments";
public static final String ATTRIBUTES_SCOPE_NAME = "attributes";
public static final String CALLER_SCOPE_NAME = "caller";
public static final String CGI_SCOPE_NAME = "cgi";
private static final String CLIENT_SCOPE_NAME = "client";
public static final String COOKIE_SCOPE_NAME = "cookie";
public static final String HTTP_SCOPE_NAME = "http"; // an alias for CGI only
private static final String FILE_SCOPE_NAME = "cffile";
public static final String FORM_SCOPE_NAME = "form";
private static final String REQUEST_SCOPE_NAME = "request";
public static final String SERVER_SCOPE_NAME = "server";
private static final String SESSION_SCOPE_NAME = "session";
public static final String SUPER_SCOPE_NAME = "super";
public static final String URL_SCOPE_NAME = "url";
public static final String VARIABLES_SCOPE_NAME = "variables";
public static final String CFTHREAD_SCOPE_NAME = "cfthread";
// --[ Setup the server and security information, once.
private static cfStructSelectiveReadOnlyData serverData;
private static SecurityCache securityStore;
// mapping from scope name to scope index, for indexing dataStore
protected static final Map<String, Integer> scopeNameMap = new FastMap<String, Integer>(FastMap.CASE_INSENSITIVE);
// mapping from scope index to scope name
private static final String[] scopeNames = new String[NUM_SCOPES];
public static String getScopeName(int i) {
return scopeNames[validateScopeIndex(i)];
}
private static int validateScopeIndex(int i) throws IllegalArgumentException {
if ((i < 0) || (i >= NUM_SCOPES)) {
throw new IllegalArgumentException(Integer.toString(i));
}
return i;
}
static {
try {
scopeNameMap.put(APPLICATION_SCOPE_NAME, new Integer(APPLICATION_SCOPE));
// scopeNameMap.put( ARGUMENTS_SCOPE_NAME, new Integer( ARGUMENTS_SCOPE )
// );
scopeNameMap.put(ATTRIBUTES_SCOPE_NAME, new Integer(ATTRIBUTES_SCOPE));
scopeNameMap.put(CALLER_SCOPE_NAME, new Integer(CALLER_SCOPE));
scopeNameMap.put(CGI_SCOPE_NAME, new Integer(CGI_SCOPE));
scopeNameMap.put(HTTP_SCOPE_NAME, new Integer(CGI_SCOPE));
scopeNameMap.put(CLIENT_SCOPE_NAME, new Integer(CLIENT_SCOPE));
scopeNameMap.put(COOKIE_SCOPE_NAME, new Integer(COOKIE_SCOPE));
scopeNameMap.put(FILE_SCOPE_NAME, new Integer(FILE_SCOPE));
scopeNameMap.put(FORM_SCOPE_NAME, new Integer(FORM_SCOPE));
scopeNameMap.put(REQUEST_SCOPE_NAME, new Integer(REQUEST_SCOPE));
scopeNameMap.put(SERVER_SCOPE_NAME, new Integer(SERVER_SCOPE));
scopeNameMap.put(SESSION_SCOPE_NAME, new Integer(SESSION_SCOPE));
scopeNameMap.put(SUPER_SCOPE_NAME, new Integer(SUPER_SCOPE));
scopeNameMap.put(URL_SCOPE_NAME, new Integer(URL_SCOPE));
scopeNameMap.put(VARIABLES_SCOPE_NAME, new Integer(VARIABLES_SCOPE));
scopeNameMap.put(CFTHREAD_SCOPE_NAME, new Integer(CFTHREAD_SCOPE));
scopeNames[APPLICATION_SCOPE] = APPLICATION_SCOPE_NAME;
// scopeNames[ ARGUMENTS_SCOPE ] = ARGUMENTS_SCOPE_NAME;
scopeNames[ATTRIBUTES_SCOPE] = ATTRIBUTES_SCOPE_NAME;
scopeNames[CALLER_SCOPE] = CALLER_SCOPE_NAME;
scopeNames[CGI_SCOPE] = CGI_SCOPE_NAME;
scopeNames[CLIENT_SCOPE] = CLIENT_SCOPE_NAME;
scopeNames[COOKIE_SCOPE] = COOKIE_SCOPE_NAME;
scopeNames[FILE_SCOPE] = FILE_SCOPE_NAME;
scopeNames[FORM_SCOPE] = FORM_SCOPE_NAME;
scopeNames[REQUEST_SCOPE] = REQUEST_SCOPE_NAME;
scopeNames[SERVER_SCOPE] = SERVER_SCOPE_NAME;
scopeNames[SESSION_SCOPE] = SESSION_SCOPE_NAME;
scopeNames[SUPER_SCOPE] = SUPER_SCOPE_NAME;
scopeNames[URL_SCOPE] = URL_SCOPE_NAME;
scopeNames[VARIABLES_SCOPE] = VARIABLES_SCOPE_NAME;
scopeNames[CFTHREAD_SCOPE] = CFTHREAD_SCOPE_NAME;
Map<String, cfData> serverReadOnlyData = new FastMap<String, cfData>(FastMap.CASE_INSENSITIVE);
serverReadOnlyData.put("bluedragon", cfStringData.EMPTY_STRING);
serverReadOnlyData.put("coldfusion", cfStringData.EMPTY_STRING);
serverReadOnlyData.put("os", cfStringData.EMPTY_STRING);
serverData = new cfStructSelectiveReadOnlyData(serverReadOnlyData);
// Set the server.bluedragon values
cfStructReadOnlyData bluedragon = new cfStructReadOnlyData();
bluedragon.setPrivateData("edition", new cfNumberData(8) ); // EDITION_J2EE
bluedragon.setPrivateData("builddate", new cfStringData(cfEngine.BUILD_ISSUE));
bluedragon.setPrivateData("level", new cfStringData("GPL"));
bluedragon.setPrivateData("state", new cfStringData( cfEngine.PRODUCT_STATE ));
bluedragon.setPrivateData("releasedate", new cfStringData( cfEngine.PRODUCT_RELEASEDATE ) );
bluedragon.setPrivateData("version", new cfStringData(cfEngine.PRODUCT_VERSION));
serverData.setPrivateData("bluedragon", bluedragon);
// Build the supportedlocales value
StringBuilder str = new StringBuilder();
Locale[] locales = Locale.getAvailableLocales();
for (int i = 0; i < locales.length; i++) {
String displayName = locales[i].getDisplayName(Locale.US);
if ((displayName != null) && (displayName.indexOf(",") == -1)) {
String country = locales[i].getCountry();
if ((country == null) || (country.length() == 0)) {
// skip language-only
continue;
}
str.append(displayName);
str.append(", ");
}
}
// [- add the Cf5.0 Strings
str.append("Dutch (Belgian),French (Canadian),Norwegian (Bokmal),Dutch (Standard),French (Standard),Norwegian (nynorsk),English (Australian),French (Swiss),Portuguese (Brazilian),English (Canadian),German (Austrian),Portuguese (Standard),English (New Zealand),German (Standard),Spanish (Mexican),English (UK),German (Swiss),Spanish (Modern),English (US),Italian (Standard),Spanish (Standard),French (Belgian),Italian (Swiss),Swedish");
for (int i = 0; i < locales.length; i++) {
str.append(", ");
str.append(locales[i].getLanguage());
if (locales[i].getCountry().length() > 0) {
str.append("_");
str.append(locales[i].getCountry());
}
}
// Set the server.coldfusion values
try {
Map<String, cfData> coldfusionReadOnlyData = new FastMap<String, cfData>(FastMap.CASE_INSENSITIVE);
coldfusionReadOnlyData.put("supportedlocales", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("productlevel", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("productname", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("productversion", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("appserver", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("installkit", cfStringData.EMPTY_STRING);
coldfusionReadOnlyData.put("rootdir", cfStringData.EMPTY_STRING);
cfStructSelectiveReadOnlyData coldfusion = new cfStructSelectiveReadOnlyData(coldfusionReadOnlyData);
coldfusion.setPrivateData("supportedlocales", new cfStringData(str.toString()));
coldfusion.setPrivateData("productlevel", new cfStringData("GPL"));
coldfusion.setPrivateData("productname", new cfStringData(cfEngine.PRODUCT_NAME));
coldfusion.setPrivateData("productversion", new cfStringData(cfEngine.PRODUCT_VERSION.replace('.', ',')));
coldfusion.setPrivateData("appserver", new cfStringData(cfEngine.thisServletContext.getServerInfo()));
coldfusion.setPrivateData("installkit", cfStringData.EMPTY_STRING);
coldfusion.setPrivateData("rootdir", new cfStringData(cfEngine.thisServletContext.getRealPath("/")));
serverData.setPrivateData("coldfusion", coldfusion);
} catch (Throwable t) {
cfEngine.log("-] ERROR: caught exception while setting the server.coldfusion values - " + t.toString());
}
// Set the server.os values
try {
Map<String, cfData> osReadOnlyData = new FastMap<String, cfData>(FastMap.CASE_INSENSITIVE);
osReadOnlyData.put("name", cfStringData.EMPTY_STRING);
osReadOnlyData.put("version", cfStringData.EMPTY_STRING);
osReadOnlyData.put("arch", cfStringData.EMPTY_STRING);
osReadOnlyData.put("buildnumber", cfStringData.EMPTY_STRING);
osReadOnlyData.put("additionalinformation", cfStringData.EMPTY_STRING);
cfStructSelectiveReadOnlyData os = new cfStructSelectiveReadOnlyData(osReadOnlyData);
os.setPrivateData("name", new cfStringData(System.getProperty("os.name")));
os.setPrivateData("version", new cfStringData(System.getProperty("os.version")));
os.setPrivateData("arch", new cfStringData(System.getProperty("os.arch")));
os.setPrivateData("additionalinformation", new cfStringData(System.getProperty("java.vendor") + " " + System.getProperty("java.version")));
serverData.setPrivateData("os", os);
} catch (Throwable t) {
cfEngine.log("ERROR: caught exception while setting the server.os values - " + t.toString());
}
Properties securityScopeProps = new Properties();
securityScopeProps.put(com.nary.security.SecurityCache.STORAGE_TYPE_KEY, "file");
securityScopeProps.put(com.nary.security.SecurityCache.STORAGE_LOCATION_KEY, cfEngine.thisPlatform.getFileIO().getWorkingDirectory().getAbsolutePath() + java.io.File.separatorChar + "cfloginuser" + java.io.File.separatorChar + com.nary.security.SecurityCache.STORAGE_FILENAME);
securityStore = new SecurityCache(1, securityScopeProps);
} catch (Throwable t) {
cfEngine.log("ERROR: caught exception in variableStore static initializer - " + t.toString());
com.nary.Debug.printStackTrace(t);
}
}
protected cfStructData[] dataStore;
protected Stack<cfQueryResultData> queryStack;
public variableStore() {
dataStore = new cfStructData[NUM_SCOPES];
dataStore[VARIABLES_SCOPE] = new cfStructData();
}
public Map<String, cfStructData> getDataStore() {
Map<String, cfStructData> dataStoreMap = new FastMap<String, cfStructData>();
for (int i = 0; i < NUM_SCOPES; i++) {
if (dataStore[i] != null)
dataStoreMap.put(getScopeName(i), dataStore[i]);
}
return dataStoreMap;
}
public variableStore(cfSession _session) {
this();
// --[ Setup the input data
if (cfEngine.isFormUrlScopeCombined()) { // this is the old way - combined Form/URL scope
cfFormData FD = new cfFormData(_session, true);
setQualifiedData(FORM_SCOPE, FD);
setQualifiedData(URL_SCOPE, FD);
} else { // this is the new way - separate Form and URL scopes
setQualifiedData(FORM_SCOPE, new cfFormData(_session));
setQualifiedData(URL_SCOPE, new cfUrlData(_session));
}
// --[ Setup the CGI data
setQualifiedData(CGI_SCOPE, new cfCGIData(_session));
// --[ Setup the CFFILE data
setQualifiedData(FILE_SCOPE, new cfStructData());
// --[ Setup the CFTHREAD data
setQualifiedData(CFTHREAD_SCOPE, new cfStructData());
// --[ Setup the Cookie information
setQualifiedData(COOKIE_SCOPE, new cfCookieData(_session));
// --[ Setup the Server information
setQualifiedData(SERVER_SCOPE, serverData);
// --[ Setup the request scope
cfStructData request = new cfJ2EERequestStructData(_session);
setQualifiedData(REQUEST_SCOPE, request);
// --[ add disabled scopes
setQualifiedData(SESSION_SCOPE, disabledSessionScope );
setQualifiedData(CLIENT_SCOPE, disabledClientScope );
// --[ Don't need the query stack just yet
queryStack = null;
}
private static cfStructData disabledSessionScope = new cfDisabledStructData(SESSION_SCOPE_NAME);
private static cfStructData disabledClientScope = new cfDisabledStructData(CLIENT_SCOPE_NAME);
/**
* ATTENTION! Calls to setQualifiedData(), getQualifiedData(), and
* deleteQualifiedData() must always be made using the constants defined at
* the top of this class as keys.
*/
public void setQualifiedData(int _key, cfStructData _cfData) {
dataStore[validateScopeIndex(_key)] = _cfData;
}
public cfStructData getQualifiedData(int _key) {
return dataStore[validateScopeIndex(_key)];
}
public cfStructData deleteQualifiedData(int _key) {
cfStructData temp = dataStore[validateScopeIndex(_key)];
dataStore[_key] = null;
return temp;
}
public cfData getData(String _key) {
return getData(_key, true, true);
}
/**
* WARNING! The performance of this method is critical to overall system
* performance. Do not make any changes to this method without doing
* before-and-after timing measurements to make sure you have not decreased
* performance.
*/
public cfData getData(String _key, boolean _doQuerySearch, boolean _doVarSearch) {
if (_key == null)
return null;
cfData tData = null;
// --[ Search the first Query Object
if (_doQuerySearch && (queryStack != null) && !queryStack.empty()) {
tData = peekQuery().getData(_key);
if (tData != null)
return tData;
}
// --[ The data may have been fully addressed, so lets check it first
Integer scopeIndex = scopeNameMap.get(_key);
if (scopeIndex != null) {
tData = dataStore[scopeIndex.intValue()];
if (tData != null)
return tData;
}
// --[ If its get this far, we need to go searching through the scopes to
// --[ find the variable: variables, cgi, cffile, url, form, cookie, client
// --[ Search the [variables] scope
if (_doVarSearch) {
tData = dataStore[VARIABLES_SCOPE].getData(_key);
if (tData != null)
return tData;
}
// --[ Search the [thread] scope
tData = dataStore[CFTHREAD_SCOPE].getData(_key);
if (tData != null)
return tData;
// --[ Search the [cgi] scope
tData = dataStore[CGI_SCOPE].getData(_key);
// checks if the value is 'really' there
if (tData != null && tData != cfStringData.EMPTY_STRING)
return tData;
// --[ Search the [cffile] scope if there
tData = dataStore[FILE_SCOPE].getData(_key);
if (tData != null)
return tData;
// --[ Search the [url] scope if there
tData = dataStore[URL_SCOPE].getData(_key);
if (tData != null)
return tData;
// --[ Search the [form] scope if there
tData = dataStore[FORM_SCOPE].getData(_key);
if (tData != null)
return tData;
// --[ Search the [cookie] scope if there
tData = dataStore[COOKIE_SCOPE].getData(_key);
if (tData != null)
return tData;
// --[ Search the [client] scope if there
cfData scope = dataStore[CLIENT_SCOPE];
if (scope != null) {
tData = scope.getData(_key);
if (tData != null)
return tData;
}
// --[ If its got down as far as here, then it hasn't been found
return null;
}
public void deleteData(String _key) throws cfmRunTimeException {
String key, subkey;
int c1 = getLastIndex(_key);
if (c1 == -1) {
subkey = _key;
key = VARIABLES_SCOPE_NAME;
} else {
subkey = _key.substring(c1 + 1);
key = _key.substring(0, c1);
}
cfData tData = getData(key);
if (tData != null)
tData.deleteData(subkey);
}
public void pushQuery(cfQueryResultData _query) {
if (queryStack == null)
queryStack = new Stack<cfQueryResultData>();
queryStack.push(_query);
}
public cfQueryResultData popQuery() {
if (queryStack == null || queryStack.empty())
return null;
return queryStack.pop();
}
public cfQueryResultData peekQuery() {
if (queryStack == null || queryStack.empty())
return null;
return queryStack.peek();
}
public Stack<cfQueryResultData> removeQueryStack() {
Stack<cfQueryResultData> temp = queryStack;
queryStack = null;
return temp;
}
public Stack<cfQueryResultData> getQueryStack() {
return queryStack;
}
public void setQueryStack(Stack<cfQueryResultData> _qs) {
queryStack = _qs;
}
private static int getLastIndex(String key) {
if (key.charAt(key.length() - 1) == ']')
return key.lastIndexOf("[");
else
return key.lastIndexOf(".");
}
public static SecurityCache getSecurityStore() {
return securityStore;
}
public static void shutdown() {
securityStore.shutdown();
}
}