View Javadoc

1   /*
2    * Copyright 2007 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.myfaces.shared.renderkit.html.util;
18  
19  import java.io.ByteArrayOutputStream;
20  import java.io.CharArrayWriter;
21  import java.io.IOException;
22  import java.io.OutputStreamWriter;
23  import java.io.UnsupportedEncodingException;
24  import java.nio.ByteBuffer;
25  import java.nio.charset.Charset;
26  
27  import org.apache.myfaces.test.base.AbstractJsfTestCase;
28  
29  /**
30   * <code>HTMLEncoderTest</code> tests <code>org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder</code>.
31   */
32  public class HTMLEncoderTest extends AbstractJsfTestCase {
33    private String stringNoSpecialChars = "Hello, this is MyFaces speaking!";
34    private String stringNoSpecialCharsEncoded = "Hello, this is MyFaces speaking!";
35    private String stringNoSpecialCharsEncodedPartial = "lo, this is MyFaces speakin";
36    private String stringSpecialChars1 = "<\"Hello\", this is MyFaces speaking!>";
37    private String stringSpecialChars1Encoded = "&lt;&quot;Hello&quot;, this is MyFaces speaking!&gt;";
38    private String stringSpecialChars2 = "Hello & this is MyFaces speaking!>";
39    private String stringSpecialChars2Encoded = "Hello &amp; this is MyFaces speaking!&gt;";
40    private String stringLineBreak = "Hell\u00F6\nthis is MyFaces speaking!>";
41    private String stringLineBreakEncoded1 = "Hell&ouml;<br/>this is MyFaces speaking!&gt;";
42    private String stringLineBreakEncoded2 = "Hell&ouml;\nthis is MyFaces speaking!&gt;";
43    private String stringLineBreakEncoded2Partial = "&ouml;\nthis is MyFaces speaking!";
44    private String stringBlanks = "<Hello   this is MyFaces speaking!>";
45    private String stringBlanksEncoded = "&lt;Hello   this is MyFaces speaking!&gt";
46  
47    public HTMLEncoderTest(String name) {
48      super(name);
49    }
50  
51    /**
52     * Test method for
53     * {@link org.apache.myfaces.shared.renderkit.html.util.HTMLEncoder#encode(String)}.
54     */
55    public void testEncodeStringNoSpecialChars() {
56      String encodedStr = HTMLEncoder.encode(stringNoSpecialChars);
57      assertEquals(stringNoSpecialCharsEncoded, encodedStr);
58    }
59  
60    public void testEncodeStringSpecialChars1() {
61      String encodedStr = HTMLEncoder.encode(stringSpecialChars1);
62      assertEquals(stringSpecialChars1Encoded, encodedStr);
63    }
64  
65    public void testEncodeStringSpecialChars2() {
66      String encodedStr = HTMLEncoder.encode(stringSpecialChars2);
67      assertEquals(stringSpecialChars2Encoded, encodedStr);
68    }
69  
70    public void testEncodeStringLineBreak1() {
71      String encodedStr = HTMLEncoder.encode(stringLineBreak, true);
72      assertEquals(stringLineBreakEncoded1, encodedStr);
73    }
74  
75    public void testEncodeStringLineBreak2() {
76      String encodedStr = HTMLEncoder.encode(stringLineBreak, false);
77      assertEquals(stringLineBreakEncoded2, encodedStr);
78    }
79  
80    public void testEncodeStringEmpty() {
81      String encodedStr = HTMLEncoder.encode("");
82      assertEquals("", encodedStr);
83    }
84  
85    public void testEncodeStringNull() {
86      String encodedStr = HTMLEncoder.encode(null);
87      assertEquals("", encodedStr);
88    }
89  
90    public void testEncodeArrayNoSpecialChars() {
91      try {
92        CharArrayWriter writer = new CharArrayWriter();
93        char[] source = stringNoSpecialChars.toCharArray();
94        HTMLEncoder.encode(source, 0, source.length, writer);
95        assertEquals(stringNoSpecialCharsEncoded.toCharArray(), writer.toCharArray());
96      } catch (IOException e) {
97        fail(e.getMessage());
98      }
99    }
100 
101   public void testEncodeArrayNoSpecialCharsPartial() {
102     try {
103       CharArrayWriter writer = new CharArrayWriter();
104       char[] source = stringNoSpecialChars.toCharArray();
105       HTMLEncoder.encode(source, 3, source.length - 5, writer);
106       assertEquals(stringNoSpecialCharsEncodedPartial.toCharArray(), writer.toCharArray());
107     } catch (IOException e) {
108       fail(e.getMessage());
109     }
110   }
111 
112   public void testEncodeArraySpecialChars1() {
113     try {
114       CharArrayWriter writer = new CharArrayWriter();
115       char[] source = stringSpecialChars1.toCharArray();
116       HTMLEncoder.encode(source, 0, source.length, writer);
117       assertEquals(stringSpecialChars1Encoded.toCharArray(), writer.toCharArray());
118     } catch (IOException e) {
119       fail(e.getMessage());
120     }
121   }
122 
123   public void testEncodeArraySpecialChars2() {
124     try {
125       CharArrayWriter writer = new CharArrayWriter();
126       char[] source = stringSpecialChars2.toCharArray();
127       HTMLEncoder.encode(source, 0, source.length, writer);
128       assertEquals(stringSpecialChars2Encoded.toCharArray(), writer.toCharArray());
129     } catch (IOException e) {
130       fail(e.getMessage());
131     }
132   }
133 
134   public void testEncodeArrayEmpty() {
135     try {
136       CharArrayWriter writer = new CharArrayWriter();
137       HTMLEncoder.encode(new char[]{}, 0, 1, writer);
138       assertEquals(new char[]{}, writer.toCharArray());
139     } catch (IOException e) {
140       fail(e.getMessage());
141     }
142   }
143 
144   public void testEncodeArrayNull() {
145     try {
146       CharArrayWriter writer = new CharArrayWriter();
147       HTMLEncoder.encode(null, 0, 0, writer);
148       assertEquals(new char[]{}, writer.toCharArray());
149     } catch (IOException e) {
150       fail(e.getMessage());
151     }
152   }
153 
154   public void testEncodeArrayWrongIndex1() {
155     try {
156       CharArrayWriter writer = new CharArrayWriter();
157       char[] source = stringSpecialChars2.toCharArray();
158       HTMLEncoder.encode(source, 0, source.length - 100, writer);
159       assertEquals(new char[]{}, writer.toCharArray());
160     } catch (IOException e) {
161       fail(e.getMessage());
162     }
163   }
164 
165   public void testEncodeArrayWrongIndex2() {
166     try {
167       CharArrayWriter writer = new CharArrayWriter();
168       char[] source = stringSpecialChars2.toCharArray();
169       HTMLEncoder.encode(source, -100, source.length, writer);
170       assertEquals(stringSpecialChars2Encoded.toCharArray(), writer.toCharArray());
171     } catch (IOException e) {
172       fail(e.getMessage());
173     }
174   }
175 
176   public void testEncodeArrayWrongIndex3() {
177     try {
178       CharArrayWriter writer = new CharArrayWriter();
179       char[] source = stringSpecialChars2.toCharArray();
180       HTMLEncoder.encode(source, 100000, source.length, writer);
181       assertEquals(new char[]{}, writer.toCharArray());
182     } catch (IOException e) {
183       fail(e.getMessage());
184     }
185   }
186 
187   public void testEncodeArrayLineBreak1() {
188     try {
189       CharArrayWriter writer = new CharArrayWriter();
190       char[] source = stringLineBreak.toCharArray();
191       HTMLEncoder.encode(source, 0, source.length, true, writer);
192       assertEquals(stringLineBreakEncoded1.toCharArray(), writer.toCharArray());
193     } catch (IOException e) {
194       fail(e.getMessage());
195     }
196   }
197 
198   public void testEncodeArrayLineBreak2() {
199     try {
200       CharArrayWriter writer = new CharArrayWriter();
201       char[] source = stringLineBreak.toCharArray();
202       HTMLEncoder.encode(source, 0, source.length, false, writer);
203       assertEquals(stringLineBreakEncoded2.toCharArray(), writer.toCharArray());
204     } catch (IOException e) {
205       fail(e.getMessage());
206     }
207   }
208 
209   public void testEncodeArrayLineBreak2WrongIndex() {
210     try {
211       CharArrayWriter writer = new CharArrayWriter();
212       char[] source = stringLineBreak.toCharArray();
213       HTMLEncoder.encode(source, 0, source.length + 5, false, writer);
214       assertEquals(stringLineBreakEncoded2.toCharArray(), writer.toCharArray());
215     } catch (IOException e) {
216       fail(e.getMessage());
217     }
218   }
219 
220   public void testEncodeArrayLineBreakPartial() {
221     try {
222       CharArrayWriter writer = new CharArrayWriter();
223       char[] source = stringLineBreak.toCharArray();
224       HTMLEncoder.encode(source, 4, source.length - 5, writer);
225       char[] expected = stringLineBreakEncoded2Partial.toCharArray();
226       assertEquals(expected, writer.toCharArray());
227     } catch (IOException e) {
228       fail(e.getMessage());
229     }
230   }
231 
232   private void assertEquals(char[] expected, char[] actual) {
233     if ((expected == null ^ actual == null) || expected.length != actual.length) {
234       fail();
235     }
236     for (int i = 0; i < expected.length; i++) {
237       assertEquals(expected[i], actual[i]);
238     }
239   }
240   
241   public void testSimpleWriteURIAttribute() throws Exception
242   {
243       String cad1 = "http://myfaces.apache.org/hello.jsf?key1=val&key2=val2#id";
244       String cad2 = "http://myfaces.apache.org/hello.jsf?key1=val&amp;key2=val2#id";
245       String cad3 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
246       assertEquals(cad2, cad3);      
247   }
248   
249   public void testUsAsciiEscapedCharactersBeforeQuery() throws Exception
250   {
251       // Escape
252       // - From %00 to %20, 
253       // - <"> %22, "%" %25
254       // - "<" %3C, ">" %3E,
255       // - "\" %5C, "^" %5E, "`" %60 
256       // - "{" %7B, "|" %7C, "}" %7D
257       // - From %7F ad infinitum
258       String cad1 = "?key=\"%<>\\`{|}^\n "; //Omit %
259       String cad2 = "?key=%22%25%3C%3E%5C%60%7B%7C%7D%5E%0A%20";
260       String cad3 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
261       assertEquals(cad2, cad3);
262       
263       String cad4 = "\"%<>\\`{|}^\n ";
264       String cad5 = "%22%25%3C%3E%5C%60%7B%7C%7D%5E%0A%20";
265       String cad6 = HTMLEncoder.encodeURIAttribute(cad4,"UTF-8");
266       assertEquals(cad5, cad6);
267       
268       
269   }
270   
271   public void testUsAsciiEscapedCharactersBeforeQueryLowerCase() throws Exception
272   {
273       // Escape
274       // - From %00 to %20, 
275       // - <"> %22, "%" %25
276       // - "<" %3C, ">" %3E,
277       // - "\" %5C, "^" %5E, "`" %60 
278       // - "{" %7B, "|" %7C, "}" %7D
279       // - From %7F ad infinitum
280       String cad1 = "?key=\"%<>\\`{|}^\n "; //Omit %
281       String cad2 = "?key=%22%25%3c%3e%5c%60%7b%7c%7d%5e%0a%20";
282       String cad3 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
283       assertEquals(cad2.substring(0,5) + cad2.substring(5).toUpperCase(), cad3);
284       
285       String cad4 = "\"%<>\\`{|}^\n ";
286       String cad5 = "%22%25%3c%3e%5c%60%7b%7c%7d%5e%0a%20";
287       String cad6 = HTMLEncoder.encodeURIAttribute(cad4,"UTF-8");
288       assertEquals(cad5.substring(0,5) + cad5.substring(5).toUpperCase(), cad6);
289       
290   }  
291   
292   public void testWriteNonUsAsciiOnURIAttribute() throws Exception
293   {
294       // Character ü in ISO-8859-1 is %FC but on UTF-8 is %C3%BC. In this case,
295       // it should encode as %C3%BC
296 	  byte [] array = new byte[]{(byte)0xFC};
297       String cad1 = new String(array,"ISO-8859-1");//+(char)0xC3BC;//"http://myfaces.apache.org/heüll o.jsf?key=val#id";
298       String cad2 = "%C3%BC";//"http://myfaces.apache.org/he%FCll%20o.jsf?key=val#id";
299       String cad3 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
300       assertEquals(cad2, cad3);
301 
302   }
303   
304   public void testReservedCharactersOnURIAttribute() throws Exception
305   {
306       //Reserved
307       // Reserved characters (should not be percent-encoded)
308       // reserved    = gen-delims / sub-delims
309       // gen-delims  = ":" / "/" / "?" / "#" / "[" / "]" / "@"
310       //               %3A   %2F   %3F   %23   %5B   %5D   %40
311       // sub-delims  = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
312       //               %21   %24   %26   %27   %28   %29   %2A   %2B   %2C   %3B   %3D
313       
314       String cad1 = "?key=:/[]@!$'()*+,;="; //Omit &
315       String cad2 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
316       assertEquals(cad1, cad2);
317       
318       String cad7 = ":/[]@!$&'()*+,;=";
319       String cad8 = HTMLEncoder.encodeURIAttribute(cad7,"UTF-8");
320       assertEquals(cad7, cad8);
321   }
322 
323   public void testNonEncodedCharactersOnURIAttribute() throws Exception
324   {
325       // "... for consistency, percent-encoded octets in the ranges of ALPHA
326       // (%41-%5A and %61-%7A), DIGIT (%30-%39), hyphen (%2D), period (%2E),
327       // underscore (%5F), or tilde (%7E) should not be created by URI
328       // producers...."
329       String cad1 = "?key=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
330       String cad2 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
331       assertEquals(cad1, cad2);
332       
333       String cad3 = "#somefile?key=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
334       String cad4 = HTMLEncoder.encodeURIAttribute(cad3,"UTF-8");
335       assertEquals(cad3, cad4);
336       
337       String cad5 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
338       String cad6 = HTMLEncoder.encodeURIAttribute(cad5,"UTF-8");
339       assertEquals(cad5, cad6);
340   }
341 
342   public void testWriteURIAttribute() throws Exception
343   {
344       //Note char 256 or 0x100 should not be passed or percent encoded, because it is not
345       //valid for URIs.
346 	  byte [] array11 = new byte[]{(byte) 0xC2,(byte) 0xA1,(byte) 0xC2,(byte) 0xA2,
347 			  (byte) 0xC2,(byte) 0xA3,(byte) 0xC2,(byte) 0xA4,(byte) 0xC2,(byte) 0xA5,
348 			  (byte) 0xC2,(byte) 0xA6,(byte) 0xC2,(byte) 0xA7,(byte) 0xC2,(byte) 0xA8,
349 			  (byte) 0xC2,(byte) 0xA9,(byte) 0xC2,(byte) 0xAA,(byte) 0xC2,(byte) 0xAB,
350 			  (byte) 0xC2,(byte) 0xAC,(byte) 0xC2,(byte) 0xAD,(byte) 0xC2,(byte) 0xAE,
351 			  (byte) 0xC2,(byte) 0xAF,(byte) 0xC2,(byte) 0xB0,(byte) 0xC2,(byte) 0xB1};
352 	  
353       String cad11 = new String(array11,"UTF-8") + ((char)(0xFF))+((char)(0x100));
354       String cad12 = "%C2%A1%C2%A2%C2%A3%C2%A4%C2%A5%C2%A6%C2%A7%C2%A8%C2%A9%C2%AA%C2%AB%C2%AC%C2%AD"+
355                      "%C2%AE%C2%AF%C2%B0%C2%B1%C3%BF%C4%80";
356       String cad13 = HTMLEncoder.encodeURIAttribute(cad11,"UTF-8");
357       assertEquals(cad12, cad13);
358       
359       String cad1= "?key=" + new String(array11,"UTF-8")+((char)(0xFF))+((char)(0x100));
360       String cad2 = "?key=%C2%A1%C2%A2%C2%A3%C2%A4%C2%A5%C2%A6%C2%A7%C2%A8%C2%A9%C2%AA%C2%AB%C2%AC%C2%AD"+
361                      "%C2%AE%C2%AF%C2%B0%C2%B1%C3%BF%C4%80";
362       String cad3 = HTMLEncoder.encodeURIAttribute(cad1,"UTF-8");
363       assertEquals(cad2, cad3);
364             
365       //String cad14 = "http://myfaces.apache.org/page.jsf?key="+((char)0xFF)+((char)0x100);
366       //String cad15 = HTMLEncoder.encodeURIAttribute(cad14,false);
367       //assertEquals(cad14,cad15);
368   }
369     
370 }