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