views:

224

answers:

3

two days ago i started using tomahawk ExtensionsFilter components im my jsf application. i noticed that all javascript alerts were not displaying special characters (ç, ã, ó ô), it displays things like #231 instead. When i remove ExtensionsFilter from my web.xml file, javascript displays allright. Anybody had this issue before?
thanks in advance.

EDIT: i was able to solve the problem by creating a filter before the extensionFilter, this new filter force the REQUEST charset to utf-8. But this is an ugly solution, a better solution, as balusC said, would be to get rid of all the inline javascript.
Thank you all for the help!

+1  A: 

It escapes XML entities. It is however also considered poor practice to serve Javascript code inline in a JSP/XHTML file. Externalize it in its own file which you specify in <script src="path/to/file.js"></script> (at least, its URL should not be covered by the filter) and this particular problem should disappear.

BalusC
Yes i know about how bad inline javascript is, but it is a huge application with 1000+ jsp files, and we just don't have the time to change all those files. Any other reasonable solution? thanks for the response.
marcos
Try a more specific mapping of filter. Map it on the `url-pattern`s of the pages which actually need this filter and then change only those pages.
BalusC
+2  A: 

A few other ideas:

  • add filter which calls setContentType or setCharacterEncoding and which is before all other filters
  • set the property -Dfile.encoding
  • rebind the javascript window.alert so that it escapes the characters

This seems to work, but would be a very, very ugly hack. This would also be very limited and won't work if javascript sets other texts, e.g. content of a div.

var hack = window.alert;
window.alert = function( text ) {
    hack( text + ' was converted' );
};
alert('hello');


UPDATE:

Here is the sequence that is suspect:

1) ExtensionsFilter intercepts the request

2) ExtensionsFilter contains

  154   // only parse HTML responses
  155   if (extendedResponse.getContentType() != null && isValidContentType(extendedResponse.getContentType()))
  156   {
        ...
  172        // writes the response
  173        addResource.writeResponse(extendedRequest, servletResponse);
  174    }
  175   else
  176   {
  178        byte[] responseArray = extendedResponse.getBytes();
  180        if(responseArray.length > 0)
  181       {
  182       // When not filtering due to not valid content-type, deliver the byte-array instead of a charset-converted string.
  183       // Otherwise a binary stream gets corrupted.
  184       servletResponse.getOutputStream().write(responseArray);
  185     }

3) DefaultAddResource uses HtmlResponseWriterImpl which uses UnicodeEncoder.

4) All "non basic latin characters" are then encoded.

Conclusion

  • if you set the content type to something invalid, the ExtensionsFilter will default to the "else" branch and won't encode the response. But, then the ExtensionsFilter is probably broken.
  • changing setCharacterEncoding has probably no effect, neither the file.encoding
  • creating an extra filter to wrap again the response and revert some of the &#xx; could work but is extremely ugly.

I don't have other ideas right now, but I'm interested in the answer as I also bumped on encoding issue which were annoying.


UPDATE 2:

You could give a try to AspectJ to alter just the part of the MyFaces library that relates to the encoding form within the filter. According to my understanding of cflow and the call pointcut pickings, something like this might intercept the encoding when it happens from the filter. If this definition creates other interferences in the request processing, you might want to also consider the call to addResource.writeResponse to limit further the pointcut.

public aspect SkipEncoding {  
    pointcut encodingInExtFilter() : 
     cflow( * org.apache.myfaces.webapp.filter. ExtensionsFilter.doFilter(..) ) && 
     call ( String UnicodeEncoder.encode( String, bool, bool ));   
    around( String s, bool b1, bool b2 ) : encodingInExtFilter
    {
     return s; // skip encoding
    }
}
ewernli
The ExtensionsFilter doesn't change page encoding.
BalusC
+1  A: 

By the way, do you have any of these in your jsp pages:

<?xml version="1.0" encoding="utf-8"?>

or

<%@ page pageEncoding="utf-8" %>
Bozho
i have the html metadata tag with charset=utf-8
marcos
this isn't always enough
Bozho
yes i know, i tried <%@ page pageEncoding="utf-8" %> but then all my jsp labels got screwed, not only javascript.
marcos
That would mean you have some deeper problem. Check whether your files are encoded properly.
Bozho