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