View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.codec.net;
19  
20  import static org.junit.Assert.assertEquals;
21  import static org.junit.Assert.assertNull;
22  import static org.junit.Assert.fail;
23  
24  import java.nio.charset.UnsupportedCharsetException;
25  
26  import org.apache.commons.codec.CharEncoding;
27  import org.apache.commons.codec.Charsets;
28  import org.apache.commons.codec.DecoderException;
29  import org.apache.commons.codec.EncoderException;
30  import org.junit.Ignore;
31  import org.junit.Test;
32  
33  /**
34   * Quoted-printable codec test cases
35   *
36   * @version $Id: QuotedPrintableCodecTest.java 1429868 2013-01-07 16:08:05Z ggregory $
37   */
38  public class QuotedPrintableCodecTest {
39  
40      static final int SWISS_GERMAN_STUFF_UNICODE [] = {
41          0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
42      };
43  
44      static final int RUSSIAN_STUFF_UNICODE [] = {
45          0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
46          0x432, 0x435, 0x442
47      };
48  
49      private String constructString(final int [] unicodeChars) {
50          final StringBuilder buffer = new StringBuilder();
51          if (unicodeChars != null) {
52              for (final int unicodeChar : unicodeChars) {
53                  buffer.append((char)unicodeChar);
54              }
55          }
56          return buffer.toString();
57      }
58  
59      @Test
60      public void testUTF8RoundTrip() throws Exception {
61  
62          final String ru_msg = constructString(RUSSIAN_STUFF_UNICODE);
63          final String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE);
64  
65          final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
66  
67          assertEquals(
68              "=D0=92=D1=81=D0=B5=D0=BC_=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D1=82",
69          qpcodec.encode(ru_msg, CharEncoding.UTF_8)
70          );
71          assertEquals("Gr=C3=BCezi_z=C3=A4m=C3=A4", qpcodec.encode(ch_msg, CharEncoding.UTF_8));
72  
73          assertEquals(ru_msg, qpcodec.decode(qpcodec.encode(ru_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
74          assertEquals(ch_msg, qpcodec.decode(qpcodec.encode(ch_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
75      }
76  
77      @Test
78      public void testBasicEncodeDecode() throws Exception {
79          final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
80          final String plain = "= Hello there =\r\n";
81          final String encoded = qpcodec.encode(plain);
82          assertEquals("Basic quoted-printable encoding test",
83              "=3D Hello there =3D=0D=0A", encoded);
84          assertEquals("Basic quoted-printable decoding test",
85              plain, qpcodec.decode(encoded));
86      }
87  
88      @Test
89      public void testSafeCharEncodeDecode() throws Exception {
90          final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
91          final String plain = "abc123_-.*~!@#$%^&()+{}\"\\;:`,/[]";
92          final String encoded = qpcodec.encode(plain);
93          assertEquals("Safe chars quoted-printable encoding test",
94              plain, encoded);
95          assertEquals("Safe chars quoted-printable decoding test",
96              plain, qpcodec.decode(encoded));
97      }
98  
99  
100     @Test
101     public void testUnsafeEncodeDecode() throws Exception {
102         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
103         final String plain = "=\r\n";
104         final String encoded = qpcodec.encode(plain);
105         assertEquals("Unsafe chars quoted-printable encoding test",
106             "=3D=0D=0A", encoded);
107         assertEquals("Unsafe chars quoted-printable decoding test",
108             plain, qpcodec.decode(encoded));
109     }
110 
111     @Test
112     public void testEncodeDecodeNull() throws Exception {
113         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
114         assertNull("Null string quoted-printable encoding test",
115             qpcodec.encode((String)null));
116         assertNull("Null string quoted-printable decoding test",
117             qpcodec.decode((String)null));
118     }
119 
120 
121     @Test
122     public void testDecodeInvalid() throws Exception {
123         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
124         try {
125             qpcodec.decode("=");
126             fail("DecoderException should have been thrown");
127         } catch (final DecoderException e) {
128             // Expected. Move on
129         }
130         try {
131             qpcodec.decode("=A");
132             fail("DecoderException should have been thrown");
133         } catch (final DecoderException e) {
134             // Expected. Move on
135         }
136         try {
137             qpcodec.decode("=WW");
138             fail("DecoderException should have been thrown");
139         } catch (final DecoderException e) {
140             // Expected. Move on
141         }
142     }
143 
144     @Test
145     public void testEncodeNull() throws Exception {
146         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
147         final byte[] plain = null;
148         final byte[] encoded = qpcodec.encode(plain);
149         assertEquals("Encoding a null string should return null",
150             null, encoded);
151     }
152 
153     @Test
154     public void testEncodeUrlWithNullBitSet() throws Exception {
155         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
156         final String plain = "1+1 = 2";
157         final String encoded = new String(QuotedPrintableCodec.
158             encodeQuotedPrintable(null, plain.getBytes(Charsets.UTF_8)));
159         assertEquals("Basic quoted-printable encoding test",
160             "1+1 =3D 2", encoded);
161         assertEquals("Basic quoted-printable decoding test",
162             plain, qpcodec.decode(encoded));
163 
164     }
165 
166     @Test
167     public void testDecodeWithNullArray() throws Exception {
168         final byte[] plain = null;
169         final byte[] result = QuotedPrintableCodec.decodeQuotedPrintable( plain );
170         assertEquals("Result should be null", null, result);
171     }
172 
173     @Test
174     public void testEncodeStringWithNull() throws Exception {
175         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
176         final String test = null;
177         final String result = qpcodec.encode( test, "charset" );
178         assertEquals("Result should be null", null, result);
179     }
180 
181     @Test
182     public void testDecodeStringWithNull() throws Exception {
183         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
184         final String test = null;
185         final String result = qpcodec.decode( test, "charset" );
186         assertEquals("Result should be null", null, result);
187     }
188 
189     @Test
190     public void testEncodeObjects() throws Exception {
191         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
192         final String plain = "1+1 = 2";
193         String encoded = (String) qpcodec.encode((Object) plain);
194         assertEquals("Basic quoted-printable encoding test",
195             "1+1 =3D 2", encoded);
196 
197         final byte[] plainBA = plain.getBytes(Charsets.UTF_8);
198         final byte[] encodedBA = (byte[]) qpcodec.encode((Object) plainBA);
199         encoded = new String(encodedBA);
200         assertEquals("Basic quoted-printable encoding test",
201             "1+1 =3D 2", encoded);
202 
203         final Object result = qpcodec.encode((Object) null);
204         assertEquals( "Encoding a null Object should return null", null, result);
205 
206         try {
207             final Object dObj = new Double(3.0);
208             qpcodec.encode( dObj );
209             fail( "Trying to url encode a Double object should cause an exception.");
210         } catch (final EncoderException ee) {
211             // Exception expected, test segment passes.
212         }
213     }
214 
215     @Test(expected=UnsupportedCharsetException.class)
216     public void testInvalidEncoding() {
217         new QuotedPrintableCodec("NONSENSE");
218     }
219 
220     @Test
221     public void testDecodeObjects() throws Exception {
222         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
223         final String plain = "1+1 =3D 2";
224         String decoded = (String) qpcodec.decode((Object) plain);
225         assertEquals("Basic quoted-printable decoding test",
226             "1+1 = 2", decoded);
227 
228         final byte[] plainBA = plain.getBytes(Charsets.UTF_8);
229         final byte[] decodedBA = (byte[]) qpcodec.decode((Object) plainBA);
230         decoded = new String(decodedBA);
231         assertEquals("Basic quoted-printable decoding test",
232             "1+1 = 2", decoded);
233 
234         final Object result = qpcodec.decode((Object) null);
235         assertEquals( "Decoding a null Object should return null", null, result);
236 
237         try {
238             final Object dObj = new Double(3.0);
239             qpcodec.decode( dObj );
240             fail( "Trying to url encode a Double object should cause an exception.");
241         } catch (final DecoderException ee) {
242             // Exception expected, test segment passes.
243         }
244     }
245 
246     @Test
247     public void testDefaultEncoding() throws Exception {
248         final String plain = "Hello there!";
249         final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec("UnicodeBig");
250         qpcodec.encode(plain); // To work around a weird quirk in Java 1.2.2
251         final String encoded1 = qpcodec.encode(plain, "UnicodeBig");
252         final String encoded2 = qpcodec.encode(plain);
253         assertEquals(encoded1, encoded2);
254     }
255 
256     @Test
257     @Ignore
258     /**
259      * The QuotedPrintableCodec documentation states that this is not supported.
260      *
261      * @throws Exception
262      * @see <a href="https://issues.apache.org/jira/browse/CODEC-121">CODEC-121</a>
263      */
264     public void testSoftLineBreakDecode() throws Exception {
265         final String qpdata = "If you believe that truth=3Dbeauty, then surely=20=\r\nmathematics is the most beautiful branch of philosophy.";
266         final String expected = "If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy.";
267         assertEquals(expected, new QuotedPrintableCodec().decode(qpdata));
268     }
269 
270     @Test
271     @Ignore
272     /**
273      * The QuotedPrintableCodec documentation states that this is not supported.
274      *
275      * @throws Exception
276      * @see <a href="https://issues.apache.org/jira/browse/CODEC-121">CODEC-121</a>
277      */
278     public void testSoftLineBreakEncode() throws Exception {
279         final String qpdata = "If you believe that truth=3Dbeauty, then surely=20=\r\nmathematics is the most beautiful branch of philosophy.";
280         final String expected = "If you believe that truth=beauty, then surely mathematics is the most beautiful branch of philosophy.";
281         assertEquals(qpdata, new QuotedPrintableCodec().encode(expected));
282     }
283 }