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.compat.annotation.UnsupportedAppUsage;
21 import android.util.Log;
22 
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.UnsupportedEncodingException;
26 import java.util.ArrayList;
27 
28 /**
29  * Encoded-string-value = Text-string | Value-length Char-set Text-string
30  */
31 public class EncodedStringValue implements Cloneable {
32     private static final String TAG = "EncodedStringValue";
33     private static final boolean DEBUG = false;
34     private static final boolean LOCAL_LOGV = false;
35 
36     /**
37      * The Char-set value.
38      */
39     private int mCharacterSet;
40 
41     /**
42      * The Text-string value.
43      */
44     private byte[] mData;
45 
46     /**
47      * Constructor.
48      *
49      * @param charset the Char-set value
50      * @param data the Text-string value
51      * @throws NullPointerException if Text-string value is null.
52      */
53     @UnsupportedAppUsage
EncodedStringValue(int charset, byte[] data)54     public EncodedStringValue(int charset, byte[] data) {
55         // TODO: CharSet needs to be validated against MIBEnum.
56         if(null == data) {
57             throw new NullPointerException("EncodedStringValue: Text-string is null.");
58         }
59 
60         mCharacterSet = charset;
61         mData = new byte[data.length];
62         System.arraycopy(data, 0, mData, 0, data.length);
63     }
64 
65     /**
66      * Constructor.
67      *
68      * @param data the Text-string value
69      * @throws NullPointerException if Text-string value is null.
70      */
71     @UnsupportedAppUsage
EncodedStringValue(byte[] data)72     public EncodedStringValue(byte[] data) {
73         this(CharacterSets.DEFAULT_CHARSET, data);
74     }
75 
76     @UnsupportedAppUsage
EncodedStringValue(String data)77     public EncodedStringValue(String data) {
78         try {
79             mData = data.getBytes(CharacterSets.DEFAULT_CHARSET_NAME);
80             mCharacterSet = CharacterSets.DEFAULT_CHARSET;
81         } catch (UnsupportedEncodingException e) {
82             Log.e(TAG, "Default encoding must be supported.", e);
83         }
84     }
85 
86     /**
87      * Get Char-set value.
88      *
89      * @return the value
90      */
91     @UnsupportedAppUsage
getCharacterSet()92     public int getCharacterSet() {
93         return mCharacterSet;
94     }
95 
96     /**
97      * Set Char-set value.
98      *
99      * @param charset the Char-set value
100      */
101     @UnsupportedAppUsage
setCharacterSet(int charset)102     public void setCharacterSet(int charset) {
103         // TODO: CharSet needs to be validated against MIBEnum.
104         mCharacterSet = charset;
105     }
106 
107     /**
108      * Get Text-string value.
109      *
110      * @return the value
111      */
112     @UnsupportedAppUsage
getTextString()113     public byte[] getTextString() {
114         byte[] byteArray = new byte[mData.length];
115 
116         System.arraycopy(mData, 0, byteArray, 0, mData.length);
117         return byteArray;
118     }
119 
120     /**
121      * Set Text-string value.
122      *
123      * @param textString the Text-string value
124      * @throws NullPointerException if Text-string value is null.
125      */
126     @UnsupportedAppUsage
setTextString(byte[] textString)127     public void setTextString(byte[] textString) {
128         if(null == textString) {
129             throw new NullPointerException("EncodedStringValue: Text-string is null.");
130         }
131 
132         mData = new byte[textString.length];
133         System.arraycopy(textString, 0, mData, 0, textString.length);
134     }
135 
136     /**
137      * Convert this object to a {@link java.lang.String}. If the encoding of
138      * the EncodedStringValue is null or unsupported, it will be
139      * treated as iso-8859-1 encoding.
140      *
141      * @return The decoded String.
142      */
143     @UnsupportedAppUsage
getString()144     public String getString()  {
145         if (CharacterSets.ANY_CHARSET == mCharacterSet) {
146             return new String(mData); // system default encoding.
147         } else {
148             try {
149                 String name = CharacterSets.getMimeName(mCharacterSet);
150                 return new String(mData, name);
151             } catch (UnsupportedEncodingException e) {
152             	if (LOCAL_LOGV) {
153             		Log.v(TAG, e.getMessage(), e);
154             	}
155             	try {
156                     return new String(mData, CharacterSets.MIMENAME_ISO_8859_1);
157                 } catch (UnsupportedEncodingException e2) {
158                     return new String(mData); // system default encoding.
159                 }
160             }
161         }
162     }
163 
164     /**
165      * Append to Text-string.
166      *
167      * @param textString the textString to append
168      * @throws NullPointerException if the text String is null
169      *                      or an IOException occurred.
170      */
171     @UnsupportedAppUsage
appendTextString(byte[] textString)172     public void appendTextString(byte[] textString) {
173         if(null == textString) {
174             throw new NullPointerException("Text-string is null.");
175         }
176 
177         if(null == mData) {
178             mData = new byte[textString.length];
179             System.arraycopy(textString, 0, mData, 0, textString.length);
180         } else {
181             ByteArrayOutputStream newTextString = new ByteArrayOutputStream();
182             try {
183                 newTextString.write(mData);
184                 newTextString.write(textString);
185             } catch (IOException e) {
186                 e.printStackTrace();
187                 throw new NullPointerException(
188                         "appendTextString: failed when write a new Text-string");
189             }
190 
191             mData = newTextString.toByteArray();
192         }
193     }
194 
195     /*
196      * (non-Javadoc)
197      * @see java.lang.Object#clone()
198      */
199     @Override
clone()200     public Object clone() throws CloneNotSupportedException {
201         super.clone();
202         int len = mData.length;
203         byte[] dstBytes = new byte[len];
204         System.arraycopy(mData, 0, dstBytes, 0, len);
205 
206         try {
207             return new EncodedStringValue(mCharacterSet, dstBytes);
208         } catch (Exception e) {
209             Log.e(TAG, "failed to clone an EncodedStringValue: " + this);
210             e.printStackTrace();
211             throw new CloneNotSupportedException(e.getMessage());
212         }
213     }
214 
215     /**
216      * Split this encoded string around matches of the given pattern.
217      *
218      * @param pattern the delimiting pattern
219      * @return the array of encoded strings computed by splitting this encoded
220      *         string around matches of the given pattern
221      */
split(String pattern)222     public EncodedStringValue[] split(String pattern) {
223         String[] temp = getString().split(pattern);
224         EncodedStringValue[] ret = new EncodedStringValue[temp.length];
225         for (int i = 0; i < ret.length; ++i) {
226             try {
227                 ret[i] = new EncodedStringValue(mCharacterSet,
228                         temp[i].getBytes());
229             } catch (NullPointerException e) {
230                 // Can't arrive here
231                 return null;
232             }
233         }
234         return ret;
235     }
236 
237     /**
238      * Extract an EncodedStringValue[] from a given String.
239      */
240     @UnsupportedAppUsage
extract(String src)241     public static EncodedStringValue[] extract(String src) {
242         String[] values = src.split(";");
243 
244         ArrayList<EncodedStringValue> list = new ArrayList<EncodedStringValue>();
245         for (int i = 0; i < values.length; i++) {
246             if (values[i].length() > 0) {
247                 list.add(new EncodedStringValue(values[i]));
248             }
249         }
250 
251         int len = list.size();
252         if (len > 0) {
253             return list.toArray(new EncodedStringValue[len]);
254         } else {
255             return null;
256         }
257     }
258 
259     /**
260      * Concatenate an EncodedStringValue[] into a single String.
261      */
262     @UnsupportedAppUsage
concat(EncodedStringValue[] addr)263     public static String concat(EncodedStringValue[] addr) {
264         StringBuilder sb = new StringBuilder();
265         int maxIndex = addr.length - 1;
266         for (int i = 0; i <= maxIndex; i++) {
267             sb.append(addr[i].getString());
268             if (i < maxIndex) {
269                 sb.append(";");
270             }
271         }
272 
273         return sb.toString();
274     }
275 
276     @UnsupportedAppUsage
copy(EncodedStringValue value)277     public static EncodedStringValue copy(EncodedStringValue value) {
278         if (value == null) {
279             return null;
280         }
281 
282         return new EncodedStringValue(value.mCharacterSet, value.mData);
283     }
284 
285     @UnsupportedAppUsage
encodeStrings(String[] array)286     public static EncodedStringValue[] encodeStrings(String[] array) {
287         int count = array.length;
288         if (count > 0) {
289             EncodedStringValue[] encodedArray = new EncodedStringValue[count];
290             for (int i = 0; i < count; i++) {
291                 encodedArray[i] = new EncodedStringValue(array[i]);
292             }
293             return encodedArray;
294         }
295         return null;
296     }
297 }
298