1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007 Esmertec AG.
3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2007 The Android Open Source Project
4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License");
6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License.
7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at
8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *      http://www.apache.org/licenses/LICENSE-2.0
10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd *
11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software
12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS,
13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and
15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License.
16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.mmslib.pdu;
19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.ByteArrayOutputStream;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class QuotedPrintable {
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static byte ESCAPE_CHAR = '=';
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Decodes an array quoted-printable characters into an array of original bytes.
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Escaped characters are converted back to their original representation.
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * <p>
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * This function implements a subset of
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * quoted-printable encoding specification (rule #1 and rule #2)
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * as defined in RFC 1521.
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * </p>
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param bytes array of quoted-printable characters
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return array of original bytes,
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *         null if quoted-printable decoding is unsuccessful.
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static final byte[] decodeQuotedPrintable(byte[] bytes) {
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (bytes == null) {
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            return null;
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        for (int i = 0; i < bytes.length; i++) {
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            int b = bytes[i];
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (b == ESCAPE_CHAR) {
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                try {
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if ('\r' == (char) bytes[i + 1] &&
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            '\n' == (char) bytes[i + 2]) {
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        i += 2;
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        continue;
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    int u = Character.digit((char) bytes[++i], 16);
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    int l = Character.digit((char) bytes[++i], 16);
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if (u == -1 || l == -1) {
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        return null;
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    buffer.write((char) ((u << 4) + l));
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                } catch (ArrayIndexOutOfBoundsException e) {
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    return null;
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                buffer.write(b);
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return buffer.toByteArray();
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
69