View Javadoc

1   /* ***** BEGIN LICENSE BLOCK *****
2    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3    *
4    * The contents of this file are subject to the Mozilla Public License Version
5    * 1.1 (the "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    * http://www.mozilla.org/MPL/
8    *
9    * Software distributed under the License is distributed on an "AS IS" basis,
10   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11   * for the specific language governing rights and limitations under the
12   * License.
13   *
14   * The Original Code is "SMS Library for the Java platform".
15   *
16   * The Initial Developer of the Original Code is Markus Eriksson.
17   * Portions created by the Initial Developer are Copyright (C) 2002
18   * the Initial Developer. All Rights Reserved.
19   *
20   * Contributor(s):
21   *
22   * Alternatively, the contents of this file may be used under the terms of
23   * either the GNU General Public License Version 2 or later (the "GPL"), or
24   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
25   * in which case the provisions of the GPL or the LGPL are applicable instead
26   * of those above. If you wish to allow use of your version of this file only
27   * under the terms of either the GPL or the LGPL, and not to allow others to
28   * use your version of this file under the terms of the MPL, indicate your
29   * decision by deleting the provisions above and replace them with the notice
30   * and other provisions required by the GPL or the LGPL. If you do not delete
31   * the provisions above, a recipient may use your version of this file under
32   * the terms of any one of the MPL, the GPL or the LGPL.
33   *
34   * ***** END LICENSE BLOCK ***** */
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 }