You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by Jacques Le Roux <ja...@les7arts.com> on 2009/02/08 17:21:10 UTC
Re: svn commit: r742013 - in /ofbiz/trunk/framework: base/config/ base/src/org/ofbiz/base/util/template/ entity/src/org/ofbiz/entity/ webapp/src/org/ofbiz/webapp/control/ widget/src/org/ofbiz/widget/screen/
This causes an issue when rendering a javascript variable build in groovy
Commenting out lines 71-73 of HtmlWidget.java solves the problem.
Please see Giant Widget with variant explosion in ecommerce when viewing details for an example.
I would suggest
if (object instanceof String) {
if (!((String) object).contains("<script language=\"JavaScript\">")) {
return new StringHtmlWrapperForFtl((String) object, this);
}
}
but not sue it's the best way (it works of course)
Jacques
From: <jo...@apache.org>
> Author: jonesde
> Date: Sun Feb 8 07:40:40 2009
> New Revision: 742013
>
> URL: http://svn.apache.org/viewvc?rev=742013&view=rev
> Log:
> Implemented StringModel extension and BeansWrapper extension to load it in order to encode strings for HTML use; this is only done
> throught the HtmlWidget class that is part of the screen widget, so won't interfere with other FTL uses; note that there is other
> experimental code in here for wrapping the GenericValue object for html encoding, but that option wasn't very complete so went
> this way instead; this option behaves better and is more transparent than that escape x as x?html option for FTL files; there are
> also a few cleanups of typos and things in here; note that this means we have a different Configuration object and so a different
> template cache, and so we have different cache settings and such; after applying this I found a few places that encoded things
> they shouldn't but for the most part it is pretty good; will be committing some changes in applications in a bit to resolve a
> couple of these issues in ecommerce; all should watch out for funny things showing up as
> HTML text instead of being interpreted by the browser as HTML, meaning it was encoded; in extreme cases just comment out lines
> 71-73 of HtmlWidget.java to turn off this encoding
>
> Added:
> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java (with props)
> Modified:
> ofbiz/trunk/framework/base/config/cache.properties
> ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java
> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java
> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java
> ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java
> ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java
>
> Modified: ofbiz/trunk/framework/base/config/cache.properties
> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/config/cache.properties?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/base/config/cache.properties (original)
> +++ ofbiz/trunk/framework/base/config/cache.properties Sun Feb 8 07:40:40 2009
> @@ -91,8 +91,9 @@
> widget.tree.locationResource.expireTime=10000
> widget.tree.webappResource.expireTime=10000
>
> -template.ftl.general.expireTime=10000
> template.ftl.location.expireTime=10000
> +template.ftl.general.expireTime=10000
> +widget.screen.template.ftl.general.expireTime=10000
>
> ModelDataFile.expireTime=10000
>
>
> Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java (original)
> +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java Sun Feb 8 07:40:40 2009
> @@ -62,7 +62,6 @@
> import freemarker.template.TemplateException;
> import freemarker.template.TemplateModel;
> import freemarker.template.TemplateModelException;
> -//import com.clarkware.profiler.Profiler;
>
> /** FreeMarkerWorker - Freemarker Template Engine Utilities.
> *
> @@ -73,17 +72,19 @@
>
> // use soft references for this so that things from Content records don't kill all of our memory, or maybe not for performance
> reasons... hmmm, leave to config file...
> public static UtilCache<String, Template> cachedTemplates = new UtilCache<String, Template>("template.ftl.general", 0, 0,
> false);
> - protected static Configuration defaultOfbizConfig = new Configuration();
> + protected static BeansWrapper defaultOfbizWrapper = BeansWrapper.getDefaultInstance();
> + protected static Configuration defaultOfbizConfig = makeConfiguration(defaultOfbizWrapper);
>
> - static {
> - BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
> - defaultOfbizConfig.setObjectWrapper(wrapper);
> - defaultOfbizConfig.setSharedVariable("Static", wrapper.getStaticModels());
> - defaultOfbizConfig.setLocalizedLookup(false);
> - defaultOfbizConfig.setTemplateLoader(new FlexibleTemplateLoader());
> + public static Configuration makeConfiguration(BeansWrapper wrapper) {
> + Configuration newConfig = new Configuration();
> +
> + newConfig.setObjectWrapper(wrapper);
> + newConfig.setSharedVariable("Static", wrapper.getStaticModels());
> + newConfig.setLocalizedLookup(false);
> + newConfig.setTemplateLoader(new FlexibleTemplateLoader());
> try {
> - defaultOfbizConfig.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss.SSS");
> - defaultOfbizConfig.setSetting("number_format", "0.##########");
> + newConfig.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss.SSS");
> + newConfig.setSetting("number_format", "0.##########");
> } catch (TemplateException e) {
> Debug.logError("Unable to set date/time and number formats in FreeMarker: " + e, module);
> }
> @@ -103,23 +104,25 @@
> if (props == null || props.isEmpty()) {
> Debug.logError("Unable to locate properties file " + propertyURL, module);
> } else {
> - loadTransforms(loader, props);
> + loadTransforms(loader, props, newConfig);
> }
> }
> +
> + return newConfig;
> }
>
> /**
> * Protected helper method.
> */
> - protected static void loadTransforms(ClassLoader loader, Properties props) {
> + protected static void loadTransforms(ClassLoader loader, Properties props, Configuration config) {
> for (Iterator<Object> i = props.keySet().iterator(); i.hasNext();) {
> - String key = (String)i.next();
> + String key = (String) i.next();
> String className = props.getProperty(key);
> if (Debug.verboseOn()) {
> Debug.logVerbose("Adding FTL Transform " + key + " with class " + className, module);
> }
> try {
> - defaultOfbizConfig.setSharedVariable(key, loader.loadClass(className).newInstance());
> + config.setSharedVariable(key, loader.loadClass(className).newInstance());
> } catch (Exception e) {
> Debug.logError(e, "Could not pre-initialize dynamically loaded class: " + className + ": " + e, module);
> }
> @@ -195,7 +198,7 @@
> // FIXME: the casting from Appendable to Writer is a temporary fix that could cause a
> // run time error if in the future we will pass a different class to the method
> // (such as a StringBuffer).
> - Environment env = template.createProcessingEnvironment(context, (Writer)outWriter);
> + Environment env = template.createProcessingEnvironment(context, (Writer) outWriter);
> applyUserSettings(env, context);
> env.process();
> return env;
> @@ -261,16 +264,20 @@
> * @param templateLocation Location of the template - file path or URL
> */
> public static Template getTemplate(String templateLocation) throws TemplateException, IOException {
> - Template template = (Template) cachedTemplates.get(templateLocation);
> + return getTemplate(templateLocation, cachedTemplates, defaultOfbizConfig);
> + }
> +
> + public static Template getTemplate(String templateLocation, UtilCache<String, Template> cache, Configuration config) throws
> TemplateException, IOException {
> + Template template = (Template) cache.get(templateLocation);
> if (template == null) {
> - synchronized (cachedTemplates) {
> - template = (Template) cachedTemplates.get(templateLocation);
> + synchronized (cache) {
> + template = (Template) cache.get(templateLocation);
> if (template == null) {
> // only make the reader if we need it, and then close it right after!
> Reader templateReader = makeReader(templateLocation);
> - template = new Template(templateLocation, templateReader, defaultOfbizConfig);
> + template = new Template(templateLocation, templateReader, config);
> templateReader.close();
> - cachedTemplates.put(templateLocation, template);
> + cache.put(templateLocation, template);
> }
> }
> }
>
> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java (original)
> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java Sun Feb 8 07:40:40 2009
> @@ -142,21 +142,21 @@
> /** Creates new GenericEntity */
> protected void init(ModelEntity modelEntity) {
> if (modelEntity == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
> }
> this.modelEntity = modelEntity;
> this.entityName = modelEntity.getEntityName();
>
> // check some things
> if (this.entityName == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
> parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
> parameter");
> }
> }
>
> /** Creates new GenericEntity from existing Map */
> protected void init(ModelEntity modelEntity, Map<String, ? extends Object> fields) {
> if (modelEntity == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
> }
> this.modelEntity = modelEntity;
> this.entityName = modelEntity.getEntityName();
> @@ -164,14 +164,14 @@
>
> // check some things
> if (this.entityName == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
> parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
> parameter");
> }
> }
>
> /** Creates new GenericEntity from existing Map */
> protected void init(ModelEntity modelEntity, Object singlePkValue) {
> if (modelEntity == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
> }
> if (modelEntity.getPksSize() != 1) {
> throw new IllegalArgumentException("Cannot create a GenericEntity with more than one primary key field");
> @@ -182,25 +182,22 @@
>
> // check some things
> if (this.entityName == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
> parameter");
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
> parameter");
> }
> }
>
> /** Copy Constructor: Creates new GenericEntity from existing GenericEntity */
> protected void init(GenericEntity value) {
> - if (value.modelEntity == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity from another GenericEntity with a null modelEntity
> in the value parameter");
> + // check some things
> + if (value.entityName == null) {
> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
> parameter");
> }
> - this.entityName = value.modelEntity.getEntityName();
> + this.entityName = value.getEntityName();
> + // NOTE: could call getModelEntity to insure we have a value, just in case the value passed in has been serialized, but
> might as well leave it null to keep the object light if it isn't there
> this.modelEntity = value.modelEntity;
> if (value.fields != null) this.fields.putAll(value.fields);
> this.delegatorName = value.delegatorName;
> this.internalDelegator = value.internalDelegator;
> -
> - // check some things
> - if (this.entityName == null) {
> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
> parameter");
> - }
> }
>
> public void reset() {
>
> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java (original)
> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java Sun Feb 8 07:40:40 2009
> @@ -24,8 +24,8 @@
> import java.util.List;
> import java.util.Map;
>
> -import javolution.lang.Reusable;
> import javolution.context.ObjectFactory;
> +import javolution.lang.Reusable;
> import javolution.util.FastMap;
>
> import org.ofbiz.base.util.Debug;
> @@ -33,7 +33,6 @@
> import org.ofbiz.base.util.UtilValidate;
> import org.ofbiz.entity.condition.EntityCondition;
> import org.ofbiz.entity.condition.EntityFieldMap;
> -import org.ofbiz.entity.condition.EntityOperator;
> import org.ofbiz.entity.model.ModelEntity;
> import org.ofbiz.entity.model.ModelKeyMap;
> import org.ofbiz.entity.model.ModelRelation;
> @@ -44,6 +43,7 @@
> * Generic Entity Value Object - Handles persistence for any defined entity.
> *
> */
> +@SuppressWarnings("serial")
> public class GenericValue extends GenericEntity implements Reusable {
>
> public static final GenericValue NULL_VALUE = new NullGenericValue();
>
> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java?rev=742013&view=auto
> ==============================================================================
> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java (added)
> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java Sun Feb 8 07:40:40 2009
> @@ -0,0 +1,105 @@
> +/*******************************************************************************
> + * Licensed to the Apache Software Foundation (ASF) under one
> + * or more contributor license agreements. See the NOTICE file
> + * distributed with this work for additional information
> + * regarding copyright ownership. The ASF licenses this file
> + * to you under the Apache License, Version 2.0 (the
> + * "License"); you may not use this file except in compliance
> + * with the License. You may obtain a copy of the License at
> + *
> + * http://www.apache.org/licenses/LICENSE-2.0
> + *
> + * Unless required by applicable law or agreed to in writing,
> + * software distributed under the License is distributed on an
> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + * KIND, either express or implied. See the License for the
> + * specific language governing permissions and limitations
> + * under the License.
> + *******************************************************************************/
> +
> +package org.ofbiz.entity;
> +
> +
> +import javolution.context.ObjectFactory;
> +
> +import org.ofbiz.base.util.Debug;
> +import org.ofbiz.base.util.StringUtil;
> +
> +import freemarker.ext.beans.BeansWrapper;
> +import freemarker.ext.beans.MapModel;
> +import freemarker.ext.beans.StringModel;
> +import freemarker.template.TemplateModel;
> +import freemarker.template.TemplateModelException;
> +
> +
> +/**
> + * Generic Entity Value Object - Handles persistence for any defined entity.
> + * WARNING: This object is experimental!
> + *
> + */
> +@SuppressWarnings("serial")
> +public class GenericValueHtmlWrapper extends GenericValue {
> + protected static final ObjectFactory<GenericValueHtmlWrapper> genericValueHtmlWrapperFactory = new
> ObjectFactory<GenericValueHtmlWrapper>() {
> + protected GenericValueHtmlWrapper create() {
> + return new GenericValueHtmlWrapper();
> + }
> + };
> +
> + /** Creates new GenericValueHtmlWrapper from existing GenericValue */
> + public static GenericValueHtmlWrapper create(GenericValue value) {
> + GenericValueHtmlWrapper newValue = genericValueHtmlWrapperFactory.object();
> + try {
> + newValue.init(value);
> + } catch (RuntimeException e) {
> + Debug.logError(e, "Error in init for clone of value: " + value, module);
> + throw e;
> + }
> + return newValue;
> + }
> +
> + /* NOTE: this is NOT used because there are certain FTL files that call services and things, and this messes those up, so
> only overriding the Map.get(Object) method to get use of this as a Map
> + * Override the basic get method, which all other get methods call so we only need to do this one (though most important for
> the Map.get(Object) and the getString() methods
> + public Object get(String name) {
> + Object value = super.get(name);
> + if (value instanceof String) {
> + return StringUtil.htmlEncoder.encode((String) value);
> + } else {
> + return value;
> + }
> + }*/
> +
> + public Object get(Object name) {
> + Object value = super.get(name);
> + if (value instanceof String) {
> + return StringUtil.htmlEncoder.encode((String) value);
> + } else {
> + return value;
> + }
> + }
> +
> + // another experimental object, this one specifically for FTL
> + public static class GenericValueHtmlWrapperForFtl extends MapModel {
> + public GenericValueHtmlWrapperForFtl(GenericValue gv, BeansWrapper wrapper) {
> + super(gv, wrapper);
> + }
> +
> + public TemplateModel get(String key) {
> + TemplateModel tm = null;
> + try {
> + tm = super.get(key);
> + } catch (TemplateModelException e) {
> + Debug.logError(e, "Error getting Map with key [" + key + "]: " + e.toString(), module);
> + }
> + if (tm instanceof StringModel) {
> + String original = ((StringModel) tm).getAsString();
> + if (original != null) {
> + String encoded = StringUtil.htmlEncoder.encode(original);
> + if (!original.equals(encoded)) {
> + return new StringModel(encoded, this.wrapper);
> + }
> + }
> + }
> + return tm;
> + }
> + }
> +}
>
> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java
> ------------------------------------------------------------------------------
> svn:eol-style = native
>
> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java
> ------------------------------------------------------------------------------
> svn:keywords = "Date Rev Author URL Id"
>
> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java
> ------------------------------------------------------------------------------
> svn:mime-type = text/plain
>
> Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java (original)
> +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java Sun Feb 8 07:40:40 2009
> @@ -950,7 +950,9 @@
> public boolean trackStats(HttpServletRequest request) {
> if (!"false".equalsIgnoreCase(context.getInitParameter("track-serverhit"))) {
> String uriString = RequestHandler.getRequestUri(request.getPathInfo());
> - return controllerConfig.requestMapMap.get(uriString).trackServerHit;
> + ConfigXMLReader.RequestMap requestMap = controllerConfig.requestMapMap.get(uriString);
> + if (requestMap == null) return false;
> + return requestMap.trackServerHit;
> } else {
> return false;
> }
> @@ -959,7 +961,9 @@
> public boolean trackVisit(HttpServletRequest request) {
> if (!"false".equalsIgnoreCase(context.getInitParameter("track-visit"))) {
> String uriString = RequestHandler.getRequestUri(request.getPathInfo());
> - return controllerConfig.requestMapMap.get(uriString).trackVisit;
> + ConfigXMLReader.RequestMap requestMap = controllerConfig.requestMapMap.get(uriString);
> + if (requestMap == null) return false;
> + return requestMap.trackVisit;
> } else {
> return false;
> }
>
> Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java
> URL:
> http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java?rev=742013&r1=742012&r2=742013&view=diff
> ==============================================================================
> --- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java (original)
> +++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java Sun Feb 8 07:40:40 2009
> @@ -21,7 +21,6 @@
> import java.io.IOException;
> import java.net.MalformedURLException;
> import java.util.ArrayList;
> -import java.util.Iterator;
> import java.util.List;
> import java.util.Map;
>
> @@ -29,9 +28,11 @@
>
> import org.ofbiz.base.util.Debug;
> import org.ofbiz.base.util.GeneralException;
> +import org.ofbiz.base.util.StringUtil;
> import org.ofbiz.base.util.UtilGenerics;
> import org.ofbiz.base.util.UtilValidate;
> import org.ofbiz.base.util.UtilXml;
> +import org.ofbiz.base.util.cache.UtilCache;
> import org.ofbiz.base.util.collections.MapStack;
> import org.ofbiz.base.util.string.FlexibleStringExpander;
> import org.ofbiz.base.util.template.FreeMarkerWorker;
> @@ -39,7 +40,13 @@
> import org.ofbiz.widget.html.HtmlWidgetRenderer;
> import org.w3c.dom.Element;
>
> +import freemarker.ext.beans.BeansWrapper;
> +import freemarker.ext.beans.StringModel;
> +import freemarker.template.Configuration;
> +import freemarker.template.Template;
> import freemarker.template.TemplateException;
> +import freemarker.template.TemplateModel;
> +import freemarker.template.TemplateModelException;
>
> /**
> * Widget Library - Screen model HTML class.
> @@ -47,6 +54,37 @@
> @SuppressWarnings("serial")
> public class HtmlWidget extends ModelScreenWidget {
> public static final String module = HtmlWidget.class.getName();
> +
> + public static UtilCache<String, Template> specialTemplateCache = new UtilCache<String,
> Template>("widget.screen.template.ftl.general", 0, 0, false);
> + protected static BeansWrapper specialBeansWrapper = new ExtendedWrapper();
> + protected static Configuration specialConfig = FreeMarkerWorker.makeConfiguration(specialBeansWrapper);
> +
> + // not sure if this is the best way to get FTL to use my fancy MapModel derivative, but should work at least...
> + public static class ExtendedWrapper extends BeansWrapper {
> + public TemplateModel wrap(Object object) throws TemplateModelException {
> + /* NOTE: don't use this and the StringHtmlWrapperForFtl or things will be double-encoded
> + if (object instanceof GenericValue) {
> + return new GenericValueHtmlWrapperForFtl((GenericValue) object, this);
> + }*/
> + // This StringHtmlWrapperForFtl option seems to be the best option
> + // and handles most things without causing too many problems
> + if (object instanceof String) {
> + return new StringHtmlWrapperForFtl((String) object, this);
> + }
> + return super.wrap(object);
> + }
> + }
> +
> + public static class StringHtmlWrapperForFtl extends StringModel {
> + public StringHtmlWrapperForFtl(String str, BeansWrapper wrapper) {
> + super(str, wrapper);
> + }
> + public String getAsString() {
> + return StringUtil.htmlEncoder.encode(super.getAsString());
> + }
> + }
> +
> + // End Static, begin class section
>
> protected List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>();
>
> @@ -87,6 +125,64 @@
> throw new IllegalArgumentException("Template location is empty");
> }
>
> +
> + /*
> + // =======================================================================
> + // Go through the context and find GenericValue objects and wrap them
> +
> + // NOTE PROBLEM: there are still problems with this as it gets some things
> + // but does not get non-entity data including lots of strings
> + // directly in the context or things prepared or derived right in
> + // the FTL file, like the results of service calls, etc; we could
> + // do something more aggressive to encode and wrap EVERYTHING in
> + // the context, but I've been thinking that even this is too much
> + // overhead and that would be crazy
> +
> + // NOTE ALTERNATIVE1: considering instead to use the FTL features to wrap
> + // everything in an <#escape x as x?html>...</#escape>, but that could
> + // cause problems with ${} expansions that have HTML in them, including:
> + // included screens (using ${screens.render(...)}), content that should
> + // have HTML in it (lots of general, product, category, etc content), etc
> +
> + // NOTE ALTERNATIVE2: kind of like the "#escape X as x?html" option,
> + // implement an FTL *Model class and load it through a ObjectWrapper
> + // FINAL NOTE: after testing all of these alternatives, this one seems
> + // to behave the best, so going with that for now.
> +
> + // isolate the scope so these wrapper objects go away after rendering is done
> + MapStack<String> contextMs;
> + if (!(context instanceof MapStack)) {
> + contextMs = MapStack.create(context);
> + context = contextMs;
> + } else {
> + contextMs = UtilGenerics.cast(context);
> + }
> +
> + contextMs.push();
> + for(Map.Entry<String, Object> mapEntry: contextMs.entrySet()) {
> + Object value = mapEntry.getValue();
> + if (value instanceof GenericValue) {
> + contextMs.put(mapEntry.getKey(), GenericValueHtmlWrapper.create((GenericValue) value));
> + } else if (value instanceof List) {
> + if (((List) value).size() > 0 && ((List) value).get(0) instanceof GenericValue) {
> + List<GenericValue> theList = (List<GenericValue>) value;
> + List<GenericValueHtmlWrapper> newList = FastList.newInstance();
> + for (GenericValue gv: theList) {
> + newList.add(GenericValueHtmlWrapper.create(gv));
> + }
> + contextMs.put(mapEntry.getKey(), newList);
> + }
> + }
> + // TODO and NOTE: should get most stuff, but we could support Maps
> + // and Lists in Maps and such; that's tricky because we have to go
> + // through the entire Map and not just one entry, and we would
> + // have to shallow copy the whole Map too
> +
> + }
> + // this line goes at the end of the method, but moved up here to be part of the big comment about this
> + contextMs.pop();
> + */
> +
> if (location.endsWith(".ftl")) {
> try {
> Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
> @@ -94,7 +190,11 @@
> if (insertWidgetBoundaryComments) {
> writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
> }
> - FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
> +
> + //FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
> + Template template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
> + FreeMarkerWorker.renderTemplate(template, context, writer);
> +
> if (insertWidgetBoundaryComments) {
> writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
> }
>
>
Re: svn commit: r742013 - in /ofbiz/trunk/framework: base/config/ base/src/org/ofbiz/base/util/template/ entity/src/org/ofbiz/entity/ webapp/src/org/ofbiz/webapp/control/ widget/src/org/ofbiz/widget/screen/
Posted by Jacques Le Roux <ja...@les7arts.com>.
I thought that I should have takeen into account case unsensitive (but anyway, as I said maybe there is a better/more general
solution)
Jacques
From: "David E Jones" <da...@hotwaxmedia.com>
>
> I'm looking into this now.
>
> -David
>
>
> On Feb 8, 2009, at 9:21 AM, Jacques Le Roux wrote:
>
>> This causes an issue when rendering a javascript variable build in groovy
>> Commenting out lines 71-73 of HtmlWidget.java solves the problem.
>> Please see Giant Widget with variant explosion in ecommerce when viewing details for an example.
>> I would suggest
>> if (object instanceof String) {
>> if (!((String) object).contains("<script language= \"JavaScript\">")) {
>> return new StringHtmlWrapperForFtl((String) object, this);
>> }
>> }
>>
>>
>> but not sue it's the best way (it works of course)
>>
>> Jacques
>>
>> From: <jo...@apache.org>
>>> Author: jonesde
>>> Date: Sun Feb 8 07:40:40 2009
>>> New Revision: 742013
>>>
>>> URL: http://svn.apache.org/viewvc?rev=742013&view=rev
>>> Log:
>>> Implemented StringModel extension and BeansWrapper extension to load it in order to encode strings for HTML use; this is only
>>> done throught the HtmlWidget class that is part of the screen widget, so won't interfere with other FTL uses; note that there
>>> is other experimental code in here for wrapping the GenericValue object for html encoding, but that option wasn't very
>>> complete so went this way instead; this option behaves better and is more transparent than that escape x as x?html option for
>>> FTL files; there are also a few cleanups of typos and things in here; note that this means we have a different Configuration
>>> object and so a different template cache, and so we have different cache settings and such; after applying this I found a few
>>> places that encoded things they shouldn't but for the most part it is pretty good; will be committing some changes in
>>> applications in a bit to resolve a couple of these issues in ecommerce; all should watch out for funny things showing up as
>>> HTML text instead of being interpreted by the browser as HTML, meaning it was encoded; in extreme cases just comment out lines
>>> 71-73 of HtmlWidget.java to turn off this encoding
>>>
>>> Added:
>>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java (with props)
>>> Modified:
>>> ofbiz/trunk/framework/base/config/cache.properties
>>> ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ FreeMarkerWorker.java
>>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java
>>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java
>>> ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ RequestHandler.java
>>> ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java
>>>
>>> Modified: ofbiz/trunk/framework/base/config/cache.properties
>>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/config/cache.properties?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/base/config/cache.properties (original)
>>> +++ ofbiz/trunk/framework/base/config/cache.properties Sun Feb 8 07:40:40 2009
>>> @@ -91,8 +91,9 @@
>>> widget.tree.locationResource.expireTime=10000
>>> widget.tree.webappResource.expireTime=10000
>>>
>>> -template.ftl.general.expireTime=10000
>>> template.ftl.location.expireTime=10000
>>> +template.ftl.general.expireTime=10000
>>> +widget.screen.template.ftl.general.expireTime=10000
>>>
>>> ModelDataFile.expireTime=10000
>>>
>>>
>>> Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/ template/FreeMarkerWorker.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ FreeMarkerWorker.java (original)
>>> +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/ FreeMarkerWorker.java Sun Feb 8 07:40:40 2009
>>> @@ -62,7 +62,6 @@
>>> import freemarker.template.TemplateException;
>>> import freemarker.template.TemplateModel;
>>> import freemarker.template.TemplateModelException;
>>> -//import com.clarkware.profiler.Profiler;
>>>
>>> /** FreeMarkerWorker - Freemarker Template Engine Utilities.
>>> *
>>> @@ -73,17 +72,19 @@
>>>
>>> // use soft references for this so that things from Content records don't kill all of our memory, or maybe not for
>>> performance reasons... hmmm, leave to config file...
>>> public static UtilCache<String, Template> cachedTemplates = new UtilCache<String, Template>("template.ftl.general", 0, 0,
>>> false);
>>> - protected static Configuration defaultOfbizConfig = new Configuration();
>>> + protected static BeansWrapper defaultOfbizWrapper = BeansWrapper.getDefaultInstance();
>>> + protected static Configuration defaultOfbizConfig = makeConfiguration(defaultOfbizWrapper);
>>>
>>> - static {
>>> - BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
>>> - defaultOfbizConfig.setObjectWrapper(wrapper);
>>> - defaultOfbizConfig.setSharedVariable("Static", wrapper.getStaticModels());
>>> - defaultOfbizConfig.setLocalizedLookup(false);
>>> - defaultOfbizConfig.setTemplateLoader(new FlexibleTemplateLoader());
>>> + public static Configuration makeConfiguration(BeansWrapper wrapper) {
>>> + Configuration newConfig = new Configuration();
>>> +
>>> + newConfig.setObjectWrapper(wrapper);
>>> + newConfig.setSharedVariable("Static", wrapper.getStaticModels());
>>> + newConfig.setLocalizedLookup(false);
>>> + newConfig.setTemplateLoader(new FlexibleTemplateLoader());
>>> try {
>>> - defaultOfbizConfig.setSetting("datetime_format", "yyyy- MM-dd HH:mm:ss.SSS");
>>> - defaultOfbizConfig.setSetting("number_format", "0.##########");
>>> + newConfig.setSetting("datetime_format", "yyyy-MM-dd HH:mm:ss.SSS");
>>> + newConfig.setSetting("number_format", "0.##########");
>>> } catch (TemplateException e) {
>>> Debug.logError("Unable to set date/time and number formats in FreeMarker: " + e, module);
>>> }
>>> @@ -103,23 +104,25 @@
>>> if (props == null || props.isEmpty()) {
>>> Debug.logError("Unable to locate properties file " + propertyURL, module);
>>> } else {
>>> - loadTransforms(loader, props);
>>> + loadTransforms(loader, props, newConfig);
>>> }
>>> }
>>> +
>>> + return newConfig;
>>> }
>>>
>>> /**
>>> * Protected helper method.
>>> */
>>> - protected static void loadTransforms(ClassLoader loader, Properties props) {
>>> + protected static void loadTransforms(ClassLoader loader, Properties props, Configuration config) {
>>> for (Iterator<Object> i = props.keySet().iterator(); i.hasNext();) {
>>> - String key = (String)i.next();
>>> + String key = (String) i.next();
>>> String className = props.getProperty(key);
>>> if (Debug.verboseOn()) {
>>> Debug.logVerbose("Adding FTL Transform " + key + " with class " + className, module);
>>> }
>>> try {
>>> - defaultOfbizConfig.setSharedVariable(key, loader.loadClass(className).newInstance());
>>> + config.setSharedVariable(key, loader.loadClass(className).newInstance());
>>> } catch (Exception e) {
>>> Debug.logError(e, "Could not pre-initialize dynamically loaded class: " + className + ": " + e, module);
>>> }
>>> @@ -195,7 +198,7 @@
>>> // FIXME: the casting from Appendable to Writer is a temporary fix that could cause a
>>> // run time error if in the future we will pass a different class to the method
>>> // (such as a StringBuffer).
>>> - Environment env = template.createProcessingEnvironment(context, (Writer)outWriter);
>>> + Environment env = template.createProcessingEnvironment(context, (Writer) outWriter);
>>> applyUserSettings(env, context);
>>> env.process();
>>> return env;
>>> @@ -261,16 +264,20 @@
>>> * @param templateLocation Location of the template - file path or URL
>>> */
>>> public static Template getTemplate(String templateLocation) throws TemplateException, IOException {
>>> - Template template = (Template) cachedTemplates.get(templateLocation);
>>> + return getTemplate(templateLocation, cachedTemplates, defaultOfbizConfig);
>>> + }
>>> +
>>> + public static Template getTemplate(String templateLocation, UtilCache<String, Template> cache, Configuration config)
>>> throws TemplateException, IOException {
>>> + Template template = (Template) cache.get(templateLocation);
>>> if (template == null) {
>>> - synchronized (cachedTemplates) {
>>> - template = (Template) cachedTemplates.get(templateLocation);
>>> + synchronized (cache) {
>>> + template = (Template) cache.get(templateLocation);
>>> if (template == null) {
>>> // only make the reader if we need it, and then close it right after!
>>> Reader templateReader = makeReader(templateLocation);
>>> - template = new Template(templateLocation, templateReader, defaultOfbizConfig);
>>> + template = new Template(templateLocation, templateReader, config);
>>> templateReader.close();
>>> - cachedTemplates.put(templateLocation, template);
>>> + cache.put(templateLocation, template);
>>> }
>>> }
>>> }
>>>
>>> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java (original)
>>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericEntity.java Sun Feb 8 07:40:40 2009
>>> @@ -142,21 +142,21 @@
>>> /** Creates new GenericEntity */
>>> protected void init(ModelEntity modelEntity) {
>>> if (modelEntity == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
>>> }
>>> this.modelEntity = modelEntity;
>>> this.entityName = modelEntity.getEntityName();
>>>
>>> // check some things
>>> if (this.entityName == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> }
>>> }
>>>
>>> /** Creates new GenericEntity from existing Map */
>>> protected void init(ModelEntity modelEntity, Map<String, ? extends Object> fields) {
>>> if (modelEntity == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
>>> }
>>> this.modelEntity = modelEntity;
>>> this.entityName = modelEntity.getEntityName();
>>> @@ -164,14 +164,14 @@
>>>
>>> // check some things
>>> if (this.entityName == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> }
>>> }
>>>
>>> /** Creates new GenericEntity from existing Map */
>>> protected void init(ModelEntity modelEntity, Object singlePkValue) {
>>> if (modelEntity == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null modelEntity parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null modelEntity parameter");
>>> }
>>> if (modelEntity.getPksSize() != 1) {
>>> throw new IllegalArgumentException("Cannot create a GenericEntity with more than one primary key field");
>>> @@ -182,25 +182,22 @@
>>>
>>> // check some things
>>> if (this.entityName == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> }
>>> }
>>>
>>> /** Copy Constructor: Creates new GenericEntity from existing GenericEntity */
>>> protected void init(GenericEntity value) {
>>> - if (value.modelEntity == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity from another GenericEntity with a null
>>> modelEntity in the value parameter");
>>> + // check some things
>>> + if (value.entityName == null) {
>>> + throw new IllegalArgumentException("Cannot create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> }
>>> - this.entityName = value.modelEntity.getEntityName();
>>> + this.entityName = value.getEntityName();
>>> + // NOTE: could call getModelEntity to insure we have a value, just in case the value passed in has been serialized,
>>> but might as well leave it null to keep the object light if it isn't there
>>> this.modelEntity = value.modelEntity;
>>> if (value.fields != null) this.fields.putAll(value.fields);
>>> this.delegatorName = value.delegatorName;
>>> this.internalDelegator = value.internalDelegator;
>>> -
>>> - // check some things
>>> - if (this.entityName == null) {
>>> - throw new IllegalArgumentException("Cannont create a GenericEntity with a null entityName in the modelEntity
>>> parameter");
>>> - }
>>> }
>>>
>>> public void reset() {
>>>
>>> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java (original)
>>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValue.java Sun Feb 8 07:40:40 2009
>>> @@ -24,8 +24,8 @@
>>> import java.util.List;
>>> import java.util.Map;
>>>
>>> -import javolution.lang.Reusable;
>>> import javolution.context.ObjectFactory;
>>> +import javolution.lang.Reusable;
>>> import javolution.util.FastMap;
>>>
>>> import org.ofbiz.base.util.Debug;
>>> @@ -33,7 +33,6 @@
>>> import org.ofbiz.base.util.UtilValidate;
>>> import org.ofbiz.entity.condition.EntityCondition;
>>> import org.ofbiz.entity.condition.EntityFieldMap;
>>> -import org.ofbiz.entity.condition.EntityOperator;
>>> import org.ofbiz.entity.model.ModelEntity;
>>> import org.ofbiz.entity.model.ModelKeyMap;
>>> import org.ofbiz.entity.model.ModelRelation;
>>> @@ -44,6 +43,7 @@
>>> * Generic Entity Value Object - Handles persistence for any defined entity.
>>> *
>>> */
>>> +@SuppressWarnings("serial")
>>> public class GenericValue extends GenericEntity implements Reusable {
>>>
>>> public static final GenericValue NULL_VALUE = new NullGenericValue();
>>>
>>> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java?rev=742013&view=auto
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java (added)
>>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java Sun Feb 8 07:40:40 2009
>>> @@ -0,0 +1,105 @@
>>> +/ *******************************************************************************
>>> + * Licensed to the Apache Software Foundation (ASF) under one
>>> + * or more contributor license agreements. See the NOTICE file
>>> + * distributed with this work for additional information
>>> + * regarding copyright ownership. The ASF licenses this file
>>> + * to you under the Apache License, Version 2.0 (the
>>> + * "License"); you may not use this file except in compliance
>>> + * with the License. You may obtain a copy of the License at
>>> + *
>>> + * http://www.apache.org/licenses/LICENSE-2.0
>>> + *
>>> + * Unless required by applicable law or agreed to in writing,
>>> + * software distributed under the License is distributed on an
>>> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>>> + * KIND, either express or implied. See the License for the
>>> + * specific language governing permissions and limitations
>>> + * under the License.
>>> + *******************************************************************************/
>>> +
>>> +package org.ofbiz.entity;
>>> +
>>> +
>>> +import javolution.context.ObjectFactory;
>>> +
>>> +import org.ofbiz.base.util.Debug;
>>> +import org.ofbiz.base.util.StringUtil;
>>> +
>>> +import freemarker.ext.beans.BeansWrapper;
>>> +import freemarker.ext.beans.MapModel;
>>> +import freemarker.ext.beans.StringModel;
>>> +import freemarker.template.TemplateModel;
>>> +import freemarker.template.TemplateModelException;
>>> +
>>> +
>>> +/**
>>> + * Generic Entity Value Object - Handles persistence for any defined entity.
>>> + * WARNING: This object is experimental!
>>> + *
>>> + */
>>> +@SuppressWarnings("serial")
>>> +public class GenericValueHtmlWrapper extends GenericValue {
>>> + protected static final ObjectFactory<GenericValueHtmlWrapper> genericValueHtmlWrapperFactory = new
>>> ObjectFactory<GenericValueHtmlWrapper>() {
>>> + protected GenericValueHtmlWrapper create() {
>>> + return new GenericValueHtmlWrapper();
>>> + }
>>> + };
>>> +
>>> + /** Creates new GenericValueHtmlWrapper from existing GenericValue */
>>> + public static GenericValueHtmlWrapper create(GenericValue value) {
>>> + GenericValueHtmlWrapper newValue = genericValueHtmlWrapperFactory.object();
>>> + try {
>>> + newValue.init(value);
>>> + } catch (RuntimeException e) {
>>> + Debug.logError(e, "Error in init for clone of value: " + value, module);
>>> + throw e;
>>> + }
>>> + return newValue;
>>> + }
>>> +
>>> + /* NOTE: this is NOT used because there are certain FTL files that call services and things, and this messes those up, so
>>> only overriding the Map.get(Object) method to get use of this as a Map
>>> + * Override the basic get method, which all other get methods call so we only need to do this one (though most important
>>> for the Map.get(Object) and the getString() methods
>>> + public Object get(String name) {
>>> + Object value = super.get(name);
>>> + if (value instanceof String) {
>>> + return StringUtil.htmlEncoder.encode((String) value);
>>> + } else {
>>> + return value;
>>> + }
>>> + }*/
>>> +
>>> + public Object get(Object name) {
>>> + Object value = super.get(name);
>>> + if (value instanceof String) {
>>> + return StringUtil.htmlEncoder.encode((String) value);
>>> + } else {
>>> + return value;
>>> + }
>>> + }
>>> +
>>> + // another experimental object, this one specifically for FTL
>>> + public static class GenericValueHtmlWrapperForFtl extends MapModel {
>>> + public GenericValueHtmlWrapperForFtl(GenericValue gv, BeansWrapper wrapper) {
>>> + super(gv, wrapper);
>>> + }
>>> +
>>> + public TemplateModel get(String key) {
>>> + TemplateModel tm = null;
>>> + try {
>>> + tm = super.get(key);
>>> + } catch (TemplateModelException e) {
>>> + Debug.logError(e, "Error getting Map with key [" + key + "]: " + e.toString(), module);
>>> + }
>>> + if (tm instanceof StringModel) {
>>> + String original = ((StringModel) tm).getAsString();
>>> + if (original != null) {
>>> + String encoded = StringUtil.htmlEncoder.encode(original);
>>> + if (!original.equals(encoded)) {
>>> + return new StringModel(encoded, this.wrapper);
>>> + }
>>> + }
>>> + }
>>> + return tm;
>>> + }
>>> + }
>>> +}
>>>
>>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java
>>> ------------------------------------------------------------------------------
>>> svn:eol-style = native
>>>
>>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java
>>> ------------------------------------------------------------------------------
>>> svn:keywords = "Date Rev Author URL Id"
>>>
>>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/ GenericValueHtmlWrapper.java
>>> ------------------------------------------------------------------------------
>>> svn:mime-type = text/plain
>>>
>>> Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ RequestHandler.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ RequestHandler.java (original)
>>> +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/ RequestHandler.java Sun Feb 8 07:40:40 2009
>>> @@ -950,7 +950,9 @@
>>> public boolean trackStats(HttpServletRequest request) {
>>> if (!"false".equalsIgnoreCase(context.getInitParameter("track- serverhit"))) {
>>> String uriString = RequestHandler.getRequestUri(request.getPathInfo());
>>> - return controllerConfig.requestMapMap.get(uriString).trackServerHit;
>>> + ConfigXMLReader.RequestMap requestMap = controllerConfig.requestMapMap.get(uriString);
>>> + if (requestMap == null) return false;
>>> + return requestMap.trackServerHit;
>>> } else {
>>> return false;
>>> }
>>> @@ -959,7 +961,9 @@
>>> public boolean trackVisit(HttpServletRequest request) {
>>> if (!"false".equalsIgnoreCase(context.getInitParameter("track- visit"))) {
>>> String uriString = RequestHandler.getRequestUri(request.getPathInfo());
>>> - return controllerConfig.requestMapMap.get(uriString).trackVisit;
>>> + ConfigXMLReader.RequestMap requestMap = controllerConfig.requestMapMap.get(uriString);
>>> + if (requestMap == null) return false;
>>> + return requestMap.trackVisit;
>>> } else {
>>> return false;
>>> }
>>>
>>> Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java
>>> URL:
>>> http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java?rev=742013&r1=742012&r2=742013&view=diff
>>> = = = = = = = = = =====================================================================
>>> --- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java (original)
>>> +++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/ HtmlWidget.java Sun Feb 8 07:40:40 2009
>>> @@ -21,7 +21,6 @@
>>> import java.io.IOException;
>>> import java.net.MalformedURLException;
>>> import java.util.ArrayList;
>>> -import java.util.Iterator;
>>> import java.util.List;
>>> import java.util.Map;
>>>
>>> @@ -29,9 +28,11 @@
>>>
>>> import org.ofbiz.base.util.Debug;
>>> import org.ofbiz.base.util.GeneralException;
>>> +import org.ofbiz.base.util.StringUtil;
>>> import org.ofbiz.base.util.UtilGenerics;
>>> import org.ofbiz.base.util.UtilValidate;
>>> import org.ofbiz.base.util.UtilXml;
>>> +import org.ofbiz.base.util.cache.UtilCache;
>>> import org.ofbiz.base.util.collections.MapStack;
>>> import org.ofbiz.base.util.string.FlexibleStringExpander;
>>> import org.ofbiz.base.util.template.FreeMarkerWorker;
>>> @@ -39,7 +40,13 @@
>>> import org.ofbiz.widget.html.HtmlWidgetRenderer;
>>> import org.w3c.dom.Element;
>>>
>>> +import freemarker.ext.beans.BeansWrapper;
>>> +import freemarker.ext.beans.StringModel;
>>> +import freemarker.template.Configuration;
>>> +import freemarker.template.Template;
>>> import freemarker.template.TemplateException;
>>> +import freemarker.template.TemplateModel;
>>> +import freemarker.template.TemplateModelException;
>>>
>>> /**
>>> * Widget Library - Screen model HTML class.
>>> @@ -47,6 +54,37 @@
>>> @SuppressWarnings("serial")
>>> public class HtmlWidget extends ModelScreenWidget {
>>> public static final String module = HtmlWidget.class.getName();
>>> +
>>> + public static UtilCache<String, Template> specialTemplateCache = new UtilCache<String,
>>> Template>("widget.screen.template.ftl.general", 0, 0, false);
>>> + protected static BeansWrapper specialBeansWrapper = new ExtendedWrapper();
>>> + protected static Configuration specialConfig = FreeMarkerWorker.makeConfiguration(specialBeansWrapper);
>>> +
>>> + // not sure if this is the best way to get FTL to use my fancy MapModel derivative, but should work at least...
>>> + public static class ExtendedWrapper extends BeansWrapper {
>>> + public TemplateModel wrap(Object object) throws TemplateModelException {
>>> + /* NOTE: don't use this and the StringHtmlWrapperForFtl or things will be double-encoded
>>> + if (object instanceof GenericValue) {
>>> + return new GenericValueHtmlWrapperForFtl((GenericValue) object, this);
>>> + }*/
>>> + // This StringHtmlWrapperForFtl option seems to be the best option
>>> + // and handles most things without causing too many problems
>>> + if (object instanceof String) {
>>> + return new StringHtmlWrapperForFtl((String) object, this);
>>> + }
>>> + return super.wrap(object);
>>> + }
>>> + }
>>> +
>>> + public static class StringHtmlWrapperForFtl extends StringModel {
>>> + public StringHtmlWrapperForFtl(String str, BeansWrapper wrapper) {
>>> + super(str, wrapper);
>>> + }
>>> + public String getAsString() {
>>> + return StringUtil.htmlEncoder.encode(super.getAsString());
>>> + }
>>> + }
>>> +
>>> + // End Static, begin class section
>>>
>>> protected List<ModelScreenWidget> subWidgets = new ArrayList<ModelScreenWidget>();
>>>
>>> @@ -87,6 +125,64 @@
>>> throw new IllegalArgumentException("Template location is empty");
>>> }
>>>
>>> +
>>> + /*
>>> + // = = =====================================================================
>>> + // Go through the context and find GenericValue objects and wrap them
>>> +
>>> + // NOTE PROBLEM: there are still problems with this as it gets some things
>>> + // but does not get non-entity data including lots of strings
>>> + // directly in the context or things prepared or derived right in
>>> + // the FTL file, like the results of service calls, etc; we could
>>> + // do something more aggressive to encode and wrap EVERYTHING in
>>> + // the context, but I've been thinking that even this is too much
>>> + // overhead and that would be crazy
>>> +
>>> + // NOTE ALTERNATIVE1: considering instead to use the FTL features to wrap
>>> + // everything in an <#escape x as x?html>...</#escape>, but that could
>>> + // cause problems with ${} expansions that have HTML in them, including:
>>> + // included screens (using ${screens.render(...)}), content that should
>>> + // have HTML in it (lots of general, product, category, etc content), etc
>>> +
>>> + // NOTE ALTERNATIVE2: kind of like the "#escape X as x? html" option,
>>> + // implement an FTL *Model class and load it through a ObjectWrapper
>>> + // FINAL NOTE: after testing all of these alternatives, this one seems
>>> + // to behave the best, so going with that for now.
>>> +
>>> + // isolate the scope so these wrapper objects go away after rendering is done
>>> + MapStack<String> contextMs;
>>> + if (!(context instanceof MapStack)) {
>>> + contextMs = MapStack.create(context);
>>> + context = contextMs;
>>> + } else {
>>> + contextMs = UtilGenerics.cast(context);
>>> + }
>>> +
>>> + contextMs.push();
>>> + for(Map.Entry<String, Object> mapEntry: contextMs.entrySet()) {
>>> + Object value = mapEntry.getValue();
>>> + if (value instanceof GenericValue) {
>>> + contextMs.put(mapEntry.getKey(), GenericValueHtmlWrapper.create((GenericValue) value));
>>> + } else if (value instanceof List) {
>>> + if (((List) value).size() > 0 && ((List) value).get(0) instanceof GenericValue) {
>>> + List<GenericValue> theList = (List<GenericValue>) value;
>>> + List<GenericValueHtmlWrapper> newList = FastList.newInstance();
>>> + for (GenericValue gv: theList) {
>>> + newList.add(GenericValueHtmlWrapper.create(gv));
>>> + }
>>> + contextMs.put(mapEntry.getKey(), newList);
>>> + }
>>> + }
>>> + // TODO and NOTE: should get most stuff, but we could support Maps
>>> + // and Lists in Maps and such; that's tricky because we have to go
>>> + // through the entire Map and not just one entry, and we would
>>> + // have to shallow copy the whole Map too
>>> +
>>> + }
>>> + // this line goes at the end of the method, but moved up here to be part of the big comment about this
>>> + contextMs.pop();
>>> + */
>>> +
>>> if (location.endsWith(".ftl")) {
>>> try {
>>> Map<String, ? extends Object> parameters = UtilGenerics.checkMap(context.get("parameters"));
>>> @@ -94,7 +190,11 @@
>>> if (insertWidgetBoundaryComments) {
>>> writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin", "Template", location));
>>> }
>>> - FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
>>> +
>>> + // FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
>>> + Template template = FreeMarkerWorker.getTemplate(location, specialTemplateCache, specialConfig);
>>> + FreeMarkerWorker.renderTemplate(template, context, writer);
>>> +
>>> if (insertWidgetBoundaryComments) {
>>> writer.append(HtmlWidgetRenderer.formatBoundaryComment("End", "Template", location));
>>> }
>>>
>>
>
Re: svn commit: r742013 - in /ofbiz/trunk/framework: base/config/ base/src/org/ofbiz/base/util/template/ entity/src/org/ofbiz/entity/ webapp/src/org/ofbiz/webapp/control/ widget/src/org/ofbiz/widget/screen/
Posted by David E Jones <da...@hotwaxmedia.com>.
I'm looking into this now.
-David
On Feb 8, 2009, at 9:21 AM, Jacques Le Roux wrote:
> This causes an issue when rendering a javascript variable build in
> groovy
> Commenting out lines 71-73 of HtmlWidget.java solves the problem.
> Please see Giant Widget with variant explosion in ecommerce when
> viewing details for an example.
> I would suggest
> if (object instanceof String) {
> if (!((String) object).contains("<script language=
> \"JavaScript\">")) {
> return new StringHtmlWrapperForFtl((String)
> object, this);
> }
> }
>
>
> but not sue it's the best way (it works of course)
>
> Jacques
>
> From: <jo...@apache.org>
>> Author: jonesde
>> Date: Sun Feb 8 07:40:40 2009
>> New Revision: 742013
>>
>> URL: http://svn.apache.org/viewvc?rev=742013&view=rev
>> Log:
>> Implemented StringModel extension and BeansWrapper extension to
>> load it in order to encode strings for HTML use; this is only done
>> throught the HtmlWidget class that is part of the screen widget, so
>> won't interfere with other FTL uses; note that there is other
>> experimental code in here for wrapping the GenericValue object for
>> html encoding, but that option wasn't very complete so went this
>> way instead; this option behaves better and is more transparent
>> than that escape x as x?html option for FTL files; there are also a
>> few cleanups of typos and things in here; note that this means we
>> have a different Configuration object and so a different template
>> cache, and so we have different cache settings and such; after
>> applying this I found a few places that encoded things they
>> shouldn't but for the most part it is pretty good; will be
>> committing some changes in applications in a bit to resolve a
>> couple of these issues in ecommerce; all should watch out for funny
>> things showing up as
>> HTML text instead of being interpreted by the browser as HTML,
>> meaning it was encoded; in extreme cases just comment out lines
>> 71-73 of HtmlWidget.java to turn off this encoding
>>
>> Added:
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java (with props)
>> Modified:
>> ofbiz/trunk/framework/base/config/cache.properties
>> ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/
>> FreeMarkerWorker.java
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericEntity.java
>> ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java
>> ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/
>> RequestHandler.java
>> ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/
>> HtmlWidget.java
>>
>> Modified: ofbiz/trunk/framework/base/config/cache.properties
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/config/cache.properties?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/base/config/cache.properties (original)
>> +++ ofbiz/trunk/framework/base/config/cache.properties Sun Feb 8
>> 07:40:40 2009
>> @@ -91,8 +91,9 @@
>> widget.tree.locationResource.expireTime=10000
>> widget.tree.webappResource.expireTime=10000
>>
>> -template.ftl.general.expireTime=10000
>> template.ftl.location.expireTime=10000
>> +template.ftl.general.expireTime=10000
>> +widget.screen.template.ftl.general.expireTime=10000
>>
>> ModelDataFile.expireTime=10000
>>
>>
>> Modified: ofbiz/trunk/framework/base/src/org/ofbiz/base/util/
>> template/FreeMarkerWorker.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/FreeMarkerWorker.java?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/
>> FreeMarkerWorker.java (original)
>> +++ ofbiz/trunk/framework/base/src/org/ofbiz/base/util/template/
>> FreeMarkerWorker.java Sun Feb 8 07:40:40 2009
>> @@ -62,7 +62,6 @@
>> import freemarker.template.TemplateException;
>> import freemarker.template.TemplateModel;
>> import freemarker.template.TemplateModelException;
>> -//import com.clarkware.profiler.Profiler;
>>
>> /** FreeMarkerWorker - Freemarker Template Engine Utilities.
>> *
>> @@ -73,17 +72,19 @@
>>
>> // use soft references for this so that things from Content
>> records don't kill all of our memory, or maybe not for performance
>> reasons... hmmm, leave to config file...
>> public static UtilCache<String, Template> cachedTemplates = new
>> UtilCache<String, Template>("template.ftl.general", 0, 0, false);
>> - protected static Configuration defaultOfbizConfig = new
>> Configuration();
>> + protected static BeansWrapper defaultOfbizWrapper =
>> BeansWrapper.getDefaultInstance();
>> + protected static Configuration defaultOfbizConfig =
>> makeConfiguration(defaultOfbizWrapper);
>>
>> - static {
>> - BeansWrapper wrapper = BeansWrapper.getDefaultInstance();
>> - defaultOfbizConfig.setObjectWrapper(wrapper);
>> - defaultOfbizConfig.setSharedVariable("Static",
>> wrapper.getStaticModels());
>> - defaultOfbizConfig.setLocalizedLookup(false);
>> - defaultOfbizConfig.setTemplateLoader(new
>> FlexibleTemplateLoader());
>> + public static Configuration makeConfiguration(BeansWrapper
>> wrapper) {
>> + Configuration newConfig = new Configuration();
>> +
>> + newConfig.setObjectWrapper(wrapper);
>> + newConfig.setSharedVariable("Static",
>> wrapper.getStaticModels());
>> + newConfig.setLocalizedLookup(false);
>> + newConfig.setTemplateLoader(new FlexibleTemplateLoader());
>> try {
>> - defaultOfbizConfig.setSetting("datetime_format", "yyyy-
>> MM-dd HH:mm:ss.SSS");
>> - defaultOfbizConfig.setSetting("number_format",
>> "0.##########");
>> + newConfig.setSetting("datetime_format", "yyyy-MM-dd
>> HH:mm:ss.SSS");
>> + newConfig.setSetting("number_format", "0.##########");
>> } catch (TemplateException e) {
>> Debug.logError("Unable to set date/time and number
>> formats in FreeMarker: " + e, module);
>> }
>> @@ -103,23 +104,25 @@
>> if (props == null || props.isEmpty()) {
>> Debug.logError("Unable to locate properties file " +
>> propertyURL, module);
>> } else {
>> - loadTransforms(loader, props);
>> + loadTransforms(loader, props, newConfig);
>> }
>> }
>> +
>> + return newConfig;
>> }
>>
>> /**
>> * Protected helper method.
>> */
>> - protected static void loadTransforms(ClassLoader loader,
>> Properties props) {
>> + protected static void loadTransforms(ClassLoader loader,
>> Properties props, Configuration config) {
>> for (Iterator<Object> i = props.keySet().iterator();
>> i.hasNext();) {
>> - String key = (String)i.next();
>> + String key = (String) i.next();
>> String className = props.getProperty(key);
>> if (Debug.verboseOn()) {
>> Debug.logVerbose("Adding FTL Transform " + key + "
>> with class " + className, module);
>> }
>> try {
>> - defaultOfbizConfig.setSharedVariable(key,
>> loader.loadClass(className).newInstance());
>> + config.setSharedVariable(key,
>> loader.loadClass(className).newInstance());
>> } catch (Exception e) {
>> Debug.logError(e, "Could not pre-initialize
>> dynamically loaded class: " + className + ": " + e, module);
>> }
>> @@ -195,7 +198,7 @@
>> // FIXME: the casting from Appendable to Writer is a
>> temporary fix that could cause a
>> // run time error if in the future we will pass a
>> different class to the method
>> // (such as a StringBuffer).
>> - Environment env =
>> template.createProcessingEnvironment(context, (Writer)outWriter);
>> + Environment env =
>> template.createProcessingEnvironment(context, (Writer) outWriter);
>> applyUserSettings(env, context);
>> env.process();
>> return env;
>> @@ -261,16 +264,20 @@
>> * @param templateLocation Location of the template - file path
>> or URL
>> */
>> public static Template getTemplate(String templateLocation)
>> throws TemplateException, IOException {
>> - Template template = (Template)
>> cachedTemplates.get(templateLocation);
>> + return getTemplate(templateLocation, cachedTemplates,
>> defaultOfbizConfig);
>> + }
>> +
>> + public static Template getTemplate(String templateLocation,
>> UtilCache<String, Template> cache, Configuration config) throws
>> TemplateException, IOException {
>> + Template template = (Template) cache.get(templateLocation);
>> if (template == null) {
>> - synchronized (cachedTemplates) {
>> - template = (Template)
>> cachedTemplates.get(templateLocation);
>> + synchronized (cache) {
>> + template = (Template) cache.get(templateLocation);
>> if (template == null) {
>> // only make the reader if we need it, and then
>> close it right after!
>> Reader templateReader =
>> makeReader(templateLocation);
>> - template = new Template(templateLocation,
>> templateReader, defaultOfbizConfig);
>> + template = new Template(templateLocation,
>> templateReader, config);
>> templateReader.close();
>> - cachedTemplates.put(templateLocation, template);
>> + cache.put(templateLocation, template);
>> }
>> }
>> }
>>
>> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericEntity.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericEntity.java?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericEntity.java (original)
>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericEntity.java Sun Feb 8 07:40:40 2009
>> @@ -142,21 +142,21 @@
>> /** Creates new GenericEntity */
>> protected void init(ModelEntity modelEntity) {
>> if (modelEntity == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null modelEntity parameter");
>> }
>> this.modelEntity = modelEntity;
>> this.entityName = modelEntity.getEntityName();
>>
>> // check some things
>> if (this.entityName == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> }
>> }
>>
>> /** Creates new GenericEntity from existing Map */
>> protected void init(ModelEntity modelEntity, Map<String, ?
>> extends Object> fields) {
>> if (modelEntity == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null modelEntity parameter");
>> }
>> this.modelEntity = modelEntity;
>> this.entityName = modelEntity.getEntityName();
>> @@ -164,14 +164,14 @@
>>
>> // check some things
>> if (this.entityName == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> }
>> }
>>
>> /** Creates new GenericEntity from existing Map */
>> protected void init(ModelEntity modelEntity, Object
>> singlePkValue) {
>> if (modelEntity == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null modelEntity parameter");
>> }
>> if (modelEntity.getPksSize() != 1) {
>> throw new IllegalArgumentException("Cannot create a
>> GenericEntity with more than one primary key field");
>> @@ -182,25 +182,22 @@
>>
>> // check some things
>> if (this.entityName == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> }
>> }
>>
>> /** Copy Constructor: Creates new GenericEntity from existing
>> GenericEntity */
>> protected void init(GenericEntity value) {
>> - if (value.modelEntity == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity from another GenericEntity with a null modelEntity in
>> the value parameter");
>> + // check some things
>> + if (value.entityName == null) {
>> + throw new IllegalArgumentException("Cannot create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> }
>> - this.entityName = value.modelEntity.getEntityName();
>> + this.entityName = value.getEntityName();
>> + // NOTE: could call getModelEntity to insure we have a
>> value, just in case the value passed in has been serialized, but
>> might as well leave it null to keep the object light if it isn't
>> there
>> this.modelEntity = value.modelEntity;
>> if (value.fields != null) this.fields.putAll(value.fields);
>> this.delegatorName = value.delegatorName;
>> this.internalDelegator = value.internalDelegator;
>> -
>> - // check some things
>> - if (this.entityName == null) {
>> - throw new IllegalArgumentException("Cannont create a
>> GenericEntity with a null entityName in the modelEntity parameter");
>> - }
>> }
>>
>> public void reset() {
>>
>> Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValue.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValue.java?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValue.java (original)
>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValue.java Sun Feb 8 07:40:40 2009
>> @@ -24,8 +24,8 @@
>> import java.util.List;
>> import java.util.Map;
>>
>> -import javolution.lang.Reusable;
>> import javolution.context.ObjectFactory;
>> +import javolution.lang.Reusable;
>> import javolution.util.FastMap;
>>
>> import org.ofbiz.base.util.Debug;
>> @@ -33,7 +33,6 @@
>> import org.ofbiz.base.util.UtilValidate;
>> import org.ofbiz.entity.condition.EntityCondition;
>> import org.ofbiz.entity.condition.EntityFieldMap;
>> -import org.ofbiz.entity.condition.EntityOperator;
>> import org.ofbiz.entity.model.ModelEntity;
>> import org.ofbiz.entity.model.ModelKeyMap;
>> import org.ofbiz.entity.model.ModelRelation;
>> @@ -44,6 +43,7 @@
>> * Generic Entity Value Object - Handles persistence for any defined
>> entity.
>> *
>> */
>> +@SuppressWarnings("serial")
>> public class GenericValue extends GenericEntity implements Reusable {
>>
>> public static final GenericValue NULL_VALUE = new
>> NullGenericValue();
>>
>> Added: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/GenericValueHtmlWrapper.java?rev=742013&view=auto
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java (added)
>> +++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java Sun Feb 8 07:40:40 2009
>> @@ -0,0 +1,105 @@
>> +/
>> *******************************************************************************
>> + * Licensed to the Apache Software Foundation (ASF) under one
>> + * or more contributor license agreements. See the NOTICE file
>> + * distributed with this work for additional information
>> + * regarding copyright ownership. The ASF licenses this file
>> + * to you under the Apache License, Version 2.0 (the
>> + * "License"); you may not use this file except in compliance
>> + * with the License. You may obtain a copy of the License at
>> + *
>> + * http://www.apache.org/licenses/LICENSE-2.0
>> + *
>> + * Unless required by applicable law or agreed to in writing,
>> + * software distributed under the License is distributed on an
>> + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
>> + * KIND, either express or implied. See the License for the
>> + * specific language governing permissions and limitations
>> + * under the License.
>> +
>> *******************************************************************************/
>> +
>> +package org.ofbiz.entity;
>> +
>> +
>> +import javolution.context.ObjectFactory;
>> +
>> +import org.ofbiz.base.util.Debug;
>> +import org.ofbiz.base.util.StringUtil;
>> +
>> +import freemarker.ext.beans.BeansWrapper;
>> +import freemarker.ext.beans.MapModel;
>> +import freemarker.ext.beans.StringModel;
>> +import freemarker.template.TemplateModel;
>> +import freemarker.template.TemplateModelException;
>> +
>> +
>> +/**
>> + * Generic Entity Value Object - Handles persistence for any
>> defined entity.
>> + * WARNING: This object is experimental!
>> + *
>> + */
>> +@SuppressWarnings("serial")
>> +public class GenericValueHtmlWrapper extends GenericValue {
>> + protected static final ObjectFactory<GenericValueHtmlWrapper>
>> genericValueHtmlWrapperFactory = new
>> ObjectFactory<GenericValueHtmlWrapper>() {
>> + protected GenericValueHtmlWrapper create() {
>> + return new GenericValueHtmlWrapper();
>> + }
>> + };
>> +
>> + /** Creates new GenericValueHtmlWrapper from existing
>> GenericValue */
>> + public static GenericValueHtmlWrapper create(GenericValue
>> value) {
>> + GenericValueHtmlWrapper newValue =
>> genericValueHtmlWrapperFactory.object();
>> + try {
>> + newValue.init(value);
>> + } catch (RuntimeException e) {
>> + Debug.logError(e, "Error in init for clone of value: "
>> + value, module);
>> + throw e;
>> + }
>> + return newValue;
>> + }
>> +
>> + /* NOTE: this is NOT used because there are certain FTL files
>> that call services and things, and this messes those up, so only
>> overriding the Map.get(Object) method to get use of this as a Map
>> + * Override the basic get method, which all other get methods
>> call so we only need to do this one (though most important for the
>> Map.get(Object) and the getString() methods
>> + public Object get(String name) {
>> + Object value = super.get(name);
>> + if (value instanceof String) {
>> + return StringUtil.htmlEncoder.encode((String) value);
>> + } else {
>> + return value;
>> + }
>> + }*/
>> +
>> + public Object get(Object name) {
>> + Object value = super.get(name);
>> + if (value instanceof String) {
>> + return StringUtil.htmlEncoder.encode((String) value);
>> + } else {
>> + return value;
>> + }
>> + }
>> +
>> + // another experimental object, this one specifically for FTL
>> + public static class GenericValueHtmlWrapperForFtl extends
>> MapModel {
>> + public GenericValueHtmlWrapperForFtl(GenericValue gv,
>> BeansWrapper wrapper) {
>> + super(gv, wrapper);
>> + }
>> +
>> + public TemplateModel get(String key) {
>> + TemplateModel tm = null;
>> + try {
>> + tm = super.get(key);
>> + } catch (TemplateModelException e) {
>> + Debug.logError(e, "Error getting Map with key [" +
>> key + "]: " + e.toString(), module);
>> + }
>> + if (tm instanceof StringModel) {
>> + String original = ((StringModel) tm).getAsString();
>> + if (original != null) {
>> + String encoded =
>> StringUtil.htmlEncoder.encode(original);
>> + if (!original.equals(encoded)) {
>> + return new StringModel(encoded,
>> this.wrapper);
>> + }
>> + }
>> + }
>> + return tm;
>> + }
>> + }
>> +}
>>
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java
>> ------------------------------------------------------------------------------
>> svn:eol-style = native
>>
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java
>> ------------------------------------------------------------------------------
>> svn:keywords = "Date Rev Author URL Id"
>>
>> Propchange: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/
>> GenericValueHtmlWrapper.java
>> ------------------------------------------------------------------------------
>> svn:mime-type = text/plain
>>
>> Modified: ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/
>> RequestHandler.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/RequestHandler.java?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/
>> RequestHandler.java (original)
>> +++ ofbiz/trunk/framework/webapp/src/org/ofbiz/webapp/control/
>> RequestHandler.java Sun Feb 8 07:40:40 2009
>> @@ -950,7 +950,9 @@
>> public boolean trackStats(HttpServletRequest request) {
>> if
>> (!"false".equalsIgnoreCase(context.getInitParameter("track-
>> serverhit"))) {
>> String uriString =
>> RequestHandler.getRequestUri(request.getPathInfo());
>> - return
>> controllerConfig.requestMapMap.get(uriString).trackServerHit;
>> + ConfigXMLReader.RequestMap requestMap =
>> controllerConfig.requestMapMap.get(uriString);
>> + if (requestMap == null) return false;
>> + return requestMap.trackServerHit;
>> } else {
>> return false;
>> }
>> @@ -959,7 +961,9 @@
>> public boolean trackVisit(HttpServletRequest request) {
>> if
>> (!"false".equalsIgnoreCase(context.getInitParameter("track-
>> visit"))) {
>> String uriString =
>> RequestHandler.getRequestUri(request.getPathInfo());
>> - return
>> controllerConfig.requestMapMap.get(uriString).trackVisit;
>> + ConfigXMLReader.RequestMap requestMap =
>> controllerConfig.requestMapMap.get(uriString);
>> + if (requestMap == null) return false;
>> + return requestMap.trackVisit;
>> } else {
>> return false;
>> }
>>
>> Modified: ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/
>> HtmlWidget.java
>> URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/HtmlWidget.java?rev=742013&r1=742012&r2=742013&view=diff
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> --- ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/
>> HtmlWidget.java (original)
>> +++ ofbiz/trunk/framework/widget/src/org/ofbiz/widget/screen/
>> HtmlWidget.java Sun Feb 8 07:40:40 2009
>> @@ -21,7 +21,6 @@
>> import java.io.IOException;
>> import java.net.MalformedURLException;
>> import java.util.ArrayList;
>> -import java.util.Iterator;
>> import java.util.List;
>> import java.util.Map;
>>
>> @@ -29,9 +28,11 @@
>>
>> import org.ofbiz.base.util.Debug;
>> import org.ofbiz.base.util.GeneralException;
>> +import org.ofbiz.base.util.StringUtil;
>> import org.ofbiz.base.util.UtilGenerics;
>> import org.ofbiz.base.util.UtilValidate;
>> import org.ofbiz.base.util.UtilXml;
>> +import org.ofbiz.base.util.cache.UtilCache;
>> import org.ofbiz.base.util.collections.MapStack;
>> import org.ofbiz.base.util.string.FlexibleStringExpander;
>> import org.ofbiz.base.util.template.FreeMarkerWorker;
>> @@ -39,7 +40,13 @@
>> import org.ofbiz.widget.html.HtmlWidgetRenderer;
>> import org.w3c.dom.Element;
>>
>> +import freemarker.ext.beans.BeansWrapper;
>> +import freemarker.ext.beans.StringModel;
>> +import freemarker.template.Configuration;
>> +import freemarker.template.Template;
>> import freemarker.template.TemplateException;
>> +import freemarker.template.TemplateModel;
>> +import freemarker.template.TemplateModelException;
>>
>> /**
>> * Widget Library - Screen model HTML class.
>> @@ -47,6 +54,37 @@
>> @SuppressWarnings("serial")
>> public class HtmlWidget extends ModelScreenWidget {
>> public static final String module = HtmlWidget.class.getName();
>> +
>> + public static UtilCache<String, Template> specialTemplateCache
>> = new UtilCache<String,
>> Template>("widget.screen.template.ftl.general", 0, 0, false);
>> + protected static BeansWrapper specialBeansWrapper = new
>> ExtendedWrapper();
>> + protected static Configuration specialConfig =
>> FreeMarkerWorker.makeConfiguration(specialBeansWrapper);
>> +
>> + // not sure if this is the best way to get FTL to use my fancy
>> MapModel derivative, but should work at least...
>> + public static class ExtendedWrapper extends BeansWrapper {
>> + public TemplateModel wrap(Object object) throws
>> TemplateModelException {
>> + /* NOTE: don't use this and the
>> StringHtmlWrapperForFtl or things will be double-encoded
>> + if (object instanceof GenericValue) {
>> + return new
>> GenericValueHtmlWrapperForFtl((GenericValue) object, this);
>> + }*/
>> + // This StringHtmlWrapperForFtl option seems to be the
>> best option
>> + // and handles most things without causing too many
>> problems
>> + if (object instanceof String) {
>> + return new StringHtmlWrapperForFtl((String)
>> object, this);
>> + }
>> + return super.wrap(object);
>> + }
>> + }
>> +
>> + public static class StringHtmlWrapperForFtl extends
>> StringModel {
>> + public StringHtmlWrapperForFtl(String str, BeansWrapper
>> wrapper) {
>> + super(str, wrapper);
>> + }
>> + public String getAsString() {
>> + return
>> StringUtil.htmlEncoder.encode(super.getAsString());
>> + }
>> + }
>> +
>> + // End Static, begin class section
>>
>> protected List<ModelScreenWidget> subWidgets = new
>> ArrayList<ModelScreenWidget>();
>>
>> @@ -87,6 +125,64 @@
>> throw new IllegalArgumentException("Template location is
>> empty");
>> }
>>
>> +
>> + /*
>> + //
>> =
>> =
>> =====================================================================
>> + // Go through the context and find GenericValue objects
>> and wrap them
>> +
>> + // NOTE PROBLEM: there are still problems with this as it
>> gets some things
>> + // but does not get non-entity data including lots of
>> strings
>> + // directly in the context or things prepared or derived
>> right in
>> + // the FTL file, like the results of service calls, etc;
>> we could
>> + // do something more aggressive to encode and wrap
>> EVERYTHING in
>> + // the context, but I've been thinking that even this is
>> too much
>> + // overhead and that would be crazy
>> +
>> + // NOTE ALTERNATIVE1: considering instead to use the FTL
>> features to wrap
>> + // everything in an <#escape x as x?html>...</#escape>,
>> but that could
>> + // cause problems with ${} expansions that have HTML in
>> them, including:
>> + // included screens (using ${screens.render(...)}),
>> content that should
>> + // have HTML in it (lots of general, product, category,
>> etc content), etc
>> +
>> + // NOTE ALTERNATIVE2: kind of like the "#escape X as x?
>> html" option,
>> + // implement an FTL *Model class and load it through a
>> ObjectWrapper
>> + // FINAL NOTE: after testing all of these alternatives,
>> this one seems
>> + // to behave the best, so going with that for now.
>> +
>> + // isolate the scope so these wrapper objects go away
>> after rendering is done
>> + MapStack<String> contextMs;
>> + if (!(context instanceof MapStack)) {
>> + contextMs = MapStack.create(context);
>> + context = contextMs;
>> + } else {
>> + contextMs = UtilGenerics.cast(context);
>> + }
>> +
>> + contextMs.push();
>> + for(Map.Entry<String, Object> mapEntry:
>> contextMs.entrySet()) {
>> + Object value = mapEntry.getValue();
>> + if (value instanceof GenericValue) {
>> + contextMs.put(mapEntry.getKey(),
>> GenericValueHtmlWrapper.create((GenericValue) value));
>> + } else if (value instanceof List) {
>> + if (((List) value).size() > 0 && ((List)
>> value).get(0) instanceof GenericValue) {
>> + List<GenericValue> theList =
>> (List<GenericValue>) value;
>> + List<GenericValueHtmlWrapper> newList =
>> FastList.newInstance();
>> + for (GenericValue gv: theList) {
>> +
>> newList.add(GenericValueHtmlWrapper.create(gv));
>> + }
>> + contextMs.put(mapEntry.getKey(), newList);
>> + }
>> + }
>> + // TODO and NOTE: should get most stuff, but we could
>> support Maps
>> + // and Lists in Maps and such; that's tricky because
>> we have to go
>> + // through the entire Map and not just one entry, and
>> we would
>> + // have to shallow copy the whole Map too
>> +
>> + }
>> + // this line goes at the end of the method, but moved up
>> here to be part of the big comment about this
>> + contextMs.pop();
>> + */
>> +
>> if (location.endsWith(".ftl")) {
>> try {
>> Map<String, ? extends Object> parameters =
>> UtilGenerics.checkMap(context.get("parameters"));
>> @@ -94,7 +190,11 @@
>> if (insertWidgetBoundaryComments) {
>>
>> writer.append(HtmlWidgetRenderer.formatBoundaryComment("Begin",
>> "Template", location));
>> }
>> -
>> FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
>> +
>> + //
>> FreeMarkerWorker.renderTemplateAtLocation(location, context, writer);
>> + Template template =
>> FreeMarkerWorker.getTemplate(location, specialTemplateCache,
>> specialConfig);
>> + FreeMarkerWorker.renderTemplate(template, context,
>> writer);
>> +
>> if (insertWidgetBoundaryComments) {
>>
>> writer.append(HtmlWidgetRenderer.formatBoundaryComment("End",
>> "Template", location));
>> }
>>
>