Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: fi/kvanttisofta/sms/SmsPduCodec.java


1   //
2   // Copyright (c) 2001 Kvanttisofta oy.  All rights reserved.
3   //
4   //
5   // SMS PDU coder/encoder class.
6   // (aspa@users.sourceforge.net).
7   //
8   // $Id: SmsPduCodec.java,v 1.1.1.1 2001/04/18 04:19:00 aspa Exp $.
9   //
10  // (based on info from: http://www.sics.se/~lpe/help/sms/)
11  //
12  // TODO:
13  // - more characters in GSM <==> ISO-8859-1 mapping.
14  // - GSM 7-bit alphabet extension table character support.
15  //
16  //
17  
18  //
19  // NB1: with jikes you have to use the '-encoding 8859_1' option.
20  //
21  
22  package fi.kvanttisofta.sms;
23  
24  public class SmsPduCodec {
25      private static final char EMPTYCHAR = 0x100;
26      private static final char EXTTABLEESCAPE = 0x1B;
27      private static char[] gsmToIsoMap; // GSM ==> ISO88591 
28      private static char[] gsmToIsoExtMap;
29      private static char[] isoToGsmMap; // ISO88591 ==> GSM
30      private static char[] isoToGsmExtMap;
31  
32      private static char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7',
33            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
34      };
35  
36      // swaps characters of every two character substring of a string.
37      public static String swapDigits(String str) {
38    if( str == null )
39        return str;
40    
41    int strlen = str.length();
42    StringBuffer sb = new StringBuffer(strlen);
43  
44    for(int i=0; (i+1) < strlen; i=i+2) {
45        sb.append(str.charAt(i+1));
46        sb.append(str.charAt(i));
47    }
48    return new String(sb);
49      }
50  
51      // returns a hex string representation of a 8 bit integer.
52      public static String toHexString(int b) {
53    char[] digits = new char[2];
54    b = b & 255;
55  
56    digits[0] = hexDigits[b / 0x10];
57    digits[1] = hexDigits[b % 0x10];
58  
59    return new String(digits);
60      }
61  
62      // returns an input string as a hex string. for debugging.
63      public static String hexDump(String s) {
64    StringBuffer dump = new StringBuffer();
65    for(int i = 0; i<s.length(); i++)
66        dump.append(SmsPduCodec.toHexString(s.charAt(i)));
67    return new String(dump);
68      }
69  
70      // converts a string of 7 bit characters to a sequence of
71      // of 8 bit bytes encoded as hex strings.
72      public static String sevenBitEncode(String message) {
73    if(message == null)
74        return message;
75    StringBuffer msg = new StringBuffer(message);
76  
77    StringBuffer encmsg = new StringBuffer(2*160);
78    int bb = 0, bblen = 0, i;
79    char o=0, c=0, tc;
80  
81    for(i=0; i < msg.length() || bblen>=8; i++) {
82        if(i<msg.length()) {
83      c = msg.charAt(i);
84      tc = isoToGsmMap[c];
85      /*
86        if(tc == EXTTABLEESCAPE) {
87        //msg.insert(i+1, isoToGsmExtMap[c]);
88        }
89      */
90      c = tc;
91  
92      c &= ~(1 << 7); // clear (discard) eight bit.
93      bb |= (c << bblen); // insert c to bb.
94      bblen += 7;    
95        }
96  
97        while(bblen >= 8) { // we have a full octet.
98      o = (char) (bb & 255); // take 8 bits.
99      encmsg.append(SmsPduCodec.toHexString(o));
100     bb >>>= 8;
101     bblen -= 8;
102       }
103 
104   } // end: for(i=0; i<msglen || bblen>=8; i++) {
105 
106   if( (bblen > 0) )
107       encmsg.append(SmsPduCodec.toHexString(bb));
108 
109   return encmsg.toString();
110     }
111 
112     public static String sevenBitDecode(String encmsg) {
113   return sevenBitDecode(encmsg, encmsg.length());
114     }
115 
116     // converts a sequence of 8 bit bytes encoded as hex
117     // strings to a string of 7 bit characters.
118     public static String sevenBitDecode(String encmsg, int msglen)
119   throws NumberFormatException {
120   // encmsg: encoded string to decode.
121   // msglen: the requested number of characters to decode.
122 
123   int i, o, r=0, rlen=0, olen=0, charcnt=0; // ints are 32 bit long.
124   StringBuffer msg = new StringBuffer(160);
125   int encmsglen = encmsg.length();
126   String ostr;
127   boolean exttableescape = false;
128   char c;
129 
130   // assumes even number of chars in octet string.
131   for(i=0; ((i+1)<encmsglen) && (charcnt<msglen); i=i+2) {
132       ostr = encmsg.substring(i, i+2);
133       o = Integer.parseInt(ostr, 16);
134       olen = 8;
135 
136       if(rlen >= 7) { // take a full char off remainder.
137     c = (char) (r & 127);
138     r >>>= 7;
139     rlen -= 7;
140     msg.append(c);
141     charcnt++;
142       }
143 
144       o <<= rlen; // push remainding bits from r to o.
145       o |= r;
146       olen += rlen;
147 
148       c = (char) (o & 127); // get first 7 bits from o.
149       o >>>= 7;
150       olen -= 7;
151 
152       r = o; // put remainding bits from o to r.
153       rlen = olen;
154 
155       // handle character conversion.
156       c = gsmToIsoMap[c];
157 
158       if( c == EXTTABLEESCAPE ) { // ext table character handling.
159     exttableescape = true;
160     continue;
161       } else if( exttableescape == true) {
162     exttableescape = false;
163     c = gsmToIsoExtMap[c];
164       }
165 
166       msg.append(c);
167       charcnt++;
168   } // end: for(i=0; ((i+1)<encmsglen) && (charcnt<msglen); i=i+2) {
169 
170   if( (rlen>0) && (charcnt<msglen) )
171       msg.append((char)r);
172 
173   return msg.toString();
174     }
175 
176     // class initialization.
177     static {
178   // construct GSM alphabet to/from ISO mappings.
179   char[] gsmiso = { 0, '@', 1, '£', 2, '$', 14, 'Å', 15, 'å', 17, '_',
180         91, 'Ä', 92, 'Ö', 95, '§', 123, 'ä', 124, 'ö'
181   };
182   char[] gsmisoext = { 0x14, '^', 0x28, '{', 0x29, '}', 0x2f, '\\',
183            0x3c, '[', 0x3d, '~', 0x3e, ']', 0x40, '|'
184   };
185 
186   final int lastindex = 255;
187   gsmToIsoMap = new char[lastindex+1];    // one too many allocated
188   gsmToIsoExtMap = new char[lastindex+1];
189   isoToGsmMap = new char[lastindex+1];
190   isoToGsmExtMap = new char[lastindex+1];
191   int i, gsmisolen, gsmisoextlen;
192   
193   for(i=0; i<=lastindex; i++) {
194       gsmToIsoMap[i] = gsmToIsoExtMap[i] = isoToGsmMap[i] = (char)i;
195   }
196 
197   gsmisolen = gsmiso.length;
198   for(i = 0; (i+1) < gsmisolen; i=i+2) {
199       gsmToIsoMap[(int)gsmiso[i]] = gsmiso[i+1];
200       isoToGsmMap[(int)gsmiso[i+1]] = gsmiso[i];
201   }
202 
203   gsmisoextlen = gsmisoext.length;
204   for(i = 0; (i+1) < gsmisoextlen; i=i+2) {
205             gsmToIsoExtMap[gsmisoext[i]] = gsmisoext[i+1];
206       //isoToGsmExtMap[gsmisoext[i+1]] = gsmisoext[i];
207       //isoToGsmMap[gsmisoext[i+1]] = EXTTABLEESCAPE;
208         }
209 
210     }
211 
212     public static void main(String[] args) {
213   // test encoding and decoding a string.
214   String s1 = "hellohello";
215   String s1enc_orig = new String("E8329BFD4697D9EC37");
216   String s1enc_my = sevenBitEncode(s1);
217   String s1dec = sevenBitDecode(s1enc_my, s1.length());
218   System.err.println("s1enc str:  " + s1enc_my + ", dec: " + s1dec);
219   System.err.println("hellohello: " + s1enc_orig);
220 
221   // test encoding and decoding a string. len: 7*8.
222   System.err.println("");
223   String s3 = "tama on pitka viesti. tuleeko tama oikein. jos ei miksi?";
224   System.err.println("s3 len: " + s3.length());
225   String s3enc = sevenBitEncode(s3);
226   String s3dec = sevenBitDecode(s3enc, s3.length());
227   System.err.println("s3:    " + s3);
228   System.err.println("s3enc: " + s3enc);
229   System.err.println("s3dec: " + s3dec);
230 
231     }
232 
233 }