• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2008 Esmertec AG.
3  * Copyright (C) 2007-2008 The Android Open Source Project
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 package com.android.messaging.mmslib.pdu;
19 
20 import android.net.Uri;
21 import android.util.SparseArray;
22 
23 /**
24  * The pdu part.
25  */
26 public class PduPart {
27     /**
28      * Well-Known Parameters.
29      */
30     public static final int P_Q                  = 0x80;
31     public static final int P_CHARSET            = 0x81;
32     public static final int P_LEVEL              = 0x82;
33     public static final int P_TYPE               = 0x83;
34     public static final int P_DEP_NAME           = 0x85;
35     public static final int P_DEP_FILENAME       = 0x86;
36     public static final int P_DIFFERENCES        = 0x87;
37     public static final int P_PADDING            = 0x88;
38     // This value of "TYPE" s used with Content-Type: multipart/related
39     public static final int P_CT_MR_TYPE         = 0x89;
40     public static final int P_DEP_START          = 0x8A;
41     public static final int P_DEP_START_INFO     = 0x8B;
42     public static final int P_DEP_COMMENT        = 0x8C;
43     public static final int P_DEP_DOMAIN         = 0x8D;
44     public static final int P_MAX_AGE            = 0x8E;
45     public static final int P_DEP_PATH           = 0x8F;
46     public static final int P_SECURE             = 0x90;
47     public static final int P_SEC                = 0x91;
48     public static final int P_MAC                = 0x92;
49     public static final int P_CREATION_DATE      = 0x93;
50     public static final int P_MODIFICATION_DATE  = 0x94;
51     public static final int P_READ_DATE          = 0x95;
52     public static final int P_SIZE               = 0x96;
53     public static final int P_NAME               = 0x97;
54     public static final int P_FILENAME           = 0x98;
55     public static final int P_START              = 0x99;
56     public static final int P_START_INFO         = 0x9A;
57     public static final int P_COMMENT            = 0x9B;
58     public static final int P_DOMAIN             = 0x9C;
59     public static final int P_PATH               = 0x9D;
60 
61     /**
62      * Header field names.
63      */
64      public static final int P_CONTENT_TYPE       = 0x91;
65      public static final int P_CONTENT_LOCATION   = 0x8E;
66      public static final int P_CONTENT_ID         = 0xC0;
67      public static final int P_DEP_CONTENT_DISPOSITION = 0xAE;
68      public static final int P_CONTENT_DISPOSITION = 0xC5;
69     // The next header is unassigned header, use reserved header(0x48) value.
70     public static final int P_CONTENT_TRANSFER_ENCODING = 0xC8;
71 
72     /**
73      * Content=Transfer-Encoding string.
74      */
75     public static final String CONTENT_TRANSFER_ENCODING =
76             "Content-Transfer-Encoding";
77 
78     /**
79      * Value of Content-Transfer-Encoding.
80      */
81     public static final String P_BINARY = "binary";
82     public static final String P_7BIT = "7bit";
83     public static final String P_8BIT = "8bit";
84     public static final String P_BASE64 = "base64";
85     public static final String P_QUOTED_PRINTABLE = "quoted-printable";
86 
87     /**
88      * Value of disposition can be set to PduPart when the value is octet in
89      * the PDU.
90      * "from-data" instead of Form-data<Octet 128>.
91      * "attachment" instead of Attachment<Octet 129>.
92      * "inline" instead of Inline<Octet 130>.
93      */
94     static final byte[] DISPOSITION_FROM_DATA = "from-data".getBytes();
95     static final byte[] DISPOSITION_ATTACHMENT = "attachment".getBytes();
96     static final byte[] DISPOSITION_INLINE = "inline".getBytes();
97 
98     /**
99      * Content-Disposition value.
100      */
101     public static final int P_DISPOSITION_FROM_DATA = 0x80;
102     public static final int P_DISPOSITION_ATTACHMENT = 0x81;
103     public static final int P_DISPOSITION_INLINE = 0x82;
104 
105     /**
106      * Header of part.
107      */
108     private SparseArray<Object> mPartHeader = null;
109 
110     /**
111      * Data uri.
112      */
113     private Uri mUri = null;
114 
115     /**
116      * Part data.
117      */
118     private byte[] mPartData = null;
119 
120     private static final String TAG = "PduPart";
121 
122     /**
123      * Empty Constructor.
124      */
PduPart()125     public PduPart() {
126         mPartHeader = new SparseArray<Object>();
127     }
128 
129     /**
130      * Set part data. The data are stored as byte array.
131      *
132      * @param data the data
133      */
setData(final byte[] data)134     public void setData(final byte[] data) {
135         mPartData = data;
136     }
137 
138     /**
139      * @return The part data or null if the data wasn't set or
140      * the data is stored as Uri.
141      * @see #getDataUri
142      */
getData()143     public byte[] getData() {
144         return mPartData;
145     }
146 
147     /**
148      * Set data uri. The data are stored as Uri.
149      *
150      * @param uri the uri
151      */
setDataUri(final Uri uri)152     public void setDataUri(final Uri uri) {
153         mUri = uri;
154     }
155 
156     /**
157      * @return The Uri of the part data or null if the data wasn't set or
158      * the data is stored as byte array.
159      * @see #getData
160      */
getDataUri()161     public Uri getDataUri() {
162         return mUri;
163     }
164 
165     /**
166      * Set Content-id value
167      *
168      * @param contentId the content-id value
169      * @throws NullPointerException if the value is null.
170      */
setContentId(final byte[] contentId)171     public void setContentId(final byte[] contentId) {
172         if ((contentId == null) || (contentId.length == 0)) {
173             throw new IllegalArgumentException(
174                     "Content-Id may not be null or empty.");
175         }
176 
177         if ((contentId.length > 1)
178                 && ((char) contentId[0] == '<')
179                 && ((char) contentId[contentId.length - 1] == '>')) {
180             mPartHeader.put(P_CONTENT_ID, contentId);
181             return;
182         }
183 
184         // Insert beginning '<' and trailing '>' for Content-Id.
185         final byte[] buffer = new byte[contentId.length + 2];
186         buffer[0] = (byte) (0xff & '<');
187         buffer[buffer.length - 1] = (byte) (0xff & '>');
188         System.arraycopy(contentId, 0, buffer, 1, contentId.length);
189         mPartHeader.put(P_CONTENT_ID, buffer);
190     }
191 
192     /**
193      * Get Content-id value.
194      *
195      * @return the value
196      */
getContentId()197     public byte[] getContentId() {
198         return (byte[]) mPartHeader.get(P_CONTENT_ID);
199     }
200 
201     /**
202      * Set Char-set value.
203      *
204      * @param charset the value
205      */
setCharset(final int charset)206     public void setCharset(final int charset) {
207         mPartHeader.put(P_CHARSET, charset);
208     }
209 
210     /**
211      * Get Char-set value
212      *
213      * @return the charset value. Return 0 if charset was not set.
214      */
getCharset()215     public int getCharset() {
216         final Integer charset = (Integer) mPartHeader.get(P_CHARSET);
217         if (charset == null) {
218             return 0;
219         } else {
220             return charset.intValue();
221         }
222     }
223 
224     /**
225      * Set Content-Location value.
226      *
227      * @param contentLocation the value
228      * @throws NullPointerException if the value is null.
229      */
setContentLocation(final byte[] contentLocation)230     public void setContentLocation(final byte[] contentLocation) {
231         if (contentLocation == null) {
232             throw new NullPointerException("null content-location");
233         }
234 
235         mPartHeader.put(P_CONTENT_LOCATION, contentLocation);
236     }
237 
238     /**
239      * Get Content-Location value.
240      *
241      * @return the value
242      * return PduPart.disposition[0] instead of <Octet 128> (Form-data).
243      * return PduPart.disposition[1] instead of <Octet 129> (Attachment).
244      * return PduPart.disposition[2] instead of <Octet 130> (Inline).
245      */
getContentLocation()246     public byte[] getContentLocation() {
247         return (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
248     }
249 
250     /**
251      * Set Content-Disposition value.
252      * Use PduPart.disposition[0] instead of <Octet 128> (Form-data).
253      * Use PduPart.disposition[1] instead of <Octet 129> (Attachment).
254      * Use PduPart.disposition[2] instead of <Octet 130> (Inline).
255      *
256      * @param contentDisposition the value
257      * @throws NullPointerException if the value is null.
258      */
setContentDisposition(final byte[] contentDisposition)259     public void setContentDisposition(final byte[] contentDisposition) {
260         if (contentDisposition == null) {
261             throw new NullPointerException("null content-disposition");
262         }
263 
264         mPartHeader.put(P_CONTENT_DISPOSITION, contentDisposition);
265     }
266 
267     /**
268      * Get Content-Disposition value.
269      *
270      * @return the value
271      */
getContentDisposition()272     public byte[] getContentDisposition() {
273         return (byte[]) mPartHeader.get(P_CONTENT_DISPOSITION);
274     }
275 
276     /**
277      * Set Content-Type value.
278      *
279      * @param value the value
280      * @throws NullPointerException if the value is null.
281      */
setContentType(final byte[] contentType)282     public void setContentType(final byte[] contentType) {
283         if (contentType == null) {
284             throw new NullPointerException("null content-type");
285         }
286 
287         mPartHeader.put(P_CONTENT_TYPE, contentType);
288     }
289 
290     /**
291      * Get Content-Type value of part.
292      *
293      * @return the value
294      */
getContentType()295     public byte[] getContentType() {
296         return (byte[]) mPartHeader.get(P_CONTENT_TYPE);
297     }
298 
299     /**
300      * Set Content-Transfer-Encoding value
301      *
302      * @param contentId the content-id value
303      * @throws NullPointerException if the value is null.
304      */
setContentTransferEncoding(final byte[] contentTransferEncoding)305     public void setContentTransferEncoding(final byte[] contentTransferEncoding) {
306         if (contentTransferEncoding == null) {
307             throw new NullPointerException("null content-transfer-encoding");
308         }
309 
310         mPartHeader.put(P_CONTENT_TRANSFER_ENCODING, contentTransferEncoding);
311     }
312 
313     /**
314      * Get Content-Transfer-Encoding value.
315      *
316      * @return the value
317      */
getContentTransferEncoding()318     public byte[] getContentTransferEncoding() {
319         return (byte[]) mPartHeader.get(P_CONTENT_TRANSFER_ENCODING);
320     }
321 
322     /**
323      * Set Content-type parameter: name.
324      *
325      * @param name the name value
326      * @throws NullPointerException if the value is null.
327      */
setName(final byte[] name)328     public void setName(final byte[] name) {
329         if (null == name) {
330             throw new NullPointerException("null content-id");
331         }
332 
333         mPartHeader.put(P_NAME, name);
334     }
335 
336     /**
337      * Get content-type parameter: name.
338      *
339      * @return the name
340      */
getName()341     public byte[] getName() {
342         return (byte[]) mPartHeader.get(P_NAME);
343     }
344 
345     /**
346      * Get Content-disposition parameter: filename
347      *
348      * @param fileName the filename value
349      * @throws NullPointerException if the value is null.
350      */
setFilename(final byte[] fileName)351     public void setFilename(final byte[] fileName) {
352         if (null == fileName) {
353             throw new NullPointerException("null content-id");
354         }
355 
356         mPartHeader.put(P_FILENAME, fileName);
357     }
358 
359     /**
360      * Set Content-disposition parameter: filename
361      *
362      * @return the filename
363      */
getFilename()364     public byte[] getFilename() {
365         return (byte[]) mPartHeader.get(P_FILENAME);
366     }
367 
generateLocation()368     public String generateLocation() {
369         // Assumption: At least one of the content-location / name / filename
370         // or content-id should be set. This is guaranteed by the PduParser
371         // for incoming messages and by MM composer for outgoing messages.
372         byte[] location = (byte[]) mPartHeader.get(P_NAME);
373         if (null == location) {
374             location = (byte[]) mPartHeader.get(P_FILENAME);
375 
376             if (null == location) {
377                 location = (byte[]) mPartHeader.get(P_CONTENT_LOCATION);
378             }
379         }
380 
381         if (null == location) {
382             final byte[] contentId = (byte[]) mPartHeader.get(P_CONTENT_ID);
383             return "cid:" + new String(contentId);
384         } else {
385             return new String(location);
386         }
387     }
388 }
389 
390