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