Details
-
Type: Improvement
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: 1.7.2 SP1
-
Component/s: ICE-Components
-
Labels:None
-
Environment:Linux, Windows, Mac OS X & IE, Safari, Firefox & Glassfish v2
-
ICEsoft Forum Reference:
Description
I think it's a bug of OutputResource, because instead of writing filename directly to Content-Disposition, it should encode it somehow first.
-
Hide
- c-s-jsp.war
- 8.05 MB
- yip.ng
-
- META-INF/MANIFEST.MF 0.1 kB
- WEB-INF/classes/.../NavigationBean.class 1 kB
- WEB-INF/classes/.../entity/Employee.class 2 kB
- WEB-INF/classes/org/.../entity/Person.class 1 kB
- WEB-INF/classes/.../EmployeeService.class 0.3 kB
- WEB-INF/.../EmployeeServiceImpl$1.class 0.3 kB
- WEB-INF/.../EmployeeServiceImpl$EmployeeComparator.class 3 kB
- WEB-INF/.../EmployeeServiceImpl.class 6 kB
- WEB-INF/classes/.../ContextUtilBean.class 3 kB
- WEB-INF/classes/.../util/FacesUtils.class 4 kB
- WEB-INF/classes/.../util/LocaleBean.class 3 kB
- WEB-INF/.../MessageBundleLoader.class 2 kB
- WEB-INF/.../RandomNumberGenerator.class 2 kB
- WEB-INF/.../SourceCodeLoaderServlet.class 3 kB
- WEB-INF/.../StyleBean$StylePath.class 1 kB
- WEB-INF/classes/org/.../util/StyleBean.class 3 kB
- WEB-INF/classes/org/.../bean/BaseBean.class 3 kB
- WEB-INF/classes/org/.../bean/BeanNames.class 0.7 kB
- WEB-INF/classes/.../NavigationNames.class 0.4 kB
- WEB-INF/classes/.../Inventory.class 2 kB
- WEB-INF/classes/.../InventoryInterface.class 0.5 kB
- WEB-INF/classes/.../InventoryItem.class 2 kB
- WEB-INF/.../ButtonsAndLinksBean.class 2 kB
- WEB-INF/classes/.../GroupingModel.class 0.8 kB
- WEB-INF/.../ColumnsBean$CellKey.class 1 kB
- WEB-INF/classes/.../ColumnsBean.class 5 kB
- WEB-INF/classes/.../SortHeaderModel.class 3 kB
- WEB-INF/classes/.../DataExporter.class 1 kB
- WEB-INF/.../DataScrollingModel$DataScrollMode.class 2 kB
- WEB-INF/classes/.../DataScrollingModel.class 3 kB
-
- fileName with '('.jpg
- 76 kB
-
- ScreenHunter_01.jpg
- 224 kB
-
- ScreenHunter_02.jpg
- 224 kB
-
- ScreenHunter_03.jpg
- 220 kB
-
- ScreenHunter_04.jpg
- 212 kB
-
- ScreenHunter_05.jpg
- 211 kB
-
- ScreenHunter_06.jpg
- 219 kB
-
- ScreenHunter_07.jpg
- 207 kB
-
- ScreenHunter_08.jpg
- 219 kB
-
- ScreenHunter_09.jpg
- 214 kB
-
- ScreenHunter_10.jpg
- 255 kB
Activity
- All
- Comments
- History
- Activity
- Remote Attachments
- Subversion
If the filename contains any special chars, even a ')' the ressource can not be found:
Firefox displays:
Could not find resource at /intertax-web/block/resource/LTIwMjc3NjA2MzI=/Testingday_20_5__(a)_200907141213.xml
see screenshot
Tried using the suggested encoding methods. Got the following exceptions:
14-Jul-2009 5:37:48 PM com.sun.faces.lifecycle.Phase doPhase
name = /block/resource/MjAyNjQwNTE1MA==/
SEVERE: JSF1054: (Phase ID: RENDER_RESPONSE 6, View ID: /showcase.jspx) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@f77511]
14-Jul-2009 5:37:48 PM com.icesoft.faces.webapp.http.core.ReceiveSendUpdates service
SEVERE: Exception occured during rendering on http://localhost:8080/component-showcase-trunk/block/send-receive-updates [/showcase.jspx]
javax.faces.FacesException: java.lang.IllegalArgumentException
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:128)
at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
at com.icesoft.faces.webapp.http.core.JsfLifecycleExecutor.apply(JsfLifecycleExecutor.java:19)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.renderCycle(ReceiveSendUpdates.java:132)
at com.icesoft.faces.webapp.http.core.ReceiveSendUpdates.service(ReceiveSendUpdates.java:74)
at com.icesoft.faces.webapp.http.core.RequestVerifier.service(RequestVerifier.java:28)
at com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer.service(PathDispatcherServer.java:24)
at com.icesoft.faces.webapp.http.servlet.MainSessionBoundServlet.service(MainSessionBoundServlet.java:160)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher$1.service(SessionDispatcher.java:42)
at com.icesoft.faces.webapp.http.servlet.ThreadBlockingAdaptingServlet.service(ThreadBlockingAdaptingServlet.java:27)
at com.icesoft.faces.webapp.http.servlet.EnvironmentAdaptingServlet.service(EnvironmentAdaptingServlet.java:63)
at com.icesoft.faces.webapp.http.servlet.SessionDispatcher.service(SessionDispatcher.java:62)
at com.icesoft.faces.webapp.http.servlet.SessionVerifier.service(SessionVerifier.java:22)
at com.icesoft.faces.webapp.http.servlet.PathDispatcher.service(PathDispatcher.java:23)
at com.icesoft.faces.webapp.http.servlet.MainServlet.service(MainServlet.java:152)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at com.icesoft.faces.webapp.xmlhttp.BlockingServlet.service(BlockingServlet.java:56)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:595)
Caused by: java.lang.IllegalArgumentException
at java.net.URI.create(URI.java:842)
at com.icesoft.faces.webapp.http.core.ResourceDispatcher.registerResource(ResourceDispatcher.java:101)
at com.icesoft.faces.context.BridgeFacesContext.registerResource(BridgeFacesContext.java:621)
at com.icesoft.faces.context.BridgeFacesContext.registerResource(BridgeFacesContext.java:613)
at com.icesoft.faces.component.outputresource.OutputResource.getResource(OutputResource.java:85)
at com.icesoft.faces.component.outputresource.OutputResourceRenderer.encodeBegin(OutputResourceRenderer.java:24)
at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:813)
at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.encodeParentAndChildren(DomBasicRenderer.java:356)
at com.icesoft.faces.renderkit.dom_html_basic.GridRenderer.encodeChildren(GridRenderer.java:208)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.encodeParentAndChildren(DomBasicRenderer.java:358)
at com.icesoft.faces.renderkit.dom_html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:96)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.encodeParentAndChildren(DomBasicRenderer.java:358)
at com.icesoft.faces.renderkit.dom_html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:96)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.encodeParentAndChildren(DomBasicRenderer.java:358)
at com.icesoft.faces.renderkit.dom_html_basic.DomBasicRenderer.encodeParentAndChildren(DomBasicRenderer.java:365)
at com.icesoft.faces.renderkit.dom_html_basic.GroupRenderer.encodeChildren(GroupRenderer.java:96)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at com.icesoft.faces.component.util.CustomComponentUtils.renderChild(CustomComponentUtils.java:339)
at com.icesoft.faces.component.panelstack.PanelStackRenderer.encodeChildren(PanelStackRenderer.java:116)
at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:837)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:517)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:522)
at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:492)
at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:153)
at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
... 28 more
Caused by: java.net.URISyntaxException: Illegal character in path at index 33: /block/resource/MjAyNjQwNTE1MA==/"icefaces.jpg"
at java.net.URI$Parser.fail(URI.java:2816)
at java.net.URI$Parser.checkChars(URI.java:2989)
at java.net.URI$Parser.parseHierarchical(URI.java:3073)
at java.net.URI$Parser.parse(URI.java:3031)
at java.net.URI.<init>(URI.java:578)
at java.net.URI.create(URI.java:840)
... 63 more
Removed the file quotes in the encoding, but still didn't work for file names with special characters:
Could not find resource at /component-showcase-trunk/block/resource/Mzc4NDI4NjUw/Testingday_20_5__(a)_200907141213.pdf
Seems it is not just a matter of changing the encoding methods. There is some major misunderstanding (or neglect) in the code about URL encoding and pattern matching. (Not only the processes involved, but also the related classes like URLEncoder, URI, Pattern, etc.)
Fixed. See screenshots 01 to 04.
Bugs caused by inappropriate URL encoding, URL pattern matching and URI method usage.
Changed to:
- use UTF encoding
- encode space character to %20
- use Unicode escape sequences for pattern matching
- use raw path from URI for outputting link
Have you tried € or £ or all German umlauts for example? I can see ue and @, which is not enough IMHO. Have you tested it with IE too? I'm asking because what I can see are attached screenshots only.
Tested using file name €£ěščřžýáíéĚŠČŘŽÝÁÉ. The file name is displayed as €£?š??žýáíé?Š??ŽÝÁÉ on web page and as ¬£a~ýáíé`__}ÝÁÉ on save file dialog. See screenshot 05. (Same on IE.) So some characters are not working. Need to figure out how to fix this.
This filename is working correctly in Safari on the Mac. This indicates that the unicode conversion is correct and difficulties saving certain filenames may actually be browser or operating system dependent problems.
Yip, can you attach your .war file that allows FileUpload filenames to be tested to this JIRA?
It would be nice to have some testing war. So, I can test it under our environment. I can cover Firefox, IE, Safari and Opera on Mac, Linux and Windows (where available). I can also test it under different environments - I mean different OS languages, localization, fonts, etc.
See screenshots 06 and 07.
Fixed file name display on web page by using Unicode escape sequences in file name in backing bean, i.e., fileName = "€£\u011Bš\u010D\u0159žýáíé\u011AŠ\u010C\u0158ŽÝÁÉ";
However, in FF, the file name in the save file dialog still doesn't match exactly; in IE, you get an error "... cannot download ... not able to open Internet site ..."
.war file attached.
See screenshots 08 - 10.
Added encoding of content disposition file name. This requires browser detection on the server side. Encoding for IE and Firefox is based on suggestion above from Robert Vojta. Other browsers and encoding methods may have to be added later case by case.
New .war file attached.
Hi Yip, thanks for testing war. I'll test it tomorrow.
I think it should be good to change behavior for Firefox & Operate to this one ...
http://greenbytes.de/tech/tc2231/#attwithfn2231utf8
Content-Disposition: attachment; filename*=UTF-8''foo-a%cc%88.html
... my solution for Firefox works because of wrong implementation in FF - probably will be fixed in the future. And I choosed it because I was able to add anything after "filename=" in OutputResource, but I wasn't able to use "attachment; filename*=" (see * before =) with OutputResource without source code modification. And as you're fixing it directly in the source code, it would be nice to have cleaner and more stable approach.
Mistake, second line s/Operate/Opera/, sorry.
Added detection for Opera. Changed encoding method for Firefox and Opera. (Required changes to other parts of OutputResource and ResourceDispatcher as well.)
New .war file attached.
Test instructions for QA:
In the component showcase demo for Download Resources, try the following names as the download file name:
€£ěščřžýáíéĚŠČŘŽÝÁÉ
Français+Español
Testingday_20_5__(a)_200907141213
The string ü@foo-bar
foo-%41
foo-ä
foo-ä-€
The popup save file dialog should display the proper file names on both IE and Firefox.
Also, try serving from Unix and downloading on Windows, and vice versa.
You can look at http://greenbytes.de/tech/tc2231/ for more info how this can be done. The problem is that there's no standard way how to do this for all browsers and you have to handle separate versions of IE as well I've workaround with the following code in Java and I pass function return value to OutputResource filename parameter. This works for IE / Firefox ...
private static String encodeForIE(String fileName)
{ /* * http://greenbytes.de/tech/tc2231/#attwithfnrawpctenca * * IE decodes %XY to characters and than if it detects * UTF-8 stream (after decoding of %XY), than it creates * UTF-8 string. * * We use this behavior to offer correct file name * for download. */ StringBuilder encodedFileName = new StringBuilder(); encodedFileName.append("\""); // ICEfaces 1.7.2 bug encodedFileName.append(URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20")); encodedFileName.append("\""); // ICEfaces 1.7.2 bug return encodedFileName.toString(); }throws UnsupportedEncodingException
private static String encodeForFirefox(String fileName)
throws UnsupportedEncodingException {
/*
*
*
*/
StringBuilder encodedFileName = new StringBuilder();
encodedFileName.append("\""); // ICEfaces 1.7.2 bug
byte[] utf8Bytes = fileName.getBytes("UTF-8");
{ char ch = (char) b; encodedFileName.append(ch); }for (byte b : utf8Bytes)
encodedFileName.append("\""); // ICEfaces 1.7.2 bug
return encodedFileName.toString();
}