1d02a064168ae5c916b977182b764580e601cb084Wink Saville/*
2d02a064168ae5c916b977182b764580e601cb084Wink Saville * Copyright (C) 2007-2008 Esmertec AG.
3d02a064168ae5c916b977182b764580e601cb084Wink Saville * Copyright (C) 2007-2008 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 android.content.ContentResolver;
21d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.content.Context;
22d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.util.Log;
23d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport android.text.TextUtils;
24d02a064168ae5c916b977182b764580e601cb084Wink Saville
25d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.ByteArrayOutputStream;
26d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.FileNotFoundException;
27d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.IOException;
28d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.io.InputStream;
29d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.util.Arrays;
30d02a064168ae5c916b977182b764580e601cb084Wink Savilleimport java.util.HashMap;
31d02a064168ae5c916b977182b764580e601cb084Wink Saville
32d02a064168ae5c916b977182b764580e601cb084Wink Savillepublic class PduComposer {
33d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
34d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Address type.
35d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
36d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_PHONE_NUMBER_ADDRESS_TYPE = 1;
37d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_EMAIL_ADDRESS_TYPE = 2;
38d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_IPV4_ADDRESS_TYPE = 3;
39d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_IPV6_ADDRESS_TYPE = 4;
40d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_UNKNOWN_ADDRESS_TYPE = 5;
41d02a064168ae5c916b977182b764580e601cb084Wink Saville
42d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
43d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Address regular expression string.
44d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
45d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String REGEXP_PHONE_NUMBER_ADDRESS_TYPE = "\\+?[0-9|\\.|\\-]+";
46d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String REGEXP_EMAIL_ADDRESS_TYPE = "[a-zA-Z| ]*\\<{0,1}[a-zA-Z| ]+@{1}" +
47d02a064168ae5c916b977182b764580e601cb084Wink Saville            "[a-zA-Z| ]+\\.{1}[a-zA-Z| ]+\\>{0,1}";
48d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String REGEXP_IPV6_ADDRESS_TYPE =
49d02a064168ae5c916b977182b764580e601cb084Wink Saville        "[a-fA-F]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
50d02a064168ae5c916b977182b764580e601cb084Wink Saville        "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}\\:{1}" +
51d02a064168ae5c916b977182b764580e601cb084Wink Saville        "[a-fA-F0-9]{4}\\:{1}[a-fA-F0-9]{4}";
52d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String REGEXP_IPV4_ADDRESS_TYPE = "[0-9]{1,3}\\.{1}[0-9]{1,3}\\.{1}" +
53d02a064168ae5c916b977182b764580e601cb084Wink Saville            "[0-9]{1,3}\\.{1}[0-9]{1,3}";
54d02a064168ae5c916b977182b764580e601cb084Wink Saville
55d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
56d02a064168ae5c916b977182b764580e601cb084Wink Saville     * The postfix strings of address.
57d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
58d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String STRING_PHONE_NUMBER_ADDRESS_TYPE = "/TYPE=PLMN";
59d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String STRING_IPV4_ADDRESS_TYPE = "/TYPE=IPV4";
60d02a064168ae5c916b977182b764580e601cb084Wink Saville    static final String STRING_IPV6_ADDRESS_TYPE = "/TYPE=IPV6";
61d02a064168ae5c916b977182b764580e601cb084Wink Saville
62d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
63d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Error values.
64d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
65d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_COMPOSE_SUCCESS = 0;
66d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_COMPOSE_CONTENT_ERROR = 1;
67d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_COMPOSE_FIELD_NOT_SET = 2;
68d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_COMPOSE_FIELD_NOT_SUPPORTED = 3;
69d02a064168ae5c916b977182b764580e601cb084Wink Saville
70d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
71d02a064168ae5c916b977182b764580e601cb084Wink Saville     * WAP values defined in WSP spec.
72d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
73d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int QUOTED_STRING_FLAG = 34;
74d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int END_STRING_FLAG = 0;
75d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int LENGTH_QUOTE = 31;
76d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int TEXT_MAX = 127;
77d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int SHORT_INTEGER_MAX = 127;
78d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int LONG_INTEGER_LENGTH_MAX = 8;
79d02a064168ae5c916b977182b764580e601cb084Wink Saville
80d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
81d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Block size when read data from InputStream.
82d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
83d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private final int PDU_COMPOSER_BLOCK_SIZE = 1024;
84d02a064168ae5c916b977182b764580e601cb084Wink Saville
85d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
86d02a064168ae5c916b977182b764580e601cb084Wink Saville     * The output message.
87d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
88d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected ByteArrayOutputStream mMessage = null;
89d02a064168ae5c916b977182b764580e601cb084Wink Saville
90d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
91d02a064168ae5c916b977182b764580e601cb084Wink Saville     * The PDU.
92d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
93d02a064168ae5c916b977182b764580e601cb084Wink Saville    private GenericPdu mPdu = null;
94d02a064168ae5c916b977182b764580e601cb084Wink Saville
95d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
96d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Current visiting position of the mMessage.
97d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
98d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected int mPosition = 0;
99d02a064168ae5c916b977182b764580e601cb084Wink Saville
100d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
101d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Message compose buffer stack.
102d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
103d02a064168ae5c916b977182b764580e601cb084Wink Saville    private BufferStack mStack = null;
104d02a064168ae5c916b977182b764580e601cb084Wink Saville
105d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
106d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Content resolver.
107d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
108d02a064168ae5c916b977182b764580e601cb084Wink Saville    private final ContentResolver mResolver;
109d02a064168ae5c916b977182b764580e601cb084Wink Saville
110d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
111d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Header of this pdu.
112d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
113d02a064168ae5c916b977182b764580e601cb084Wink Saville    private PduHeaders mPduHeader = null;
114d02a064168ae5c916b977182b764580e601cb084Wink Saville
115d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
116d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Map of all content type
117d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
118d02a064168ae5c916b977182b764580e601cb084Wink Saville    private static HashMap<String, Integer> mContentTypeMap = null;
119d02a064168ae5c916b977182b764580e601cb084Wink Saville
120d02a064168ae5c916b977182b764580e601cb084Wink Saville    static {
121d02a064168ae5c916b977182b764580e601cb084Wink Saville        mContentTypeMap = new HashMap<String, Integer>();
122d02a064168ae5c916b977182b764580e601cb084Wink Saville
123d02a064168ae5c916b977182b764580e601cb084Wink Saville        int i;
124d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (i = 0; i < PduContentTypes.contentTypes.length; i++) {
125d02a064168ae5c916b977182b764580e601cb084Wink Saville            mContentTypeMap.put(PduContentTypes.contentTypes[i], i);
126d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
127d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
128d02a064168ae5c916b977182b764580e601cb084Wink Saville
129d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
130d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Constructor.
131d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
132d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param context the context
133d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param pdu the pdu to be composed
134d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
135d02a064168ae5c916b977182b764580e601cb084Wink Saville    public PduComposer(Context context, GenericPdu pdu) {
136d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPdu = pdu;
137d02a064168ae5c916b977182b764580e601cb084Wink Saville        mResolver = context.getContentResolver();
138d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPduHeader = pdu.getPduHeaders();
139d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack = new BufferStack();
140d02a064168ae5c916b977182b764580e601cb084Wink Saville        mMessage = new ByteArrayOutputStream();
141d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPosition = 0;
142d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
143d02a064168ae5c916b977182b764580e601cb084Wink Saville
144d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
145d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make the message. No need to check whether mandatory fields are set,
146d02a064168ae5c916b977182b764580e601cb084Wink Saville     * because the constructors of outgoing pdus are taking care of this.
147d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
148d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return OutputStream of maked message. Return null if
149d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         the PDU is invalid.
150d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
151d02a064168ae5c916b977182b764580e601cb084Wink Saville    public byte[] make() {
152d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Get Message-type.
153d02a064168ae5c916b977182b764580e601cb084Wink Saville        int type = mPdu.getMessageType();
154d02a064168ae5c916b977182b764580e601cb084Wink Saville
155d02a064168ae5c916b977182b764580e601cb084Wink Saville        /* make the message */
156d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch (type) {
157d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_SEND_REQ:
158d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (makeSendReqPdu() != PDU_COMPOSE_SUCCESS) {
159d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
160d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
161d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
162d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND:
163d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (makeNotifyResp() != PDU_COMPOSE_SUCCESS) {
164d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
165d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
166d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
167d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND:
168d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (makeAckInd() != PDU_COMPOSE_SUCCESS) {
169d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
170d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
171d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
172d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_TYPE_READ_REC_IND:
173d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (makeReadRecInd() != PDU_COMPOSE_SUCCESS) {
174d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return null;
175d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
176d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
177d02a064168ae5c916b977182b764580e601cb084Wink Saville            default:
178d02a064168ae5c916b977182b764580e601cb084Wink Saville                return null;
179d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
180d02a064168ae5c916b977182b764580e601cb084Wink Saville
181d02a064168ae5c916b977182b764580e601cb084Wink Saville        return mMessage.toByteArray();
182d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
183d02a064168ae5c916b977182b764580e601cb084Wink Saville
184d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
185d02a064168ae5c916b977182b764580e601cb084Wink Saville     *  Copy buf to mMessage.
186d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
187d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void arraycopy(byte[] buf, int pos, int length) {
188d02a064168ae5c916b977182b764580e601cb084Wink Saville        mMessage.write(buf, pos, length);
189d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPosition = mPosition + length;
190d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
191d02a064168ae5c916b977182b764580e601cb084Wink Saville
192d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
193d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append a byte to mMessage.
194d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
195d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void append(int value) {
196d02a064168ae5c916b977182b764580e601cb084Wink Saville        mMessage.write(value);
197d02a064168ae5c916b977182b764580e601cb084Wink Saville        mPosition ++;
198d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
199d02a064168ae5c916b977182b764580e601cb084Wink Saville
200d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
201d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append short integer value to mMessage.
202d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
203d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
204d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
205d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendShortInteger(int value) {
206d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
207d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
208d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-integer = OCTET
209d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; Integers in range 0-127 shall be encoded as a one octet value
210d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; with the most significant bit set to one (1xxx xxxx) and with
211d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; the value in the remaining least significant bits.
212d02a064168ae5c916b977182b764580e601cb084Wink Saville         * In our implementation, only low 7 bits are stored and otherwise
213d02a064168ae5c916b977182b764580e601cb084Wink Saville         * bits are ignored.
214d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
215d02a064168ae5c916b977182b764580e601cb084Wink Saville        append((value | 0x80) & 0xff);
216d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
217d02a064168ae5c916b977182b764580e601cb084Wink Saville
218d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
219d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append an octet number between 128 and 255 into mMessage.
220d02a064168ae5c916b977182b764580e601cb084Wink Saville     * NOTE:
221d02a064168ae5c916b977182b764580e601cb084Wink Saville     * A value between 0 and 127 should be appended by using appendShortInteger.
222d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
223d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
224d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
225d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendOctet(int number) {
226d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(number);
227d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
228d02a064168ae5c916b977182b764580e601cb084Wink Saville
229d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
230d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append a short length into mMessage.
231d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
232d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
233d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
234d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendShortLength(int value) {
235d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
236d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
237d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-length = <Any octet 0-30>
238d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
239d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(value);
240d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
241d02a064168ae5c916b977182b764580e601cb084Wink Saville
242d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
243d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append long integer into mMessage. it's used for really long integers.
244d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
245d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
246d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
247d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendLongInteger(long longInt) {
248d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
249d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
250d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Long-integer = Short-length Multi-octet-integer
251d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; The Short-length indicates the length of the Multi-octet-integer
252d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Multi-octet-integer = 1*30 OCTET
253d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; The content octets shall be an unsigned integer value with the
254d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; most significant octet encoded first (big-endian representation).
255d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; The minimum number of octets must be used to encode the value.
256d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
257d02a064168ae5c916b977182b764580e601cb084Wink Saville        int size;
258d02a064168ae5c916b977182b764580e601cb084Wink Saville        long temp = longInt;
259d02a064168ae5c916b977182b764580e601cb084Wink Saville
260d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Count the length of the long integer.
261d02a064168ae5c916b977182b764580e601cb084Wink Saville        for(size = 0; (temp != 0) && (size < LONG_INTEGER_LENGTH_MAX); size++) {
262d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = (temp >>> 8);
263d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
264d02a064168ae5c916b977182b764580e601cb084Wink Saville
265d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Set Length.
266d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendShortLength(size);
267d02a064168ae5c916b977182b764580e601cb084Wink Saville
268d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Count and set the long integer.
269d02a064168ae5c916b977182b764580e601cb084Wink Saville        int i;
270d02a064168ae5c916b977182b764580e601cb084Wink Saville        int shift = (size -1) * 8;
271d02a064168ae5c916b977182b764580e601cb084Wink Saville
272d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (i = 0; i < size; i++) {
273d02a064168ae5c916b977182b764580e601cb084Wink Saville            append((int)((longInt >>> shift) & 0xff));
274d02a064168ae5c916b977182b764580e601cb084Wink Saville            shift = shift - 8;
275d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
276d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
277d02a064168ae5c916b977182b764580e601cb084Wink Saville
278d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
279d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append text string into mMessage.
280d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
281d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
282d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
283d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendTextString(byte[] text) {
284d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
285d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
286d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Text-string = [Quote] *TEXT End-of-string
287d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; If the first character in the TEXT is in the range of 128-255,
288d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; a Quote character must precede it. Otherwise the Quote character
289d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;must be omitted. The Quote is not part of the contents.
290d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
291d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (((text[0])&0xff) > TEXT_MAX) { // No need to check for <= 255
292d02a064168ae5c916b977182b764580e601cb084Wink Saville            append(TEXT_MAX);
293d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
294d02a064168ae5c916b977182b764580e601cb084Wink Saville
295d02a064168ae5c916b977182b764580e601cb084Wink Saville        arraycopy(text, 0, text.length);
296d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(0);
297d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
298d02a064168ae5c916b977182b764580e601cb084Wink Saville
299d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
300d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append text string into mMessage.
301d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
302d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
303d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
304d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendTextString(String str) {
305d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
306d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
307d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Text-string = [Quote] *TEXT End-of-string
308d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; If the first character in the TEXT is in the range of 128-255,
309d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; a Quote character must precede it. Otherwise the Quote character
310d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;must be omitted. The Quote is not part of the contents.
311d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
312d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendTextString(str.getBytes());
313d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
314d02a064168ae5c916b977182b764580e601cb084Wink Saville
315d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
316d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append encoded string value to mMessage.
317d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
318d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
319d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
320d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendEncodedString(EncodedStringValue enStr) {
321d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
322d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From OMA-TS-MMS-ENC-V1_3-20050927-C:
323d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Encoded-string-value = Text-string | Value-length Char-set Text-string
324d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
325d02a064168ae5c916b977182b764580e601cb084Wink Saville        assert(enStr != null);
326d02a064168ae5c916b977182b764580e601cb084Wink Saville
327d02a064168ae5c916b977182b764580e601cb084Wink Saville        int charset = enStr.getCharacterSet();
328d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] textString = enStr.getTextString();
329d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null == textString) {
330d02a064168ae5c916b977182b764580e601cb084Wink Saville            return;
331d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
332d02a064168ae5c916b977182b764580e601cb084Wink Saville
333d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
334d02a064168ae5c916b977182b764580e601cb084Wink Saville         * In the implementation of EncodedStringValue, the charset field will
335d02a064168ae5c916b977182b764580e601cb084Wink Saville         * never be 0. It will always be composed as
336d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Encoded-string-value = Value-length Char-set Text-string
337d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
338d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.newbuf();
339d02a064168ae5c916b977182b764580e601cb084Wink Saville        PositionMarker start = mStack.mark();
340d02a064168ae5c916b977182b764580e601cb084Wink Saville
341d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendShortInteger(charset);
342d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendTextString(textString);
343d02a064168ae5c916b977182b764580e601cb084Wink Saville
344d02a064168ae5c916b977182b764580e601cb084Wink Saville        int len = start.getLength();
345d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.pop();
346d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendValueLength(len);
347d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.copy();
348d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
349d02a064168ae5c916b977182b764580e601cb084Wink Saville
350d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
351d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append uintvar integer into mMessage.
352d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
353d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
354d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
355d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendUintvarInteger(long value) {
356d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
357d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
358d02a064168ae5c916b977182b764580e601cb084Wink Saville         * To encode a large unsigned integer, split it into 7-bit fragments
359d02a064168ae5c916b977182b764580e601cb084Wink Saville         * and place them in the payloads of multiple octets. The most significant
360d02a064168ae5c916b977182b764580e601cb084Wink Saville         * bits are placed in the first octets with the least significant bits
361d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ending up in the last octet. All octets MUST set the Continue bit to 1
362d02a064168ae5c916b977182b764580e601cb084Wink Saville         * except the last octet, which MUST set the Continue bit to 0.
363d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
364d02a064168ae5c916b977182b764580e601cb084Wink Saville        int i;
365d02a064168ae5c916b977182b764580e601cb084Wink Saville        long max = SHORT_INTEGER_MAX;
366d02a064168ae5c916b977182b764580e601cb084Wink Saville
367d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (i = 0; i < 5; i++) {
368d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (value < max) {
369d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
370d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
371d02a064168ae5c916b977182b764580e601cb084Wink Saville
372d02a064168ae5c916b977182b764580e601cb084Wink Saville            max = (max << 7) | 0x7fl;
373d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
374d02a064168ae5c916b977182b764580e601cb084Wink Saville
375d02a064168ae5c916b977182b764580e601cb084Wink Saville        while(i > 0) {
376d02a064168ae5c916b977182b764580e601cb084Wink Saville            long temp = value >>> (i * 7);
377d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = temp & 0x7f;
378d02a064168ae5c916b977182b764580e601cb084Wink Saville
379d02a064168ae5c916b977182b764580e601cb084Wink Saville            append((int)((temp | 0x80) & 0xff));
380d02a064168ae5c916b977182b764580e601cb084Wink Saville
381d02a064168ae5c916b977182b764580e601cb084Wink Saville            i--;
382d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
383d02a064168ae5c916b977182b764580e601cb084Wink Saville
384d02a064168ae5c916b977182b764580e601cb084Wink Saville        append((int)(value & 0x7f));
385d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
386d02a064168ae5c916b977182b764580e601cb084Wink Saville
387d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
388d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append date value into mMessage.
389d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
390d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
391d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
392d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendDateValue(long date) {
393d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
394d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From OMA-TS-MMS-ENC-V1_3-20050927-C:
395d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Date-value = Long-integer
396d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
397d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendLongInteger(date);
398d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
399d02a064168ae5c916b977182b764580e601cb084Wink Saville
400d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
401d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append value length to mMessage.
402d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
403d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
404d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
405d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendValueLength(long value) {
406d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
407d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
408d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Value-length = Short-length | (Length-quote Length)
409d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ; Value length is used to indicate the length of the value to follow
410d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Short-length = <Any octet 0-30>
411d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Length-quote = <Octet 31>
412d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Length = Uintvar-integer
413d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
414d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (value < LENGTH_QUOTE) {
415d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendShortLength((int) value);
416d02a064168ae5c916b977182b764580e601cb084Wink Saville            return;
417d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
418d02a064168ae5c916b977182b764580e601cb084Wink Saville
419d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(LENGTH_QUOTE);
420d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendUintvarInteger(value);
421d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
422d02a064168ae5c916b977182b764580e601cb084Wink Saville
423d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
424d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append quoted string to mMessage.
425d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
426d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
427d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
428d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendQuotedString(byte[] text) {
429d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
430d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
431d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Quoted-string = <Octet 34> *TEXT End-of-string
432d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
433d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;quotation-marks <"> removed.
434d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
435d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(QUOTED_STRING_FLAG);
436d02a064168ae5c916b977182b764580e601cb084Wink Saville        arraycopy(text, 0, text.length);
437d02a064168ae5c916b977182b764580e601cb084Wink Saville        append(END_STRING_FLAG);
438d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
439d02a064168ae5c916b977182b764580e601cb084Wink Saville
440d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
441d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append quoted string to mMessage.
442d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation doesn't check the validity of parameter, since it
443d02a064168ae5c916b977182b764580e601cb084Wink Saville     * assumes that the values are validated in the GenericPdu setter methods.
444d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
445d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected void appendQuotedString(String str) {
446d02a064168ae5c916b977182b764580e601cb084Wink Saville        /*
447d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From WAP-230-WSP-20010705-a:
448d02a064168ae5c916b977182b764580e601cb084Wink Saville         * Quoted-string = <Octet 34> *TEXT End-of-string
449d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;The TEXT encodes an RFC2616 Quoted-string with the enclosing
450d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ;quotation-marks <"> removed.
451d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
452d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendQuotedString(str.getBytes());
453d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
454d02a064168ae5c916b977182b764580e601cb084Wink Saville
455d02a064168ae5c916b977182b764580e601cb084Wink Saville    private EncodedStringValue appendAddressType(EncodedStringValue address) {
456d02a064168ae5c916b977182b764580e601cb084Wink Saville        EncodedStringValue temp = null;
457d02a064168ae5c916b977182b764580e601cb084Wink Saville
458d02a064168ae5c916b977182b764580e601cb084Wink Saville        try {
459d02a064168ae5c916b977182b764580e601cb084Wink Saville            int addressType = checkAddressType(address.getString());
460d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp = EncodedStringValue.copy(address);
461d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (PDU_PHONE_NUMBER_ADDRESS_TYPE == addressType) {
462d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Phone number.
463d02a064168ae5c916b977182b764580e601cb084Wink Saville                temp.appendTextString(STRING_PHONE_NUMBER_ADDRESS_TYPE.getBytes());
464d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else if (PDU_IPV4_ADDRESS_TYPE == addressType) {
465d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Ipv4 address.
466d02a064168ae5c916b977182b764580e601cb084Wink Saville                temp.appendTextString(STRING_IPV4_ADDRESS_TYPE.getBytes());
467d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else if (PDU_IPV6_ADDRESS_TYPE == addressType) {
468d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Ipv6 address.
469d02a064168ae5c916b977182b764580e601cb084Wink Saville                temp.appendTextString(STRING_IPV6_ADDRESS_TYPE.getBytes());
470d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
471d02a064168ae5c916b977182b764580e601cb084Wink Saville        } catch (NullPointerException e) {
472d02a064168ae5c916b977182b764580e601cb084Wink Saville            return null;
473d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
474d02a064168ae5c916b977182b764580e601cb084Wink Saville
475d02a064168ae5c916b977182b764580e601cb084Wink Saville        return temp;
476d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
477d02a064168ae5c916b977182b764580e601cb084Wink Saville
478d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
479d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Append header to mMessage.
480d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
481d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int appendHeader(int field) {
482d02a064168ae5c916b977182b764580e601cb084Wink Saville        switch (field) {
483d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MMS_VERSION:
484d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
485d02a064168ae5c916b977182b764580e601cb084Wink Saville
486d02a064168ae5c916b977182b764580e601cb084Wink Saville                int version = mPduHeader.getOctet(field);
487d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == version) {
488d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendShortInteger(PduHeaders.CURRENT_MMS_VERSION);
489d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
490d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendShortInteger(version);
491d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
492d02a064168ae5c916b977182b764580e601cb084Wink Saville
493d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
494d02a064168ae5c916b977182b764580e601cb084Wink Saville
495d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_ID:
496d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.TRANSACTION_ID:
497d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] textString = mPduHeader.getTextString(field);
498d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == textString) {
499d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
500d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
501d02a064168ae5c916b977182b764580e601cb084Wink Saville
502d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
503d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendTextString(textString);
504d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
505d02a064168ae5c916b977182b764580e601cb084Wink Saville
506d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.TO:
507d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.BCC:
508d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.CC:
509d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue[] addr = mPduHeader.getEncodedStringValues(field);
510d02a064168ae5c916b977182b764580e601cb084Wink Saville
511d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == addr) {
512d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
513d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
514d02a064168ae5c916b977182b764580e601cb084Wink Saville
515d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue temp;
516d02a064168ae5c916b977182b764580e601cb084Wink Saville                for (int i = 0; i < addr.length; i++) {
517d02a064168ae5c916b977182b764580e601cb084Wink Saville                    temp = appendAddressType(addr[i]);
518d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (temp == null) {
519d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return PDU_COMPOSE_CONTENT_ERROR;
520d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
521d02a064168ae5c916b977182b764580e601cb084Wink Saville
522d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendOctet(field);
523d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendEncodedString(temp);
524d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
525d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
526d02a064168ae5c916b977182b764580e601cb084Wink Saville
527d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.FROM:
528d02a064168ae5c916b977182b764580e601cb084Wink Saville                // Value-length (Address-present-token Encoded-string-value | Insert-address-token)
529d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
530d02a064168ae5c916b977182b764580e601cb084Wink Saville
531d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue from = mPduHeader.getEncodedStringValue(field);
532d02a064168ae5c916b977182b764580e601cb084Wink Saville                if ((from == null)
533d02a064168ae5c916b977182b764580e601cb084Wink Saville                        || TextUtils.isEmpty(from.getString())
534d02a064168ae5c916b977182b764580e601cb084Wink Saville                        || new String(from.getTextString()).equals(
535d02a064168ae5c916b977182b764580e601cb084Wink Saville                                PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR)) {
536d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // Length of from = 1
537d02a064168ae5c916b977182b764580e601cb084Wink Saville                    append(1);
538d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // Insert-address-token = <Octet 129>
539d02a064168ae5c916b977182b764580e601cb084Wink Saville                    append(PduHeaders.FROM_INSERT_ADDRESS_TOKEN);
540d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
541d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mStack.newbuf();
542d02a064168ae5c916b977182b764580e601cb084Wink Saville                    PositionMarker fstart = mStack.mark();
543d02a064168ae5c916b977182b764580e601cb084Wink Saville
544d02a064168ae5c916b977182b764580e601cb084Wink Saville                    // Address-present-token = <Octet 128>
545d02a064168ae5c916b977182b764580e601cb084Wink Saville                    append(PduHeaders.FROM_ADDRESS_PRESENT_TOKEN);
546d02a064168ae5c916b977182b764580e601cb084Wink Saville
547d02a064168ae5c916b977182b764580e601cb084Wink Saville                    temp = appendAddressType(from);
548d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (temp == null) {
549d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return PDU_COMPOSE_CONTENT_ERROR;
550d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
551d02a064168ae5c916b977182b764580e601cb084Wink Saville
552d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendEncodedString(temp);
553d02a064168ae5c916b977182b764580e601cb084Wink Saville
554d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int flen = fstart.getLength();
555d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mStack.pop();
556d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendValueLength(flen);
557d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mStack.copy();
558d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
559d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
560d02a064168ae5c916b977182b764580e601cb084Wink Saville
561d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.READ_STATUS:
562d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.STATUS:
563d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.REPORT_ALLOWED:
564d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.PRIORITY:
565d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.DELIVERY_REPORT:
566d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.READ_REPORT:
567d02a064168ae5c916b977182b764580e601cb084Wink Saville                int octet = mPduHeader.getOctet(field);
568d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (0 == octet) {
569d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
570d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
571d02a064168ae5c916b977182b764580e601cb084Wink Saville
572d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
573d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(octet);
574d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
575d02a064168ae5c916b977182b764580e601cb084Wink Saville
576d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.DATE:
577d02a064168ae5c916b977182b764580e601cb084Wink Saville                long date = mPduHeader.getLongInteger(field);
578d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == date) {
579d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
580d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
581d02a064168ae5c916b977182b764580e601cb084Wink Saville
582d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
583d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendDateValue(date);
584d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
585d02a064168ae5c916b977182b764580e601cb084Wink Saville
586d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.SUBJECT:
587d02a064168ae5c916b977182b764580e601cb084Wink Saville                EncodedStringValue enString =
588d02a064168ae5c916b977182b764580e601cb084Wink Saville                    mPduHeader.getEncodedStringValue(field);
589d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == enString) {
590d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
591d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
592d02a064168ae5c916b977182b764580e601cb084Wink Saville
593d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
594d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendEncodedString(enString);
595d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
596d02a064168ae5c916b977182b764580e601cb084Wink Saville
597d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.MESSAGE_CLASS:
598d02a064168ae5c916b977182b764580e601cb084Wink Saville                byte[] messageClass = mPduHeader.getTextString(field);
599d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == messageClass) {
600d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
601d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
602d02a064168ae5c916b977182b764580e601cb084Wink Saville
603d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
604d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (Arrays.equals(messageClass,
605d02a064168ae5c916b977182b764580e601cb084Wink Saville                        PduHeaders.MESSAGE_CLASS_ADVERTISEMENT_STR.getBytes())) {
606d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendOctet(PduHeaders.MESSAGE_CLASS_ADVERTISEMENT);
607d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else if (Arrays.equals(messageClass,
608d02a064168ae5c916b977182b764580e601cb084Wink Saville                        PduHeaders.MESSAGE_CLASS_AUTO_STR.getBytes())) {
609d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendOctet(PduHeaders.MESSAGE_CLASS_AUTO);
610d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else if (Arrays.equals(messageClass,
611d02a064168ae5c916b977182b764580e601cb084Wink Saville                        PduHeaders.MESSAGE_CLASS_PERSONAL_STR.getBytes())) {
612d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendOctet(PduHeaders.MESSAGE_CLASS_PERSONAL);
613d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else if (Arrays.equals(messageClass,
614d02a064168ae5c916b977182b764580e601cb084Wink Saville                        PduHeaders.MESSAGE_CLASS_INFORMATIONAL_STR.getBytes())) {
615d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendOctet(PduHeaders.MESSAGE_CLASS_INFORMATIONAL);
616d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
617d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendTextString(messageClass);
618d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
619d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
620d02a064168ae5c916b977182b764580e601cb084Wink Saville
621d02a064168ae5c916b977182b764580e601cb084Wink Saville            case PduHeaders.EXPIRY:
622d02a064168ae5c916b977182b764580e601cb084Wink Saville                long expiry = mPduHeader.getLongInteger(field);
623d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (-1 == expiry) {
624d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_FIELD_NOT_SET;
625d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
626d02a064168ae5c916b977182b764580e601cb084Wink Saville
627d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(field);
628d02a064168ae5c916b977182b764580e601cb084Wink Saville
629d02a064168ae5c916b977182b764580e601cb084Wink Saville                mStack.newbuf();
630d02a064168ae5c916b977182b764580e601cb084Wink Saville                PositionMarker expiryStart = mStack.mark();
631d02a064168ae5c916b977182b764580e601cb084Wink Saville
632d02a064168ae5c916b977182b764580e601cb084Wink Saville                append(PduHeaders.VALUE_RELATIVE_TOKEN);
633d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendLongInteger(expiry);
634d02a064168ae5c916b977182b764580e601cb084Wink Saville
635d02a064168ae5c916b977182b764580e601cb084Wink Saville                int expiryLength = expiryStart.getLength();
636d02a064168ae5c916b977182b764580e601cb084Wink Saville                mStack.pop();
637d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendValueLength(expiryLength);
638d02a064168ae5c916b977182b764580e601cb084Wink Saville                mStack.copy();
639d02a064168ae5c916b977182b764580e601cb084Wink Saville                break;
640d02a064168ae5c916b977182b764580e601cb084Wink Saville
641d02a064168ae5c916b977182b764580e601cb084Wink Saville            default:
642d02a064168ae5c916b977182b764580e601cb084Wink Saville                return PDU_COMPOSE_FIELD_NOT_SUPPORTED;
643d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
644d02a064168ae5c916b977182b764580e601cb084Wink Saville
645d02a064168ae5c916b977182b764580e601cb084Wink Saville        return PDU_COMPOSE_SUCCESS;
646d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
647d02a064168ae5c916b977182b764580e601cb084Wink Saville
648d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
649d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make ReadRec.Ind.
650d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
651d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int makeReadRecInd() {
652d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mMessage == null) {
653d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = new ByteArrayOutputStream();
654d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = 0;
655d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
656d02a064168ae5c916b977182b764580e601cb084Wink Saville
657d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Message-Type
658d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE);
659d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE_READ_REC_IND);
660d02a064168ae5c916b977182b764580e601cb084Wink Saville
661d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-MMS-Version
662d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
663d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
664d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
665d02a064168ae5c916b977182b764580e601cb084Wink Saville
666d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Message-ID
667d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.MESSAGE_ID) != PDU_COMPOSE_SUCCESS) {
668d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
669d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
670d02a064168ae5c916b977182b764580e601cb084Wink Saville
671d02a064168ae5c916b977182b764580e601cb084Wink Saville        // To
672d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_SUCCESS) {
673d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
674d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
675d02a064168ae5c916b977182b764580e601cb084Wink Saville
676d02a064168ae5c916b977182b764580e601cb084Wink Saville        // From
677d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
678d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
679d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
680d02a064168ae5c916b977182b764580e601cb084Wink Saville
681d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Date Optional
682d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.DATE);
683d02a064168ae5c916b977182b764580e601cb084Wink Saville
684d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Read-Status
685d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.READ_STATUS) != PDU_COMPOSE_SUCCESS) {
686d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
687d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
688d02a064168ae5c916b977182b764580e601cb084Wink Saville
689d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Applic-ID Optional(not support)
690d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Reply-Applic-ID Optional(not support)
691d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Aux-Applic-Info Optional(not support)
692d02a064168ae5c916b977182b764580e601cb084Wink Saville
693d02a064168ae5c916b977182b764580e601cb084Wink Saville        return PDU_COMPOSE_SUCCESS;
694d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
695d02a064168ae5c916b977182b764580e601cb084Wink Saville
696d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
697d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make NotifyResp.Ind.
698d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
699d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int makeNotifyResp() {
700d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mMessage == null) {
701d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = new ByteArrayOutputStream();
702d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = 0;
703d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
704d02a064168ae5c916b977182b764580e601cb084Wink Saville
705d02a064168ae5c916b977182b764580e601cb084Wink Saville        //    X-Mms-Message-Type
706d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE);
707d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE_NOTIFYRESP_IND);
708d02a064168ae5c916b977182b764580e601cb084Wink Saville
709d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Transaction-ID
710d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
711d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
712d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
713d02a064168ae5c916b977182b764580e601cb084Wink Saville
714d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-MMS-Version
715d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
716d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
717d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
718d02a064168ae5c916b977182b764580e601cb084Wink Saville
719d02a064168ae5c916b977182b764580e601cb084Wink Saville        //  X-Mms-Status
720d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.STATUS) != PDU_COMPOSE_SUCCESS) {
721d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
722d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
723d02a064168ae5c916b977182b764580e601cb084Wink Saville
724d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Report-Allowed Optional (not support)
725d02a064168ae5c916b977182b764580e601cb084Wink Saville        return PDU_COMPOSE_SUCCESS;
726d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
727d02a064168ae5c916b977182b764580e601cb084Wink Saville
728d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
729d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make Acknowledge.Ind.
730d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
731d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int makeAckInd() {
732d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mMessage == null) {
733d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = new ByteArrayOutputStream();
734d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = 0;
735d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
736d02a064168ae5c916b977182b764580e601cb084Wink Saville
737d02a064168ae5c916b977182b764580e601cb084Wink Saville        //    X-Mms-Message-Type
738d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE);
739d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE_ACKNOWLEDGE_IND);
740d02a064168ae5c916b977182b764580e601cb084Wink Saville
741d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Transaction-ID
742d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.TRANSACTION_ID) != PDU_COMPOSE_SUCCESS) {
743d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
744d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
745d02a064168ae5c916b977182b764580e601cb084Wink Saville
746d02a064168ae5c916b977182b764580e601cb084Wink Saville        //     X-Mms-MMS-Version
747d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
748d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
749d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
750d02a064168ae5c916b977182b764580e601cb084Wink Saville
751d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Report-Allowed Optional
752d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.REPORT_ALLOWED);
753d02a064168ae5c916b977182b764580e601cb084Wink Saville
754d02a064168ae5c916b977182b764580e601cb084Wink Saville        return PDU_COMPOSE_SUCCESS;
755d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
756d02a064168ae5c916b977182b764580e601cb084Wink Saville
757d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
758d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make Send.req.
759d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
760d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int makeSendReqPdu() {
761d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (mMessage == null) {
762d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = new ByteArrayOutputStream();
763d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = 0;
764d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
765d02a064168ae5c916b977182b764580e601cb084Wink Saville
766d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Message-Type
767d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE);
768d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.MESSAGE_TYPE_SEND_REQ);
769d02a064168ae5c916b977182b764580e601cb084Wink Saville
770d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Transaction-ID
771d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.TRANSACTION_ID);
772d02a064168ae5c916b977182b764580e601cb084Wink Saville
773d02a064168ae5c916b977182b764580e601cb084Wink Saville        byte[] trid = mPduHeader.getTextString(PduHeaders.TRANSACTION_ID);
774d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (trid == null) {
775d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Transaction-ID should be set(by Transaction) before make().
776d02a064168ae5c916b977182b764580e601cb084Wink Saville            throw new IllegalArgumentException("Transaction-ID is null.");
777d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
778d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendTextString(trid);
779d02a064168ae5c916b977182b764580e601cb084Wink Saville
780d02a064168ae5c916b977182b764580e601cb084Wink Saville        //  X-Mms-MMS-Version
781d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.MMS_VERSION) != PDU_COMPOSE_SUCCESS) {
782d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
783d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
784d02a064168ae5c916b977182b764580e601cb084Wink Saville
785d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Date Date-value Optional.
786d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.DATE);
787d02a064168ae5c916b977182b764580e601cb084Wink Saville
788d02a064168ae5c916b977182b764580e601cb084Wink Saville        // From
789d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.FROM) != PDU_COMPOSE_SUCCESS) {
790d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
791d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
792d02a064168ae5c916b977182b764580e601cb084Wink Saville
793d02a064168ae5c916b977182b764580e601cb084Wink Saville        boolean recipient = false;
794d02a064168ae5c916b977182b764580e601cb084Wink Saville
795d02a064168ae5c916b977182b764580e601cb084Wink Saville        // To
796d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.TO) != PDU_COMPOSE_CONTENT_ERROR) {
797d02a064168ae5c916b977182b764580e601cb084Wink Saville            recipient = true;
798d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
799d02a064168ae5c916b977182b764580e601cb084Wink Saville
800d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Cc
801d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.CC) != PDU_COMPOSE_CONTENT_ERROR) {
802d02a064168ae5c916b977182b764580e601cb084Wink Saville            recipient = true;
803d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
804d02a064168ae5c916b977182b764580e601cb084Wink Saville
805d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Bcc
806d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (appendHeader(PduHeaders.BCC) != PDU_COMPOSE_CONTENT_ERROR) {
807d02a064168ae5c916b977182b764580e601cb084Wink Saville            recipient = true;
808d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
809d02a064168ae5c916b977182b764580e601cb084Wink Saville
810d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Need at least one of "cc", "bcc" and "to".
811d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (false == recipient) {
812d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
813d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
814d02a064168ae5c916b977182b764580e601cb084Wink Saville
815d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Subject Optional
816d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.SUBJECT);
817d02a064168ae5c916b977182b764580e601cb084Wink Saville
818d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Message-Class Optional
819d02a064168ae5c916b977182b764580e601cb084Wink Saville        // Message-class-value = Class-identifier | Token-text
820d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.MESSAGE_CLASS);
821d02a064168ae5c916b977182b764580e601cb084Wink Saville
822d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Expiry Optional
823d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.EXPIRY);
824d02a064168ae5c916b977182b764580e601cb084Wink Saville
825d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Priority Optional
826d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.PRIORITY);
827d02a064168ae5c916b977182b764580e601cb084Wink Saville
828d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Delivery-Report Optional
829d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.DELIVERY_REPORT);
830d02a064168ae5c916b977182b764580e601cb084Wink Saville
831d02a064168ae5c916b977182b764580e601cb084Wink Saville        // X-Mms-Read-Report Optional
832d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendHeader(PduHeaders.READ_REPORT);
833d02a064168ae5c916b977182b764580e601cb084Wink Saville
834d02a064168ae5c916b977182b764580e601cb084Wink Saville        //    Content-Type
835d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendOctet(PduHeaders.CONTENT_TYPE);
836d02a064168ae5c916b977182b764580e601cb084Wink Saville
837d02a064168ae5c916b977182b764580e601cb084Wink Saville        //  Message body
838d02a064168ae5c916b977182b764580e601cb084Wink Saville        return makeMessageBody();
839d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
840d02a064168ae5c916b977182b764580e601cb084Wink Saville
841d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
842d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Make message body.
843d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
844d02a064168ae5c916b977182b764580e601cb084Wink Saville    private int makeMessageBody() {
845d02a064168ae5c916b977182b764580e601cb084Wink Saville        // 1. add body informations
846d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.newbuf();  // Switching buffer because we need to
847d02a064168ae5c916b977182b764580e601cb084Wink Saville
848d02a064168ae5c916b977182b764580e601cb084Wink Saville        PositionMarker ctStart = mStack.mark();
849d02a064168ae5c916b977182b764580e601cb084Wink Saville
850d02a064168ae5c916b977182b764580e601cb084Wink Saville        // This contentTypeIdentifier should be used for type of attachment...
851d02a064168ae5c916b977182b764580e601cb084Wink Saville        String contentType = new String(mPduHeader.getTextString(PduHeaders.CONTENT_TYPE));
852d02a064168ae5c916b977182b764580e601cb084Wink Saville        Integer contentTypeIdentifier = mContentTypeMap.get(contentType);
853d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (contentTypeIdentifier == null) {
854d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content type is mandatory
855d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_CONTENT_ERROR;
856d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
857d02a064168ae5c916b977182b764580e601cb084Wink Saville
858d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendShortInteger(contentTypeIdentifier.intValue());
859d02a064168ae5c916b977182b764580e601cb084Wink Saville
860d02a064168ae5c916b977182b764580e601cb084Wink Saville        // content-type parameter: start
861d02a064168ae5c916b977182b764580e601cb084Wink Saville        PduBody body = ((SendReq) mPdu).getBody();
862d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null == body || body.getPartsNum() == 0) {
863d02a064168ae5c916b977182b764580e601cb084Wink Saville            // empty message
864d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendUintvarInteger(0);
865d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.pop();
866d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.copy();
867d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_COMPOSE_SUCCESS;
868d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
869d02a064168ae5c916b977182b764580e601cb084Wink Saville
870d02a064168ae5c916b977182b764580e601cb084Wink Saville        PduPart part;
871d02a064168ae5c916b977182b764580e601cb084Wink Saville        try {
872d02a064168ae5c916b977182b764580e601cb084Wink Saville            part = body.getPart(0);
873d02a064168ae5c916b977182b764580e601cb084Wink Saville
874d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] start = part.getContentId();
875d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (start != null) {
876d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(PduPart.P_DEP_START);
877d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (('<' == start[0]) && ('>' == start[start.length - 1])) {
878d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendTextString(start);
879d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
880d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendTextString("<" + new String(start) + ">");
881d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
882d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
883d02a064168ae5c916b977182b764580e601cb084Wink Saville
884d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content-type parameter: type
885d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendOctet(PduPart.P_CT_MR_TYPE);
886d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendTextString(part.getContentType());
887d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
888d02a064168ae5c916b977182b764580e601cb084Wink Saville        catch (ArrayIndexOutOfBoundsException e){
889d02a064168ae5c916b977182b764580e601cb084Wink Saville            e.printStackTrace();
890d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
891d02a064168ae5c916b977182b764580e601cb084Wink Saville
892d02a064168ae5c916b977182b764580e601cb084Wink Saville        int ctLength = ctStart.getLength();
893d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.pop();
894d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendValueLength(ctLength);
895d02a064168ae5c916b977182b764580e601cb084Wink Saville        mStack.copy();
896d02a064168ae5c916b977182b764580e601cb084Wink Saville
897d02a064168ae5c916b977182b764580e601cb084Wink Saville        // 3. add content
898d02a064168ae5c916b977182b764580e601cb084Wink Saville        int partNum = body.getPartsNum();
899d02a064168ae5c916b977182b764580e601cb084Wink Saville        appendUintvarInteger(partNum);
900d02a064168ae5c916b977182b764580e601cb084Wink Saville        for (int i = 0; i < partNum; i++) {
901d02a064168ae5c916b977182b764580e601cb084Wink Saville            part = body.getPart(i);
902d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.newbuf();  // Leaving space for header lengh and data length
903d02a064168ae5c916b977182b764580e601cb084Wink Saville            PositionMarker attachment = mStack.mark();
904d02a064168ae5c916b977182b764580e601cb084Wink Saville
905d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.newbuf();  // Leaving space for Content-Type length
906d02a064168ae5c916b977182b764580e601cb084Wink Saville            PositionMarker contentTypeBegin = mStack.mark();
907d02a064168ae5c916b977182b764580e601cb084Wink Saville
908d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] partContentType = part.getContentType();
909d02a064168ae5c916b977182b764580e601cb084Wink Saville
910d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (partContentType == null) {
911d02a064168ae5c916b977182b764580e601cb084Wink Saville                // content type is mandatory
912d02a064168ae5c916b977182b764580e601cb084Wink Saville                return PDU_COMPOSE_CONTENT_ERROR;
913d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
914d02a064168ae5c916b977182b764580e601cb084Wink Saville
915d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content-type value
916d02a064168ae5c916b977182b764580e601cb084Wink Saville            Integer partContentTypeIdentifier =
917d02a064168ae5c916b977182b764580e601cb084Wink Saville                mContentTypeMap.get(new String(partContentType));
918d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (partContentTypeIdentifier == null) {
919d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendTextString(partContentType);
920d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
921d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendShortInteger(partContentTypeIdentifier.intValue());
922d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
923d02a064168ae5c916b977182b764580e601cb084Wink Saville
924d02a064168ae5c916b977182b764580e601cb084Wink Saville            /* Content-type parameter : name.
925d02a064168ae5c916b977182b764580e601cb084Wink Saville             * The value of name, filename, content-location is the same.
926d02a064168ae5c916b977182b764580e601cb084Wink Saville             * Just one of them is enough for this PDU.
927d02a064168ae5c916b977182b764580e601cb084Wink Saville             */
928d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] name = part.getName();
929d02a064168ae5c916b977182b764580e601cb084Wink Saville
930d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null == name) {
931d02a064168ae5c916b977182b764580e601cb084Wink Saville                name = part.getFilename();
932d02a064168ae5c916b977182b764580e601cb084Wink Saville
933d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (null == name) {
934d02a064168ae5c916b977182b764580e601cb084Wink Saville                    name = part.getContentLocation();
935d02a064168ae5c916b977182b764580e601cb084Wink Saville
936d02a064168ae5c916b977182b764580e601cb084Wink Saville                    if (null == name) {
937d02a064168ae5c916b977182b764580e601cb084Wink Saville                        /* at lease one of name, filename, Content-location
938d02a064168ae5c916b977182b764580e601cb084Wink Saville                         * should be available.
939d02a064168ae5c916b977182b764580e601cb084Wink Saville                         */
940d02a064168ae5c916b977182b764580e601cb084Wink Saville                        return PDU_COMPOSE_CONTENT_ERROR;
941d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
942d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
943d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
944d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendOctet(PduPart.P_DEP_NAME);
945d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendTextString(name);
946d02a064168ae5c916b977182b764580e601cb084Wink Saville
947d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content-type parameter : charset
948d02a064168ae5c916b977182b764580e601cb084Wink Saville            int charset = part.getCharset();
949d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (charset != 0) {
950d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(PduPart.P_CHARSET);
951d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendShortInteger(charset);
952d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
953d02a064168ae5c916b977182b764580e601cb084Wink Saville
954d02a064168ae5c916b977182b764580e601cb084Wink Saville            int contentTypeLength = contentTypeBegin.getLength();
955d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.pop();
956d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendValueLength(contentTypeLength);
957d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.copy();
958d02a064168ae5c916b977182b764580e601cb084Wink Saville
959d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content id
960d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] contentId = part.getContentId();
961d02a064168ae5c916b977182b764580e601cb084Wink Saville
962d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != contentId) {
963d02a064168ae5c916b977182b764580e601cb084Wink Saville                appendOctet(PduPart.P_CONTENT_ID);
964d02a064168ae5c916b977182b764580e601cb084Wink Saville                if (('<' == contentId[0]) && ('>' == contentId[contentId.length - 1])) {
965d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendQuotedString(contentId);
966d02a064168ae5c916b977182b764580e601cb084Wink Saville                } else {
967d02a064168ae5c916b977182b764580e601cb084Wink Saville                    appendQuotedString("<" + new String(contentId) + ">");
968d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
969d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
970d02a064168ae5c916b977182b764580e601cb084Wink Saville
971d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content-location
972d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] contentLocation = part.getContentLocation();
973d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (null != contentLocation) {
974d02a064168ae5c916b977182b764580e601cb084Wink Saville            	appendOctet(PduPart.P_CONTENT_LOCATION);
975d02a064168ae5c916b977182b764580e601cb084Wink Saville            	appendTextString(contentLocation);
976d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
977d02a064168ae5c916b977182b764580e601cb084Wink Saville
978d02a064168ae5c916b977182b764580e601cb084Wink Saville            // content
979d02a064168ae5c916b977182b764580e601cb084Wink Saville            int headerLength = attachment.getLength();
980d02a064168ae5c916b977182b764580e601cb084Wink Saville
981d02a064168ae5c916b977182b764580e601cb084Wink Saville            int dataLength = 0; // Just for safety...
982d02a064168ae5c916b977182b764580e601cb084Wink Saville            byte[] partData = part.getData();
983d02a064168ae5c916b977182b764580e601cb084Wink Saville
984d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (partData != null) {
985d02a064168ae5c916b977182b764580e601cb084Wink Saville                arraycopy(partData, 0, partData.length);
986d02a064168ae5c916b977182b764580e601cb084Wink Saville                dataLength = partData.length;
987d02a064168ae5c916b977182b764580e601cb084Wink Saville            } else {
988d02a064168ae5c916b977182b764580e601cb084Wink Saville                InputStream cr;
989d02a064168ae5c916b977182b764580e601cb084Wink Saville                try {
990d02a064168ae5c916b977182b764580e601cb084Wink Saville                    byte[] buffer = new byte[PDU_COMPOSER_BLOCK_SIZE];
991d02a064168ae5c916b977182b764580e601cb084Wink Saville                    cr = mResolver.openInputStream(part.getDataUri());
992d02a064168ae5c916b977182b764580e601cb084Wink Saville                    int len = 0;
993d02a064168ae5c916b977182b764580e601cb084Wink Saville                    while ((len = cr.read(buffer)) != -1) {
994d02a064168ae5c916b977182b764580e601cb084Wink Saville                        mMessage.write(buffer, 0, len);
995d02a064168ae5c916b977182b764580e601cb084Wink Saville                        mPosition += len;
996d02a064168ae5c916b977182b764580e601cb084Wink Saville                        dataLength += len;
997d02a064168ae5c916b977182b764580e601cb084Wink Saville                    }
998d02a064168ae5c916b977182b764580e601cb084Wink Saville                } catch (FileNotFoundException e) {
999d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_CONTENT_ERROR;
1000d02a064168ae5c916b977182b764580e601cb084Wink Saville                } catch (IOException e) {
1001d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_CONTENT_ERROR;
1002d02a064168ae5c916b977182b764580e601cb084Wink Saville                } catch (RuntimeException e) {
1003d02a064168ae5c916b977182b764580e601cb084Wink Saville                    return PDU_COMPOSE_CONTENT_ERROR;
1004d02a064168ae5c916b977182b764580e601cb084Wink Saville                }
1005d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1006d02a064168ae5c916b977182b764580e601cb084Wink Saville
1007d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (dataLength != (attachment.getLength() - headerLength)) {
1008d02a064168ae5c916b977182b764580e601cb084Wink Saville                throw new RuntimeException("BUG: Length sanity check failed");
1009d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1010d02a064168ae5c916b977182b764580e601cb084Wink Saville
1011d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.pop();
1012d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendUintvarInteger(headerLength);
1013d02a064168ae5c916b977182b764580e601cb084Wink Saville            appendUintvarInteger(dataLength);
1014d02a064168ae5c916b977182b764580e601cb084Wink Saville            mStack.copy();
1015d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1016d02a064168ae5c916b977182b764580e601cb084Wink Saville
1017d02a064168ae5c916b977182b764580e601cb084Wink Saville        return PDU_COMPOSE_SUCCESS;
1018d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1019d02a064168ae5c916b977182b764580e601cb084Wink Saville
1020d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1021d02a064168ae5c916b977182b764580e601cb084Wink Saville     *  Record current message informations.
1022d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1023d02a064168ae5c916b977182b764580e601cb084Wink Saville    static private class LengthRecordNode {
1024d02a064168ae5c916b977182b764580e601cb084Wink Saville        ByteArrayOutputStream currentMessage = null;
1025d02a064168ae5c916b977182b764580e601cb084Wink Saville        public int currentPosition = 0;
1026d02a064168ae5c916b977182b764580e601cb084Wink Saville
1027d02a064168ae5c916b977182b764580e601cb084Wink Saville        public LengthRecordNode next = null;
1028d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1029d02a064168ae5c916b977182b764580e601cb084Wink Saville
1030d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1031d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Mark current message position and stact size.
1032d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1033d02a064168ae5c916b977182b764580e601cb084Wink Saville    private class PositionMarker {
1034d02a064168ae5c916b977182b764580e601cb084Wink Saville        private int c_pos;   // Current position
1035d02a064168ae5c916b977182b764580e601cb084Wink Saville        private int currentStackSize;  // Current stack size
1036d02a064168ae5c916b977182b764580e601cb084Wink Saville
1037d02a064168ae5c916b977182b764580e601cb084Wink Saville        int getLength() {
1038d02a064168ae5c916b977182b764580e601cb084Wink Saville            // If these assert fails, likely that you are finding the
1039d02a064168ae5c916b977182b764580e601cb084Wink Saville            // size of buffer that is deep in BufferStack you can only
1040d02a064168ae5c916b977182b764580e601cb084Wink Saville            // find the length of the buffer that is on top
1041d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (currentStackSize != mStack.stackSize) {
1042d02a064168ae5c916b977182b764580e601cb084Wink Saville                throw new RuntimeException("BUG: Invalid call to getLength()");
1043d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1044d02a064168ae5c916b977182b764580e601cb084Wink Saville
1045d02a064168ae5c916b977182b764580e601cb084Wink Saville            return mPosition - c_pos;
1046d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1047d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1048d02a064168ae5c916b977182b764580e601cb084Wink Saville
1049d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1050d02a064168ae5c916b977182b764580e601cb084Wink Saville     * This implementation can be OPTIMIZED to use only
1051d02a064168ae5c916b977182b764580e601cb084Wink Saville     * 2 buffers. This optimization involves changing BufferStack
1052d02a064168ae5c916b977182b764580e601cb084Wink Saville     * only... Its usage (interface) will not change.
1053d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1054d02a064168ae5c916b977182b764580e601cb084Wink Saville    private class BufferStack {
1055d02a064168ae5c916b977182b764580e601cb084Wink Saville        private LengthRecordNode stack = null;
1056d02a064168ae5c916b977182b764580e601cb084Wink Saville        private LengthRecordNode toCopy = null;
1057d02a064168ae5c916b977182b764580e601cb084Wink Saville
1058d02a064168ae5c916b977182b764580e601cb084Wink Saville        int stackSize = 0;
1059d02a064168ae5c916b977182b764580e601cb084Wink Saville
1060d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1061d02a064168ae5c916b977182b764580e601cb084Wink Saville         *  Create a new message buffer and push it into the stack.
1062d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1063d02a064168ae5c916b977182b764580e601cb084Wink Saville        void newbuf() {
1064d02a064168ae5c916b977182b764580e601cb084Wink Saville            // You can't create a new buff when toCopy != null
1065d02a064168ae5c916b977182b764580e601cb084Wink Saville            // That is after calling pop() and before calling copy()
1066d02a064168ae5c916b977182b764580e601cb084Wink Saville            // If you do, it is a bug
1067d02a064168ae5c916b977182b764580e601cb084Wink Saville            if (toCopy != null) {
1068d02a064168ae5c916b977182b764580e601cb084Wink Saville                throw new RuntimeException("BUG: Invalid newbuf() before copy()");
1069d02a064168ae5c916b977182b764580e601cb084Wink Saville            }
1070d02a064168ae5c916b977182b764580e601cb084Wink Saville
1071d02a064168ae5c916b977182b764580e601cb084Wink Saville            LengthRecordNode temp = new LengthRecordNode();
1072d02a064168ae5c916b977182b764580e601cb084Wink Saville
1073d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp.currentMessage = mMessage;
1074d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp.currentPosition = mPosition;
1075d02a064168ae5c916b977182b764580e601cb084Wink Saville
1076d02a064168ae5c916b977182b764580e601cb084Wink Saville            temp.next = stack;
1077d02a064168ae5c916b977182b764580e601cb084Wink Saville            stack = temp;
1078d02a064168ae5c916b977182b764580e601cb084Wink Saville
1079d02a064168ae5c916b977182b764580e601cb084Wink Saville            stackSize = stackSize + 1;
1080d02a064168ae5c916b977182b764580e601cb084Wink Saville
1081d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = new ByteArrayOutputStream();
1082d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = 0;
1083d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1084d02a064168ae5c916b977182b764580e601cb084Wink Saville
1085d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1086d02a064168ae5c916b977182b764580e601cb084Wink Saville         *  Pop the message before and record current message in the stack.
1087d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1088d02a064168ae5c916b977182b764580e601cb084Wink Saville        void pop() {
1089d02a064168ae5c916b977182b764580e601cb084Wink Saville            ByteArrayOutputStream currentMessage = mMessage;
1090d02a064168ae5c916b977182b764580e601cb084Wink Saville            int currentPosition = mPosition;
1091d02a064168ae5c916b977182b764580e601cb084Wink Saville
1092d02a064168ae5c916b977182b764580e601cb084Wink Saville            mMessage = stack.currentMessage;
1093d02a064168ae5c916b977182b764580e601cb084Wink Saville            mPosition = stack.currentPosition;
1094d02a064168ae5c916b977182b764580e601cb084Wink Saville
1095d02a064168ae5c916b977182b764580e601cb084Wink Saville            toCopy = stack;
1096d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Re using the top element of the stack to avoid memory allocation
1097d02a064168ae5c916b977182b764580e601cb084Wink Saville
1098d02a064168ae5c916b977182b764580e601cb084Wink Saville            stack = stack.next;
1099d02a064168ae5c916b977182b764580e601cb084Wink Saville            stackSize = stackSize - 1;
1100d02a064168ae5c916b977182b764580e601cb084Wink Saville
1101d02a064168ae5c916b977182b764580e601cb084Wink Saville            toCopy.currentMessage = currentMessage;
1102d02a064168ae5c916b977182b764580e601cb084Wink Saville            toCopy.currentPosition = currentPosition;
1103d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1104d02a064168ae5c916b977182b764580e601cb084Wink Saville
1105d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1106d02a064168ae5c916b977182b764580e601cb084Wink Saville         *  Append current message to the message before.
1107d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1108d02a064168ae5c916b977182b764580e601cb084Wink Saville        void copy() {
1109d02a064168ae5c916b977182b764580e601cb084Wink Saville            arraycopy(toCopy.currentMessage.toByteArray(), 0,
1110d02a064168ae5c916b977182b764580e601cb084Wink Saville                    toCopy.currentPosition);
1111d02a064168ae5c916b977182b764580e601cb084Wink Saville
1112d02a064168ae5c916b977182b764580e601cb084Wink Saville            toCopy = null;
1113d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1114d02a064168ae5c916b977182b764580e601cb084Wink Saville
1115d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1116d02a064168ae5c916b977182b764580e601cb084Wink Saville         *  Mark current message position
1117d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1118d02a064168ae5c916b977182b764580e601cb084Wink Saville        PositionMarker mark() {
1119d02a064168ae5c916b977182b764580e601cb084Wink Saville            PositionMarker m = new PositionMarker();
1120d02a064168ae5c916b977182b764580e601cb084Wink Saville
1121d02a064168ae5c916b977182b764580e601cb084Wink Saville            m.c_pos = mPosition;
1122d02a064168ae5c916b977182b764580e601cb084Wink Saville            m.currentStackSize = stackSize;
1123d02a064168ae5c916b977182b764580e601cb084Wink Saville
1124d02a064168ae5c916b977182b764580e601cb084Wink Saville            return m;
1125d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1126d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1127d02a064168ae5c916b977182b764580e601cb084Wink Saville
1128d02a064168ae5c916b977182b764580e601cb084Wink Saville    /**
1129d02a064168ae5c916b977182b764580e601cb084Wink Saville     * Check address type.
1130d02a064168ae5c916b977182b764580e601cb084Wink Saville     *
1131d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @param address address string without the postfix stinng type,
1132d02a064168ae5c916b977182b764580e601cb084Wink Saville     *        such as "/TYPE=PLMN", "/TYPE=IPv6" and "/TYPE=IPv4"
1133d02a064168ae5c916b977182b764580e601cb084Wink Saville     * @return PDU_PHONE_NUMBER_ADDRESS_TYPE if it is phone number,
1134d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         PDU_EMAIL_ADDRESS_TYPE if it is email address,
1135d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         PDU_IPV4_ADDRESS_TYPE if it is ipv4 address,
1136d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         PDU_IPV6_ADDRESS_TYPE if it is ipv6 address,
1137d02a064168ae5c916b977182b764580e601cb084Wink Saville     *         PDU_UNKNOWN_ADDRESS_TYPE if it is unknown.
1138d02a064168ae5c916b977182b764580e601cb084Wink Saville     */
1139d02a064168ae5c916b977182b764580e601cb084Wink Saville    protected static int checkAddressType(String address) {
1140d02a064168ae5c916b977182b764580e601cb084Wink Saville        /**
1141d02a064168ae5c916b977182b764580e601cb084Wink Saville         * From OMA-TS-MMS-ENC-V1_3-20050927-C.pdf, section 8.
1142d02a064168ae5c916b977182b764580e601cb084Wink Saville         * address = ( e-mail / device-address / alphanum-shortcode / num-shortcode)
1143d02a064168ae5c916b977182b764580e601cb084Wink Saville         * e-mail = mailbox; to the definition of mailbox as described in
1144d02a064168ae5c916b977182b764580e601cb084Wink Saville         * section 3.4 of [RFC2822], but excluding the
1145d02a064168ae5c916b977182b764580e601cb084Wink Saville         * obsolete definitions as indicated by the "obs-" prefix.
1146d02a064168ae5c916b977182b764580e601cb084Wink Saville         * device-address = ( global-phone-number "/TYPE=PLMN" )
1147d02a064168ae5c916b977182b764580e601cb084Wink Saville         * / ( ipv4 "/TYPE=IPv4" ) / ( ipv6 "/TYPE=IPv6" )
1148d02a064168ae5c916b977182b764580e601cb084Wink Saville         * / ( escaped-value "/TYPE=" address-type )
1149d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1150d02a064168ae5c916b977182b764580e601cb084Wink Saville         * global-phone-number = ["+"] 1*( DIGIT / written-sep )
1151d02a064168ae5c916b977182b764580e601cb084Wink Saville         * written-sep =("-"/".")
1152d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1153d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ipv4 = 1*3DIGIT 3( "." 1*3DIGIT ) ; IPv4 address value
1154d02a064168ae5c916b977182b764580e601cb084Wink Saville         *
1155d02a064168ae5c916b977182b764580e601cb084Wink Saville         * ipv6 = 4HEXDIG 7( ":" 4HEXDIG ) ; IPv6 address per RFC 2373
1156d02a064168ae5c916b977182b764580e601cb084Wink Saville         */
1157d02a064168ae5c916b977182b764580e601cb084Wink Saville
1158d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (null == address) {
1159d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_UNKNOWN_ADDRESS_TYPE;
1160d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1161d02a064168ae5c916b977182b764580e601cb084Wink Saville
1162d02a064168ae5c916b977182b764580e601cb084Wink Saville        if (address.matches(REGEXP_IPV4_ADDRESS_TYPE)) {
1163d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Ipv4 address.
1164d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_IPV4_ADDRESS_TYPE;
1165d02a064168ae5c916b977182b764580e601cb084Wink Saville        }else if (address.matches(REGEXP_PHONE_NUMBER_ADDRESS_TYPE)) {
1166d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Phone number.
1167d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_PHONE_NUMBER_ADDRESS_TYPE;
1168d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else if (address.matches(REGEXP_EMAIL_ADDRESS_TYPE)) {
1169d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Email address.
1170d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_EMAIL_ADDRESS_TYPE;
1171d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else if (address.matches(REGEXP_IPV6_ADDRESS_TYPE)) {
1172d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Ipv6 address.
1173d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_IPV6_ADDRESS_TYPE;
1174d02a064168ae5c916b977182b764580e601cb084Wink Saville        } else {
1175d02a064168ae5c916b977182b764580e601cb084Wink Saville            // Unknown address.
1176d02a064168ae5c916b977182b764580e601cb084Wink Saville            return PDU_UNKNOWN_ADDRESS_TYPE;
1177d02a064168ae5c916b977182b764580e601cb084Wink Saville        }
1178d02a064168ae5c916b977182b764580e601cb084Wink Saville    }
1179d02a064168ae5c916b977182b764580e601cb084Wink Saville}
1180