You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2010/03/30 23:25:12 UTC
svn commit: r929296 - in
/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces:
application/PortletStateManagerImpl.java
context/PortletExternalContextImpl.java
Author: mfreedman
Date: Tue Mar 30 21:25:11 2010
New Revision: 929296
URL: http://svn.apache.org/viewvc?rev=929296&view=rev
Log:
PORTLETBRIDGE-139: Bridge doesn't properly detect xml & escaping in QS
PORTLETBRIDGE-138: Bridge doesn't work correctly use of deprecated StateManager APIs
Modified:
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java
myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java?rev=929296&r1=929295&r2=929296&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletStateManagerImpl.java Tue Mar 30 21:25:11 2010
@@ -108,6 +108,46 @@ public class PortletStateManagerImpl
}
+ public void writeState(FacesContext context, SerializedView state)
+ throws IOException
+ {
+ // Do nothing when not running in portlet request
+ if (!BridgeUtil.isPortletRequest())
+ {
+ super.writeState(context, state);
+ return;
+ }
+
+ // Replace current response writer so can grab what is written
+ ResponseWriter oldRW = context.getResponseWriter();
+ StringWriter stringWriter = new StringWriter(128);
+ ResponseWriter newRW = oldRW.cloneWithWriter(stringWriter);
+ context.setResponseWriter(newRW);
+
+ super.writeState(context, state);
+
+ // Restore real responsewriter
+ context.setResponseWriter(oldRW);
+
+ // Get written state
+ newRW.flush();
+ String stateValue = new String(stringWriter.getBuffer());
+
+
+ // Write it to the old response writer
+ oldRW.write(stateValue);
+
+ // Now extract the parameter value from the buffer:
+ stateValue = extractViewStateParamValue(stateValue);
+
+ if (stateValue != null)
+ {
+ Map<String, Object> m = context.getExternalContext().getRequestMap();
+ m.put(BridgeImpl.UPDATED_VIEW_STATE_PARAM, stateValue);
+ }
+
+ }
+
public StateManager getWrapped()
{
return mDelegatee;
Modified: myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=929296&r1=929295&r2=929296&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Tue Mar 30 21:25:11 2010
@@ -463,15 +463,30 @@ public class PortletExternalContextImpl
}
}
}
+
+ url = actionURL.toString();
+
+ // JSF expects encodeActionURL to not perturb any XML encoding (or lack thereof) of the url.
+ // I.e. the caller is responsible for either pre or post XML escaping the string sent/returned
+ // by encodeActionURL. Unfortunately, the portlet 1.0 spec didn't define whether toString()
+ // returns an XML encoded string or not. Most containers behaved like the servlet environment and did not,
+ // however wsrp based containers had the option of encoding the consumer rewrite url either with & or &.
+ // Some containers choose the later.
+ //
+ // So special care must be taken here to fix up the url returned by the container
+ // to have the same encoding as what was sent in.
- // If we weren't already Xhtml encoded (used &) then renderkit will likely
- // do it after us if it needs to do such encoding -- so undo any xml encoding the portlet URL might
- // have done to avoid double encoding -- Otherwise if the string passed in was encoded the renderkit
- // is unlikely to reencode after the call -- so don't undo any encoding.
if (!isStrictXhtmlEncoded)
{
- url = actionURL.toString();
- url = url.replaceAll("\\&\\;", "&");
+ // If we weren't already Xhtml encoded (used &) then renderkit will likely
+ // do it after us if it needs to do such encoding -- so undo any xml encoding the portlet URL might
+ // have done to avoid double encoding -- Otherwise if the string passed in was encoded the renderkit
+ // is unlikely to reencode after the call -- so don't undo any encoding.
+ url = url.replace("&", "&");
+ }
+ else if (!isStrictXhtmlEncoded(url)) // check the new url and process if its not xml encoded
+ {
+ url = xhtmlEncode(url);
}
}
else
@@ -631,6 +646,8 @@ public class PortletExternalContextImpl
private String encodeResourceURL(String s, boolean targetInApp)
{
+ boolean isStrictXhtmlEncoded = isStrictXhtmlEncoded(s); // do here because replaceResourceQSMarkers changes
+
if (targetInApp)
{
s = normalizeResourcePath(s);
@@ -643,7 +660,7 @@ public class PortletExternalContextImpl
// do it after us if it needs to do such encoding -- so undo any xml encoding the portlet URL might
// have done to avoid double encoding -- Otherwise if the string passed in was encoded the renderkit
// is unlikely to reencode after the call -- so don't undo any encoding.
- if (!isStrictXhtmlEncoded(s))
+ if (!isStrictXhtmlEncoded)
{
// Some portlet containers implementing wsrp choose to separate the
@@ -651,11 +668,11 @@ public class PortletExternalContextImpl
// spec allows for either that or &. If the container has chosen to
// to do such -- undo it (use & instead) as faces renderkits/response writers
// may reencode when writing XMl content.
- return mPortletResponse.encodeURL(s).replaceAll("\\&\\;", "&");
+ return mPortletResponse.encodeURL(s).replace("&", "&");
}
else
{
- return mPortletResponse.encodeURL(s);
+ return xhtmlEncode(mPortletResponse.encodeURL(s));
}
}
@@ -1764,6 +1781,40 @@ public class PortletExternalContextImpl
return url.toLowerCase().startsWith("portlet:");
}
+ private String xhtmlEncode(String url)
+ {
+ StringBuffer sb = new StringBuffer(url.length());
+
+ // check for use of & in query string
+ int copyFrom = 0;
+ int currentPos = url.indexOf('?');
+
+ if (currentPos == -1) return url;
+
+ while (true)
+ {
+ int ampPos = url.indexOf('&', currentPos);
+ int xhtmlAmpPos = url.indexOf("&", currentPos);
+ // no more & to process -- so return current value of isStrict
+ if (ampPos == -1)
+ {
+ if (copyFrom < url.length())
+ {
+ sb.append(url, copyFrom, url.length());
+ }
+ return sb.toString();
+ }
+ // if the amp we found doesn't start an & then its not strict
+ if (ampPos != xhtmlAmpPos)
+ {
+ sb.append(url, copyFrom, ampPos);
+ sb.append("&");
+ copyFrom = ampPos + 1;
+ }
+ currentPos = ampPos + 1;
+ }
+ }
+
private boolean isStrictXhtmlEncoded(String url)
{
// check for use of & in query string
@@ -1775,7 +1826,7 @@ public class PortletExternalContextImpl
while (true)
{
int ampPos = url.indexOf('&', currentPos);
- int xhtmlAmpPos = url.indexOf("\\&\\;", currentPos);
+ int xhtmlAmpPos = url.indexOf("&", currentPos);
// no more & to process -- so return current value of isStrict
if (ampPos == -1)
{
@@ -1787,7 +1838,7 @@ public class PortletExternalContextImpl
return false;
}
isStrict = true;
- currentPos = ampPos;
+ currentPos = ampPos + 1;
}
}