001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017
018 package org.apache.commons.codec.net;
019
020 import static org.junit.Assert.assertEquals;
021 import static org.junit.Assert.assertNull;
022 import static org.junit.Assert.fail;
023
024 import java.nio.charset.UnsupportedCharsetException;
025
026 import org.apache.commons.codec.CharEncoding;
027 import org.apache.commons.codec.Charsets;
028 import org.apache.commons.codec.DecoderException;
029 import org.apache.commons.codec.EncoderException;
030 import org.junit.Ignore;
031 import org.junit.Test;
032
033 /**
034 * Quoted-printable codec test cases
035 *
036 * @version $Id: QuotedPrintableCodecTest.html 889935 2013-12-11 05:05:13Z ggregory $
037 */
038 public class QuotedPrintableCodecTest {
039
040 static final int SWISS_GERMAN_STUFF_UNICODE [] = {
041 0x47, 0x72, 0xFC, 0x65, 0x7A, 0x69, 0x5F, 0x7A, 0xE4, 0x6D, 0xE4
042 };
043
044 static final int RUSSIAN_STUFF_UNICODE [] = {
045 0x412, 0x441, 0x435, 0x43C, 0x5F, 0x43F, 0x440, 0x438,
046 0x432, 0x435, 0x442
047 };
048
049 private String constructString(final int [] unicodeChars) {
050 final StringBuilder buffer = new StringBuilder();
051 if (unicodeChars != null) {
052 for (final int unicodeChar : unicodeChars) {
053 buffer.append((char)unicodeChar);
054 }
055 }
056 return buffer.toString();
057 }
058
059 @Test
060 public void testUTF8RoundTrip() throws Exception {
061
062 final String ru_msg = constructString(RUSSIAN_STUFF_UNICODE);
063 final String ch_msg = constructString(SWISS_GERMAN_STUFF_UNICODE);
064
065 final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
066
067 assertEquals(
068 "=D0=92=D1=81=D0=B5=D0=BC_=D0=BF=D1=80=D0=B8=D0=B2=D0=B5=D1=82",
069 qpcodec.encode(ru_msg, CharEncoding.UTF_8)
070 );
071 assertEquals("Gr=C3=BCezi_z=C3=A4m=C3=A4", qpcodec.encode(ch_msg, CharEncoding.UTF_8));
072
073 assertEquals(ru_msg, qpcodec.decode(qpcodec.encode(ru_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
074 assertEquals(ch_msg, qpcodec.decode(qpcodec.encode(ch_msg, CharEncoding.UTF_8), CharEncoding.UTF_8));
075 }
076
077 @Test
078 public void testBasicEncodeDecode() throws Exception {
079 final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
080 final String plain = "= Hello there =\r\n";
081 final String encoded = qpcodec.encode(plain);
082 assertEquals("Basic quoted-printable encoding test",
083 "=3D Hello there =3D=0D=0A", encoded);
084 assertEquals("Basic quoted-printable decoding test",
085 plain, qpcodec.decode(encoded));
086 }
087
088 @Test
089 public void testSafeCharEncodeDecode() throws Exception {
090 final QuotedPrintableCodec qpcodec = new QuotedPrintableCodec();
091 final String plain = "abc123_-.*~!@#$%^&()+{}\"\\;:`,/[]";
092 final String encoded = qpcodec.encode(plain);
093 assertEquals("Safe chars quoted-printable encoding test",
094 plain, encoded);
095 assertEquals("Safe chars quoted-printable decoding test",
096 plain, qpcodec.decode(encoded));
097 }
098
099
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 }