1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 package org.marre.sms;
36
37 import java.io.ByteArrayOutputStream;
38 import java.io.IOException;
39
40 /***
41 * Toolkit class for SmsUdhElement objects.
42 *
43 * @author Markus Eriksson
44 * @version $Id: SmsUdhUtil.java,v 1.5 2005/05/06 13:55:11 c95men Exp $
45 */
46 public final class SmsUdhUtil
47 {
48 /***
49 * Constructor for SmsUdhUtil.
50 */
51 private SmsUdhUtil()
52 {
53 }
54
55 /***
56 * Calculates the number of bytes needed for the supplied udh elements.
57 *
58 * @param theUdhElements The udh elements
59 * @return The size (in bytes)
60 */
61 public static int getTotalSize(SmsUdhElement[] theUdhElements)
62 {
63 int totLength = 0;
64
65 if (theUdhElements == null)
66 {
67 return 0;
68 }
69
70 for (int i = 0; i < theUdhElements.length; i++)
71 {
72 totLength += theUdhElements[i].getTotalSize();
73 }
74
75 return totLength;
76 }
77
78 /***
79 * Returns the whole udh as a byte array.
80 * <p>
81 * The returned UDH is the same as specified when the message was created.
82 * No concat headers are added.
83 *
84 * TODO: Rename this function. The name is totally wrong.
85 *
86 * @return the UDH elements as a byte array.
87 */
88 public static byte[] toByteArray(SmsUdhElement[] theUdhElements)
89 {
90 ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
91
92 if (theUdhElements == null)
93 {
94 return new byte[0];
95 }
96
97 baos.write((byte) SmsUdhUtil.getTotalSize(theUdhElements));
98
99 try
100 {
101 for (int i = 0; i < theUdhElements.length; i++)
102 {
103 theUdhElements[i].writeTo(baos);
104 }
105 }
106 catch (IOException ioe)
107 {
108 throw new RuntimeException(ioe);
109 }
110
111 return baos.toByteArray();
112 }
113
114 /***
115 * Calculates if the given data needs a concatenated SMS.
116 *
117 * @param ud User data
118 * @param udh UDH elements
119 * @return true if the message must be concatentated.
120 */
121 public static boolean isConcat(SmsUserData ud, byte[] udh)
122 {
123 int udLength = ud.getLength();
124
125 int bytesLeft = 140;
126 int maxChars;
127
128 if (udh != null)
129 {
130 bytesLeft -= udh.length;
131 }
132
133 switch (ud.getDcs().getAlphabet())
134 {
135 case SmsDcs.ALPHABET_GSM:
136 maxChars = (bytesLeft * 8) / 7;
137 break;
138
139 case SmsDcs.ALPHABET_UCS2:
140 maxChars = bytesLeft / 2;
141 break;
142
143 case SmsDcs.ALPHABET_8BIT:
144 default:
145 maxChars = bytesLeft;
146 break;
147 }
148
149 return (udLength > maxChars);
150 }
151
152 /***
153 * Creates a "8Bit concatenated" UDH element using UDH_IEI_CONCATENATED_8BIT.
154 *
155 * This can be used to create a concatenated SMS.
156 *
157 * @param theRefNr The reference number of this SMS, must be the same in
158 * all SMS. Max 255.
159 * @param theTotSms Total number of SMS. Max 255.
160 * @param theSeqNr Sequence number. Max 255.
161 * @return A SmsUdhElement
162 */
163 public static SmsUdhElement get8BitConcatUdh(int theRefNr, int theTotSms, int theSeqNr)
164 {
165 byte[] udh = new byte[3];
166
167 udh[0] = (byte) (theRefNr & 0xff);
168 udh[1] = (byte) (theTotSms & 0xff);
169 udh[2] = (byte) (theSeqNr & 0xff);
170
171 return new SmsUdhElement(SmsConstants.UDH_IEI_CONCATENATED_8BIT, udh);
172 }
173
174 /***
175 * Creates a "Message waiting" UDH element using UDH_IEI_SPECIAL_MESSAGE.
176 * <p>
177 * If more than one type of message is required to be indicated within
178 * one SMS message, then multiple "Message waiting" UDH elements must
179 * be used.
180 * <p>
181 * <b>Special handling in concatenated messages:</b><br>
182 * <i>
183 * "In the case where this IEI is to be used in a concatenated SM then the
184 * IEI, its associated IEI length and IEI data shall be contained in the
185 * first segment of the concatenated SM. The IEI, its associated IEI length
186 * and IEI data should also be contained in every subsequent segment of the
187 * concatenated SM although this is not mandatory. However, in the case
188 * where these elements are not contained in every subsequent segment of
189 * the concatenated SM and where an out of sequence segment delivery
190 * occurs or where the first segment is not delivered then processing
191 * difficulties may arise at the receiving entity which may result in
192 * the concatenated SM being totally or partially discarded."
193 * </i>
194 *
195 * @param storeMsg Set to true if the message should be stored
196 * @param theMsgType Message type, may be one of MESSAGE_WAITING_VOICE,
197 * MESSAGE_WAITING_FAX, MESSAGE_WAITING_EMAIL or MESSAGE_WAITING_OTHER.
198 * @param theMsgCount Number of messages waiting for retrieval. Max 255
199 * messages. The value 255 shall be taken to mean 255 or greater.
200 * @return A SmsUdhElement
201 */
202 public static SmsUdhElement getMessageWaitingUdh(boolean storeMsg, int theMsgType, int theMsgCount)
203 {
204 byte[] udh = new byte[2];
205
206 udh[0] = (byte) (theMsgType & 0x7f);
207 if ( storeMsg )
208 {
209 udh[0] |= (byte) (0x80);
210 }
211 udh[1] = (byte) (theMsgCount & 0xff);
212
213 return new SmsUdhElement(SmsConstants.UDH_IEI_SPECIAL_MESSAGE, udh);
214 }
215
216 /***
217 * Creates a "8 bit Application Port Adressing" UDH element
218 * using UDH_IEI_APP_PORT_8BIT
219 * <p>
220 * Note! Only values between 240 and 255 are usable, the rest of the port
221 * numbers are marked as reserved.
222 * <p>
223 * <b>Special handling in concatenated messages:</b><br>
224 * <i>
225 * In the case where this IE is to be used in a concatenated SM then the
226 * IEI, its associated IEI length and IEI data shall be contained in the
227 * first segment of the concatenated SM. The IEI, its associated IEI length
228 * and IEI data shall also be contained in every subsequent segment of the
229 * concatenated SM.
230 * </i>
231 * @param theDestPort Destination port
232 * @param theOrigPort Source port
233 * @return A SmsUdhElement
234 */
235 public static SmsUdhElement get8BitApplicationPortUdh(int theDestPort, int theOrigPort)
236 {
237 byte[] udh = new byte[2];
238
239 udh[0] = (byte) (theDestPort & 0xff);
240 udh[1] = (byte) (theOrigPort & 0xff);
241
242 return new SmsUdhElement(SmsConstants.UDH_IEI_APP_PORT_8BIT, udh);
243 }
244
245 /***
246 * Creates a "16 bit Application Port Adressing" UDH element
247 * using UDH_IEI_APP_PORT_16BIT
248 * <p>
249 * Note! Only values between 0 and 16999 are usable, the rest of the port
250 * numbers are marked as reserved.
251 * <p>
252 * <b>Special handling in concatenated messages:</b><br>
253 * <i>
254 * In the case where this IE is to be used in a concatenated SM then the
255 * IEI, its associated IEI length and IEI data shall be contained in the
256 * first segment of the concatenated SM. The IEI, its associated IEI length
257 * and IEI data shall also be contained in every subsequent segment of the
258 * concatenated SM.
259 * </i>
260 * @param theDestPort Destination port
261 * @param theOrigPort Source port
262 * @return A SmsUdhElement
263 */
264 public static SmsUdhElement get16BitApplicationPortUdh(int theDestPort, int theOrigPort)
265 {
266 byte[] udh = new byte[4];
267
268 udh[0] = (byte) ((theDestPort >> 8) & 0xff);
269 udh[1] = (byte) (theDestPort & 0xff);
270 udh[2] = (byte) ((theOrigPort >> 8) & 0xff);
271 udh[3] = (byte) (theOrigPort & 0xff);
272
273 return new SmsUdhElement(SmsConstants.UDH_IEI_APP_PORT_16BIT, udh);
274 }
275
276 /***
277 * Creates a "16Bit concatenated" UDH element using UDH_IEI_CONCATENATED_16BIT
278 * <p>
279 * This can be used to create a concatenated SMS.
280 *
281 * @param theRefNr The reference number of this SMS, must be the same in
282 * all SMS. Max 65536
283 * @param theTotSms Total number of SMS. Max 255
284 * @param theSeqNr Sequence number. Max 255
285 * @return A SmsUdhElement
286 */
287 public static SmsUdhElement get16BitConcatUdh(int theRefNr, int theTotSms, int theSeqNr)
288 {
289 byte[] udh = new byte[4];
290
291 udh[0] = (byte) ((theRefNr >> 8) & 0xff);
292 udh[1] = (byte) (theRefNr & 0xff);
293 udh[2] = (byte) (theTotSms & 0xff);
294 udh[3] = (byte) (theSeqNr & 0xff);
295
296 return new SmsUdhElement(SmsConstants.UDH_IEI_CONCATENATED_16BIT, udh);
297 }
298
299 /***
300 * Creates a "EMS Text Formatting" UDH element.
301 *
302 * @param theStartPos Start position of the text formatting. This position
303 * is relative to the start of the UD field of the PDU.
304 * @param theFormatLen The number of character to format. If 0 it sets the
305 * default text formatting.
306 * @param theAlignment Can be any of EMS_TEXT_ALIGN_*
307 * @param theFontSize Can be any of EMS_TEXT_SIZE_*
308 * @param theStyle Can be any of EMS_TEXT_STYLE_*
309 * @param theForegroundColor Can be any of EMS_TEXT_COLOR_*
310 * @param theBackgroundColor Can be any of EMS_TEXT_COLOR_*
311 * @return A SmsUdhElement
312 */
313 public static SmsUdhElement getEmsTextFormattingUdh(int theStartPos, int theFormatLen,
314 byte theAlignment, byte theFontSize, byte theStyle, byte theForegroundColor, byte theBackgroundColor)
315 {
316 byte[] udh = new byte[4];
317
318 udh[0] = (byte) (theStartPos & 0xff);
319 udh[1] = (byte) (theFormatLen & 0xff);
320 udh[2] = (byte) (( (theAlignment & 0x03) | (theFontSize & 0x0C) | (theStyle & 0xF0) ) & 0xff);
321 udh[3] = (byte) (( (theForegroundColor & 0x0f) | (((theBackgroundColor & 0x0f) << 4) & 0xf0) ) & 0xff);
322
323 return new SmsUdhElement(SmsConstants.UDH_IEI_EMS_TEXT_FORMATTING, udh);
324 }
325
326 /***
327 * Creates an ems user defined sound udh.
328 *
329 * @param theIMelody The imelody data
330 * @param position The position
331 * @return An SmsUdhElement with a user defined sound
332 */
333 public static SmsUdhElement getEmsUserDefinedSoundUdh(byte[] theIMelody, int position)
334 {
335 int iMelodyLength = theIMelody.length;
336 byte[] udh = new byte[iMelodyLength + 1];
337 udh[0] = (byte) position;
338 System.arraycopy(theIMelody, 0, udh, 1, iMelodyLength);
339
340 return new SmsUdhElement(SmsConstants.UDH_IEI_EMS_USER_DEFINED_SOUND, udh);
341 }
342
343 /***
344 * Creates an ems user prompt indicator udh.
345 *
346 * @param numFragments Number of fragments
347 * @return An SmsUdhElement with an user prompt indicator
348 */
349 public static SmsUdhElement getEmsUserPromptIndicatorUdh(int numFragments)
350 {
351 byte[] udh = new byte[1];
352 udh[0] = (byte) numFragments;
353
354 return new SmsUdhElement(SmsConstants.UDH_IEI_EMS_USER_PROMPT, udh);
355 }
356
357 /***
358 * Creates an ems variable picture udh.
359 *
360 * @param bitmap The bitmap data
361 * @param width The width of the bitmap (in pixels)
362 * @param height The height of the bitmap (in pixels)
363 * @param position The position of the bitmap
364 * @return An SmsUdhElement with the bitmap
365 */
366 public static SmsUdhElement getEmsVariablePictureUdh(byte[] bitmap, int width, int height, int position)
367 {
368 int otaBitmapLength = bitmap.length;
369 byte[] udh = new byte[otaBitmapLength + 3];
370
371 udh[0] = (byte) position;
372 udh[1] = (byte) (width / 8);
373 udh[2] = (byte) height;
374
375 System.arraycopy(bitmap, 0, udh, 3, otaBitmapLength);
376
377 return new SmsUdhElement(SmsConstants.UDH_IEI_EMS_VARIABLE_PICTURE, udh);
378 }
379 }