ruby_ucp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +42 -0
- data/LICENSE +505 -0
- data/README +10 -0
- data/Rakefile +118 -0
- data/Rakefile.orig +45 -0
- data/VERSION +1 -0
- data/lib/ruby_ucp.rb +42 -0
- data/lib/samples/main.rb +182 -0
- data/lib/ucp/base.rb +24 -0
- data/lib/ucp/pdu/base.rb +22 -0
- data/lib/ucp/pdu/ucp01.rb +37 -0
- data/lib/ucp/pdu/ucp01_operation.rb +61 -0
- data/lib/ucp/pdu/ucp01_result.rb +60 -0
- data/lib/ucp/pdu/ucp30.rb +28 -0
- data/lib/ucp/pdu/ucp30_operation.rb +59 -0
- data/lib/ucp/pdu/ucp30_result.rb +63 -0
- data/lib/ucp/pdu/ucp31.rb +29 -0
- data/lib/ucp/pdu/ucp31_operation.rb +50 -0
- data/lib/ucp/pdu/ucp31_result.rb +61 -0
- data/lib/ucp/pdu/ucp51_operation.rb +167 -0
- data/lib/ucp/pdu/ucp51_result.rb +64 -0
- data/lib/ucp/pdu/ucp52_operation.rb +31 -0
- data/lib/ucp/pdu/ucp52_result.rb +31 -0
- data/lib/ucp/pdu/ucp53_operation.rb +31 -0
- data/lib/ucp/pdu/ucp53_result.rb +31 -0
- data/lib/ucp/pdu/ucp54_operation.rb +31 -0
- data/lib/ucp/pdu/ucp54_result.rb +31 -0
- data/lib/ucp/pdu/ucp55_operation.rb +31 -0
- data/lib/ucp/pdu/ucp55_result.rb +31 -0
- data/lib/ucp/pdu/ucp56_operation.rb +31 -0
- data/lib/ucp/pdu/ucp56_result.rb +31 -0
- data/lib/ucp/pdu/ucp57_operation.rb +31 -0
- data/lib/ucp/pdu/ucp57_result.rb +31 -0
- data/lib/ucp/pdu/ucp58_operation.rb +31 -0
- data/lib/ucp/pdu/ucp58_result.rb +31 -0
- data/lib/ucp/pdu/ucp5x.rb +40 -0
- data/lib/ucp/pdu/ucp60.rb +30 -0
- data/lib/ucp/pdu/ucp60_operation.rb +58 -0
- data/lib/ucp/pdu/ucp60_result.rb +60 -0
- data/lib/ucp/pdu/ucp61.rb +31 -0
- data/lib/ucp/pdu/ucp61_operation.rb +49 -0
- data/lib/ucp/pdu/ucp61_result.rb +60 -0
- data/lib/ucp/pdu/ucp_operation.rb +27 -0
- data/lib/ucp/pdu/ucp_result.rb +26 -0
- data/lib/ucp/pdu/ucpmessage.rb +125 -0
- data/lib/ucp/util/base.rb +22 -0
- data/lib/ucp/util/gsm_packed_msg.rb +50 -0
- data/lib/ucp/util/packed_msg.rb +34 -0
- data/lib/ucp/util/sms_request.rb +48 -0
- data/lib/ucp/util/ucp.rb +885 -0
- data/lib/ucp/util/ucp_client.rb +207 -0
- data/lib/ucp/util/ucp_server.rb +122 -0
- data/lib/ucp/util/ucs2_packed_msg.rb +29 -0
- metadata +120 -0
data/lib/ucp/util/ucp.rb
ADDED
@@ -0,0 +1,885 @@
|
|
1
|
+
=begin
|
2
|
+
Ruby library implementation of EMI/UCP protocol v4.6 for SMS
|
3
|
+
Copyright (C) 2011, Sergio Freire <sergio.freire@gmail.com>
|
4
|
+
|
5
|
+
This library is free software; you can redistribute it and/or
|
6
|
+
modify it under the terms of the GNU Lesser General Public
|
7
|
+
License as published by the Free Software Foundation; either
|
8
|
+
version 2.1 of the License, or (at your option) any later version.
|
9
|
+
|
10
|
+
This library is distributed in the hope that it will be useful,
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
13
|
+
Lesser General Public License for more details.
|
14
|
+
|
15
|
+
You should have received a copy of the GNU Lesser General Public
|
16
|
+
License along with this library; if not, write to the Free Software
|
17
|
+
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18
|
+
=end
|
19
|
+
|
20
|
+
|
21
|
+
require "iconv"
|
22
|
+
|
23
|
+
$KCODE = 'UTF8'
|
24
|
+
require 'jcode'
|
25
|
+
|
26
|
+
include Ucp::Pdu
|
27
|
+
|
28
|
+
class Ucp::Util::UCP
|
29
|
+
|
30
|
+
@gsmtable={}
|
31
|
+
@asciitable={}
|
32
|
+
@extensiontable={}
|
33
|
+
@extensiontable_rev={}
|
34
|
+
|
35
|
+
:private
|
36
|
+
def self.add_char(value,char)
|
37
|
+
@gsmtable[char]=value
|
38
|
+
@asciitable[value]=char
|
39
|
+
end
|
40
|
+
|
41
|
+
:private
|
42
|
+
def self.add_extchar(value,char)
|
43
|
+
@extensiontable[char]=value
|
44
|
+
@extensiontable_rev[value]=char
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.initialize_ascii2ira
|
48
|
+
|
49
|
+
('A'..'Z').each { |c|
|
50
|
+
add_char(c[0],c)
|
51
|
+
}
|
52
|
+
('a'..'z').each { |c|
|
53
|
+
#@gsmtable[c]=c[0]
|
54
|
+
#@asciitable[c[0]]=c
|
55
|
+
add_char(c[0],c)
|
56
|
+
}
|
57
|
+
('0'..'9').each { |c|
|
58
|
+
add_char(c[0],c)
|
59
|
+
}
|
60
|
+
|
61
|
+
|
62
|
+
add_char(0x00,"@")
|
63
|
+
add_char(0x01,"£")
|
64
|
+
add_char(0x02,"$")
|
65
|
+
#add_char(0x03," ")
|
66
|
+
add_char(0x04,"è")
|
67
|
+
add_char(0x05,"é")
|
68
|
+
add_char(0x06,"ù")
|
69
|
+
add_char(0x07,"ì")
|
70
|
+
add_char(0x08,"ò")
|
71
|
+
add_char(0x09,"Ç")
|
72
|
+
add_char(0x0A,"\n")
|
73
|
+
#add_char(0x0B," ")
|
74
|
+
#add_char(0x0C," ")
|
75
|
+
add_char(0x0D,"\r")
|
76
|
+
#add_char(0x0E,"A")
|
77
|
+
#add_char(0x0F,"a")
|
78
|
+
|
79
|
+
add_char(0x1F,"É")
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
add_char(0x20," ")
|
84
|
+
add_char(0x21,"!")
|
85
|
+
add_char(0x22,'"')
|
86
|
+
add_char(0x23,"#")
|
87
|
+
#add_char(0x24," ")
|
88
|
+
add_char(0x25,"%")
|
89
|
+
add_char(0x26,"&")
|
90
|
+
add_char(0x27,"'")
|
91
|
+
add_char(0x28,"(")
|
92
|
+
add_char(0x29,")")
|
93
|
+
add_char(0x2A,"*")
|
94
|
+
add_char(0x2B,"+")
|
95
|
+
add_char(0x2C,",")
|
96
|
+
add_char(0x2D,"-")
|
97
|
+
add_char(0x2E,".")
|
98
|
+
add_char(0x2F,"/")
|
99
|
+
|
100
|
+
add_char(0x3A,":")
|
101
|
+
add_char(0x3B,";")
|
102
|
+
add_char(0x3C,"<")
|
103
|
+
add_char(0x3D,"=")
|
104
|
+
add_char(0x3E,">")
|
105
|
+
add_char(0x3F,"?")
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
#@extensiontable["€"]=0x65
|
110
|
+
#@extensiontable_rev[0x65]="€"
|
111
|
+
add_extchar(0x65,"€")
|
112
|
+
add_extchar(0x14,"^")
|
113
|
+
add_extchar(0x28,"{")
|
114
|
+
add_extchar(0x29,"}")
|
115
|
+
add_extchar(0x2F,"\\")
|
116
|
+
add_extchar(0x3C,"[")
|
117
|
+
add_extchar(0x3D,"~")
|
118
|
+
add_extchar(0x3E,"]")
|
119
|
+
add_extchar(0x40,"|")
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.pack7bits(str)
|
126
|
+
#UCP.initialize_ascii2ira
|
127
|
+
|
128
|
+
s=""
|
129
|
+
str.each_char { |c|
|
130
|
+
|
131
|
+
ext=""
|
132
|
+
gsmchar=@gsmtable[c]
|
133
|
+
|
134
|
+
if gsmchar.nil?
|
135
|
+
if @extensiontable.has_key?(c)
|
136
|
+
ext="0011011" # 1B
|
137
|
+
gsmchar=@extensiontable[c]
|
138
|
+
else
|
139
|
+
gsmchar=@gsmtable[" "]
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
#gsmchar=c[0]
|
144
|
+
#puts "#{c} : #{gsmchar} xxx"
|
145
|
+
#gsmchar=@gsmtable[" "] if gsmchar.nil?
|
146
|
+
|
147
|
+
tmp= gsmchar.to_s(2)
|
148
|
+
|
149
|
+
remainder=tmp.length%7
|
150
|
+
if remainder!=0
|
151
|
+
nfillbits=7-remainder
|
152
|
+
tmp="0"*nfillbits+tmp
|
153
|
+
end
|
154
|
+
|
155
|
+
s=tmp+ext+s
|
156
|
+
|
157
|
+
}
|
158
|
+
|
159
|
+
remainder=s.length%8
|
160
|
+
if remainder!=0
|
161
|
+
nfillbits=8-remainder
|
162
|
+
s="0"*nfillbits+s
|
163
|
+
end
|
164
|
+
|
165
|
+
#puts "S: #{s}"
|
166
|
+
|
167
|
+
i=s.length-8
|
168
|
+
hexstr=""
|
169
|
+
while i>=0
|
170
|
+
c=s[i,8]
|
171
|
+
|
172
|
+
tmp=c.to_i(2).to_s(16).upcase
|
173
|
+
if tmp.length==1
|
174
|
+
tmp="0"+tmp
|
175
|
+
end
|
176
|
+
# puts tmp
|
177
|
+
hexstr+=tmp
|
178
|
+
i-=8
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
|
183
|
+
return hexstr
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
def self.pack7bits2(str,max_bytes)
|
188
|
+
|
189
|
+
tainted=false
|
190
|
+
s=""
|
191
|
+
idx=0
|
192
|
+
str.each_char { |c|
|
193
|
+
|
194
|
+
ext=""
|
195
|
+
gsmchar=@gsmtable[c]
|
196
|
+
|
197
|
+
if gsmchar.nil?
|
198
|
+
if @extensiontable.has_key?(c)
|
199
|
+
ext="0011011" # 1B
|
200
|
+
gsmchar=@extensiontable[c]
|
201
|
+
else
|
202
|
+
gsmchar=@gsmtable[" "]
|
203
|
+
tainted=true
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
#gsmchar=c[0]
|
208
|
+
#puts "#{c} : #{gsmchar} xxx"
|
209
|
+
#gsmchar=@gsmtable[" "] if gsmchar.nil?
|
210
|
+
|
211
|
+
tmp= gsmchar.to_s(2)
|
212
|
+
|
213
|
+
remainder=tmp.length%7
|
214
|
+
if remainder!=0
|
215
|
+
nfillbits=7-remainder
|
216
|
+
tmp="0"*nfillbits+tmp
|
217
|
+
end
|
218
|
+
|
219
|
+
# if adding this character exceeds the max allowed nr of bytes, break
|
220
|
+
if ((tmp+ext+s).length*1.0/8).ceil>max_bytes
|
221
|
+
break
|
222
|
+
end
|
223
|
+
|
224
|
+
s=tmp+ext+s
|
225
|
+
|
226
|
+
# if reached the max allowed nr of bytes, break
|
227
|
+
if (s.length*1.0/8).ceil==max_bytes
|
228
|
+
idx+=1
|
229
|
+
break
|
230
|
+
end
|
231
|
+
|
232
|
+
idx+=1
|
233
|
+
}
|
234
|
+
|
235
|
+
|
236
|
+
required_septets=s.length/7
|
237
|
+
remainder=s.length%8
|
238
|
+
if remainder!=0
|
239
|
+
nfillbits=8-remainder
|
240
|
+
s="0"*nfillbits+s
|
241
|
+
end
|
242
|
+
|
243
|
+
#puts "S: #{s}"
|
244
|
+
|
245
|
+
i=s.length-8
|
246
|
+
hexstr=""
|
247
|
+
while i>=0
|
248
|
+
c=s[i,8]
|
249
|
+
|
250
|
+
tmp=c.to_i(2).to_s(16).upcase
|
251
|
+
if tmp.length==1
|
252
|
+
tmp="0"+tmp
|
253
|
+
end
|
254
|
+
# puts tmp
|
255
|
+
hexstr+=tmp
|
256
|
+
i-=8
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
return GsmPackedMsg.new(hexstr,str[0,idx],idx,required_septets,tainted)
|
261
|
+
end
|
262
|
+
|
263
|
+
# @deprecated remove because unecessary
|
264
|
+
def self.multi_pack7bits(str,max_bytes)
|
265
|
+
msgparts=[]
|
266
|
+
idx=0
|
267
|
+
while true
|
268
|
+
packedmsg=UCP.pack7bits2(str[idx..-1],max_bytes)
|
269
|
+
msgparts<<packedmsg
|
270
|
+
if idx+packedmsg.chars<str.length
|
271
|
+
idx+=packedmsg.chars
|
272
|
+
else
|
273
|
+
break
|
274
|
+
end
|
275
|
+
end
|
276
|
+
return msgparts
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
# convert standard string to IRA encoded hexstring
|
281
|
+
def self.ascii2ira(str,max_bytes=nil)
|
282
|
+
|
283
|
+
tainted=false # true if not able to convert a character
|
284
|
+
s=""
|
285
|
+
idx=0
|
286
|
+
str.each_char { |c|
|
287
|
+
gsmchar=@gsmtable[c]
|
288
|
+
|
289
|
+
ext=""
|
290
|
+
if gsmchar.nil?
|
291
|
+
if @extensiontable.has_key?(c)
|
292
|
+
ext="1B"
|
293
|
+
gsmchar=@extensiontable[c]
|
294
|
+
else
|
295
|
+
gsmchar=@gsmtable[" "]
|
296
|
+
tainted=true
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
tmp=int2hex(gsmchar)
|
302
|
+
|
303
|
+
|
304
|
+
if !max_bytes.nil?
|
305
|
+
# if adding this character exceeds the max allowed nr of bytes, break
|
306
|
+
if ((tmp+ext+s).length*7.0/16).ceil>max_bytes
|
307
|
+
break
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
s+=ext+tmp
|
312
|
+
idx+=(ext+tmp).length/2
|
313
|
+
|
314
|
+
# if reached the max allowed nr of bytes, break
|
315
|
+
# if (s.length*7.0/16).floor==max_bytes
|
316
|
+
# break
|
317
|
+
# end
|
318
|
+
|
319
|
+
}
|
320
|
+
|
321
|
+
required_septets=s.length/2
|
322
|
+
#puts "idx: #{idx}; req_sep: #{required_septets}"
|
323
|
+
return GsmPackedMsg.new(s,UCP.utf8_substr(str,0,idx-1),idx,required_septets,tainted)
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
def self.utf8_substr(str,idxs,idxe=nil)
|
328
|
+
s=""
|
329
|
+
i=0
|
330
|
+
idxe=str.jlength-1 if idxe.nil?
|
331
|
+
str.each_char{ |c|
|
332
|
+
s+=c if i>=idxs and i<=idxe
|
333
|
+
i+=1
|
334
|
+
}
|
335
|
+
return s
|
336
|
+
end
|
337
|
+
|
338
|
+
def self.multi_ascii2ira(str,max_bytes)
|
339
|
+
msgparts=[]
|
340
|
+
idx=0
|
341
|
+
|
342
|
+
if str.jlength<=160
|
343
|
+
packedmsg=UCP.ascii2ira(UCP.utf8_substr(str,idx),140)
|
344
|
+
#puts "pckd_chars: #{packedmsg.chars}; strlen: #{str.jlength}"
|
345
|
+
if packedmsg.chars==str.jlength
|
346
|
+
msgparts<<packedmsg
|
347
|
+
return msgparts
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
while true
|
352
|
+
#packedmsg=UCP.ascii2ira(str[idx..-1],max_bytes)
|
353
|
+
#puts "bla: #{UCP.utf8_substr(str,idx)}"
|
354
|
+
packedmsg=UCP.ascii2ira(UCP.utf8_substr(str,idx),max_bytes)
|
355
|
+
msgparts<<packedmsg
|
356
|
+
#break
|
357
|
+
#puts "idx: #{idx}; pckd_chars: #{packedmsg.chars}; strlen: #{str.jlength}"
|
358
|
+
|
359
|
+
#puts "sL: #{UCP.utf8_substr(str,idx,idx+packedmsg.chars- 1)} ; #{str[0,idx+packedmsg.chars].length}#"
|
360
|
+
|
361
|
+
#if idx+packedmsg.chars<str.length
|
362
|
+
if idx+packedmsg.chars<str.jlength
|
363
|
+
idx+=packedmsg.chars
|
364
|
+
else
|
365
|
+
break
|
366
|
+
end
|
367
|
+
end
|
368
|
+
return msgparts
|
369
|
+
end
|
370
|
+
|
371
|
+
|
372
|
+
def self.str2ucs2(str,max_bytes=nil)
|
373
|
+
hexstr=""
|
374
|
+
str=Iconv.iconv("utf-16be", "utf-8", str).first
|
375
|
+
i=0
|
376
|
+
str.each_byte{ |c|
|
377
|
+
hexstr+=UCP.int2hex(c)
|
378
|
+
i+=1
|
379
|
+
if (!max_bytes.nil?) && (i == max_bytes)
|
380
|
+
break
|
381
|
+
end
|
382
|
+
}
|
383
|
+
|
384
|
+
return Ucs2PackedMsg.new(hexstr,UCP.utf8_substr(str,0,i-1),i/2,i)
|
385
|
+
end
|
386
|
+
|
387
|
+
def self.multi_ucs2(str,max_bytes)
|
388
|
+
msgparts=[]
|
389
|
+
idx=0
|
390
|
+
|
391
|
+
if str.jlength<=70
|
392
|
+
packedmsg=UCP.str2ucs2(str,140)
|
393
|
+
#puts "pckd_chars: #{packedmsg.chars}; strlen: #{str.jlength}"
|
394
|
+
if packedmsg.chars==str.jlength
|
395
|
+
msgparts<<packedmsg
|
396
|
+
return msgparts
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
while true
|
401
|
+
|
402
|
+
#puts "bla: #{UCP.utf8_substr(str,idx)}"
|
403
|
+
packedmsg=UCP.str2ucs2(UCP.utf8_substr(str,idx),max_bytes)
|
404
|
+
msgparts<<packedmsg
|
405
|
+
#break
|
406
|
+
#puts "idx: #{idx}; pckd_chars: #{packedmsg.chars}; strlen: #{str.jlength}"
|
407
|
+
#puts "sL: #{UCP.utf8_substr(str,idx,idx+packedmsg.chars- 1)} ; #{str[0,idx+packedmsg.chars].length}#"
|
408
|
+
|
409
|
+
if idx+packedmsg.chars<str.jlength
|
410
|
+
idx+=packedmsg.chars
|
411
|
+
else
|
412
|
+
break
|
413
|
+
end
|
414
|
+
end
|
415
|
+
return msgparts
|
416
|
+
end
|
417
|
+
|
418
|
+
|
419
|
+
|
420
|
+
def self.make_multi_ucps(originator,recipient,message,mr=0)
|
421
|
+
ucps=[]
|
422
|
+
|
423
|
+
gsm7bit_encodable=false
|
424
|
+
|
425
|
+
if gsm7bit_encodable
|
426
|
+
gsmparts= UCP.multi_ascii2ira(message,134)
|
427
|
+
else
|
428
|
+
gsmparts= UCP.multi_ucs2(message,134)
|
429
|
+
end
|
430
|
+
|
431
|
+
|
432
|
+
part_nr=1
|
433
|
+
gsmparts.each { |gsmpart|
|
434
|
+
ucp=Ucp51Operation.new
|
435
|
+
ucp.basic_submit(originator,recipient,nil)
|
436
|
+
|
437
|
+
if gsmparts.length>1
|
438
|
+
# concatenated xser
|
439
|
+
ucp.add_xser("01","050003"+UCP.int2hex(mr)+UCP.int2hex(gsmparts.length)+UCP.int2hex(part_nr))
|
440
|
+
end
|
441
|
+
|
442
|
+
if gsm7bit_encodable
|
443
|
+
ucp.set_fields({:mt=>3, :msg=>gsmpart.encoded})
|
444
|
+
# DCS xser
|
445
|
+
ucp.add_xser("02","01")
|
446
|
+
else
|
447
|
+
ucp.set_fields({:msg=>gsmpart.encoded,:mt=>4,:nb=>gsmpart.encoded.length*4})
|
448
|
+
# DCS xser
|
449
|
+
ucp.add_xser("02","08")
|
450
|
+
end
|
451
|
+
|
452
|
+
#ucp.trn=UCP.int2hex(initial_trn)
|
453
|
+
#initial_trn+=1
|
454
|
+
|
455
|
+
#puts "part: #{ucp.to_s}"
|
456
|
+
ucps<<ucp
|
457
|
+
part_nr+=1
|
458
|
+
}
|
459
|
+
return ucps
|
460
|
+
end
|
461
|
+
|
462
|
+
|
463
|
+
|
464
|
+
def self.packucs2(str)
|
465
|
+
hexstr=""
|
466
|
+
s= Iconv.iconv("ucs-2be", "utf-8", str).first
|
467
|
+
s.each_char{ |c|
|
468
|
+
|
469
|
+
tmp=c[0].to_s(16).upcase
|
470
|
+
if tmp.length==1
|
471
|
+
tmp="0"+tmp
|
472
|
+
end
|
473
|
+
|
474
|
+
hexstr+=tmp
|
475
|
+
|
476
|
+
}
|
477
|
+
#puts s
|
478
|
+
return hexstr
|
479
|
+
end
|
480
|
+
|
481
|
+
def self.packoadc(oa)
|
482
|
+
packedoa=UCP.pack7bits(oa)
|
483
|
+
|
484
|
+
# esta conta nao esta correcta... por causa das extensoes...
|
485
|
+
#useful_nibbles=packedoa.length
|
486
|
+
useful_nibbles=(oa.length*7.0/4).ceil
|
487
|
+
|
488
|
+
tmp=useful_nibbles.to_s(16).upcase
|
489
|
+
if tmp.length==1
|
490
|
+
tmp="0"+tmp
|
491
|
+
end
|
492
|
+
|
493
|
+
return tmp+packedoa
|
494
|
+
end
|
495
|
+
|
496
|
+
def self.hextobin(hstr)
|
497
|
+
bstr=""
|
498
|
+
i=0
|
499
|
+
while i<hstr.length
|
500
|
+
tmp=hstr[i,2].to_i(16).to_s(2)
|
501
|
+
|
502
|
+
nfillbits=8-tmp.length
|
503
|
+
if nfillbits!=0
|
504
|
+
tmp="0"*nfillbits+tmp
|
505
|
+
end
|
506
|
+
|
507
|
+
bstr+=tmp
|
508
|
+
i+=2
|
509
|
+
end
|
510
|
+
return bstr
|
511
|
+
end
|
512
|
+
|
513
|
+
|
514
|
+
def self.hextobin_reversed(hstr)
|
515
|
+
bstr=""
|
516
|
+
i=0
|
517
|
+
while i<hstr.length
|
518
|
+
tmp=hstr[i,2].to_i(16).to_s(2)
|
519
|
+
|
520
|
+
nfillbits=8-tmp.length
|
521
|
+
if nfillbits!=0
|
522
|
+
tmp="0"*nfillbits+tmp
|
523
|
+
end
|
524
|
+
|
525
|
+
bstr=tmp+bstr
|
526
|
+
i+=2
|
527
|
+
end
|
528
|
+
return bstr
|
529
|
+
end
|
530
|
+
|
531
|
+
|
532
|
+
def self.decode7bitgsm(str)
|
533
|
+
|
534
|
+
# retirar isto!!
|
535
|
+
#initialize_ascii2ira
|
536
|
+
|
537
|
+
unencoded=""
|
538
|
+
#puts "#{str}"
|
539
|
+
bstr=UCP.hextobin_reversed(str)
|
540
|
+
#puts "#{bstr}"
|
541
|
+
# 110 1111 110 1100 110 0001
|
542
|
+
# 1000011 1011101 0110111 000
|
543
|
+
|
544
|
+
i=bstr.length-7
|
545
|
+
while i>=0
|
546
|
+
value=bstr[i,7].to_i(2)
|
547
|
+
if value==0x1B
|
548
|
+
i-=7
|
549
|
+
value=@extensiontable_rev[bstr[i,7].to_i(2)]
|
550
|
+
value=" " if value.nil?
|
551
|
+
unencoded+=value
|
552
|
+
else
|
553
|
+
val=@asciitable[value]
|
554
|
+
#puts "value: #{value} ; val: #{val}"
|
555
|
+
val=" " if val.nil?
|
556
|
+
unencoded+=val
|
557
|
+
#unencoded+=value.chr
|
558
|
+
end
|
559
|
+
|
560
|
+
|
561
|
+
|
562
|
+
|
563
|
+
i-=7
|
564
|
+
end
|
565
|
+
|
566
|
+
|
567
|
+
# i=0
|
568
|
+
# while i<str.length
|
569
|
+
# hexv=str[i,2]
|
570
|
+
# if "1B".eql?(hexv)
|
571
|
+
# i+=2
|
572
|
+
# hexv=str[i,2]
|
573
|
+
# end
|
574
|
+
#
|
575
|
+
# unencoded+=hexv.to_i(16).chr
|
576
|
+
#
|
577
|
+
# i+=2
|
578
|
+
# end
|
579
|
+
|
580
|
+
|
581
|
+
return unencoded
|
582
|
+
end
|
583
|
+
|
584
|
+
|
585
|
+
|
586
|
+
def self.decode_ira(str)
|
587
|
+
unencoded=""
|
588
|
+
|
589
|
+
i=0
|
590
|
+
while i<str.length
|
591
|
+
hexv=str[i,2]
|
592
|
+
if "1B".eql?(hexv)
|
593
|
+
i+=2
|
594
|
+
hexv=str[i,2]
|
595
|
+
|
596
|
+
value=@extensiontable_rev[hexv.to_i(16)]
|
597
|
+
value=" " if value.nil?
|
598
|
+
unencoded+=value
|
599
|
+
else
|
600
|
+
val=@asciitable[hexv.to_i(16)]
|
601
|
+
val=" " if val.nil?
|
602
|
+
unencoded+=val
|
603
|
+
end
|
604
|
+
|
605
|
+
i+=2
|
606
|
+
end
|
607
|
+
|
608
|
+
return unencoded
|
609
|
+
end
|
610
|
+
|
611
|
+
|
612
|
+
|
613
|
+
|
614
|
+
def self.int2hex(i,max_nibbles=2)
|
615
|
+
tmp=i.to_s(16).upcase
|
616
|
+
if tmp.length%2!=0
|
617
|
+
tmp="0"+tmp
|
618
|
+
end
|
619
|
+
|
620
|
+
remaining_nibbles=max_nibbles-tmp.length
|
621
|
+
if remaining_nibbles>0
|
622
|
+
tmp="0"*remaining_nibbles+tmp;
|
623
|
+
end
|
624
|
+
|
625
|
+
return tmp
|
626
|
+
end
|
627
|
+
|
628
|
+
|
629
|
+
|
630
|
+
# usado para construir um UCP duma string
|
631
|
+
def self.parse_str(ustr)
|
632
|
+
#puts "parse_str(#{ustr})"
|
633
|
+
|
634
|
+
if ustr.nil?
|
635
|
+
return nil
|
636
|
+
end
|
637
|
+
|
638
|
+
arr=ustr[(ustr.index(2.chr)+1)..-2].split("/")
|
639
|
+
trn=arr[0]
|
640
|
+
#puts "#{trn}"
|
641
|
+
# length
|
642
|
+
operation_type=arr[2]
|
643
|
+
#puts "#{operation_type}"
|
644
|
+
operation=arr[3]
|
645
|
+
#puts "#{operation}"
|
646
|
+
|
647
|
+
ucpmsg=nil
|
648
|
+
|
649
|
+
if operation.eql?("01")
|
650
|
+
if operation_type.eql?("O")
|
651
|
+
# puts "parsing a ucp01"
|
652
|
+
ucpmsg=Ucp01Operation.new(arr)
|
653
|
+
elsif operation_type.eql?("R")
|
654
|
+
# puts "parsing a result of a ucp01"
|
655
|
+
ucpmsg=Ucp01Result.new(arr)
|
656
|
+
end
|
657
|
+
elsif operation.eql?("30")
|
658
|
+
if operation_type.eql?("O")
|
659
|
+
# puts "parsing a ucp30"
|
660
|
+
ucpmsg=Ucp30Operation.new(arr)
|
661
|
+
elsif operation_type.eql?("R")
|
662
|
+
#puts "parsing a result of a ucp30"
|
663
|
+
ucpmsg=Ucp30Result.new(arr)
|
664
|
+
end
|
665
|
+
elsif operation.eql?("31")
|
666
|
+
if operation_type.eql?("O")
|
667
|
+
#puts "parsing a ucp31"
|
668
|
+
ucpmsg=Ucp31Operation.new(arr)
|
669
|
+
elsif operation_type.eql?("R")
|
670
|
+
#puts "parsing a result of a ucp31"
|
671
|
+
ucpmsg=Ucp31Result.new(arr)
|
672
|
+
end
|
673
|
+
elsif operation.eql?("51")
|
674
|
+
if operation_type.eql?("O")
|
675
|
+
#puts "parsing a ucp51"
|
676
|
+
ucpmsg=Ucp51Operation.new(arr)
|
677
|
+
elsif operation_type.eql?("R")
|
678
|
+
#puts "parsing a result of a ucp51"
|
679
|
+
ucpmsg=Ucp51Result.new(arr)
|
680
|
+
end
|
681
|
+
elsif operation.eql?("52")
|
682
|
+
if operation_type.eql?("O")
|
683
|
+
#puts "parsing a ucp52"
|
684
|
+
ucpmsg=Ucp52Operation.new(arr)
|
685
|
+
elsif operation_type.eql?("R")
|
686
|
+
#puts "parsing a result of a ucp52"
|
687
|
+
ucpmsg=Ucp52Result.new(arr)
|
688
|
+
end
|
689
|
+
elsif operation.eql?("53")
|
690
|
+
if operation_type.eql?("O")
|
691
|
+
#puts "parsing a ucp53"
|
692
|
+
ucpmsg=Ucp53Operation.new(arr)
|
693
|
+
elsif operation_type.eql?("R")
|
694
|
+
#puts "parsing a result of a ucp53"
|
695
|
+
ucpmsg=Ucp53Result.new(arr)
|
696
|
+
end
|
697
|
+
elsif operation.eql?("54")
|
698
|
+
if operation_type.eql?("O")
|
699
|
+
#puts "parsing a ucp54"
|
700
|
+
ucpmsg=Ucp54Operation.new(arr)
|
701
|
+
elsif operation_type.eql?("R")
|
702
|
+
#puts "parsing a result of a ucp54"
|
703
|
+
ucpmsg=Ucp54Result.new(arr)
|
704
|
+
end
|
705
|
+
elsif operation.eql?("55")
|
706
|
+
if operation_type.eql?("O")
|
707
|
+
#puts "parsing a ucp55"
|
708
|
+
ucpmsg=Ucp55Operation.new(arr)
|
709
|
+
elsif operation_type.eql?("R")
|
710
|
+
#puts "parsing a result of a ucp55"
|
711
|
+
ucpmsg=Ucp55Result.new(arr)
|
712
|
+
end
|
713
|
+
elsif operation.eql?("56")
|
714
|
+
if operation_type.eql?("O")
|
715
|
+
#puts "parsing a ucp56"
|
716
|
+
ucpmsg=Ucp56Operation.new(arr)
|
717
|
+
elsif operation_type.eql?("R")
|
718
|
+
#puts "parsing a result of a ucp56"
|
719
|
+
ucpmsg=Ucp56Result.new(arr)
|
720
|
+
end
|
721
|
+
elsif operation.eql?("57")
|
722
|
+
if operation_type.eql?("O")
|
723
|
+
#puts "parsing a ucp57"
|
724
|
+
ucpmsg=Ucp57Operation.new(arr)
|
725
|
+
elsif operation_type.eql?("R")
|
726
|
+
#puts "parsing a result of a ucp57"
|
727
|
+
ucpmsg=Ucp57Result.new(arr)
|
728
|
+
end
|
729
|
+
elsif operation.eql?("58")
|
730
|
+
if operation_type.eql?("O")
|
731
|
+
#puts "parsing a ucp58"
|
732
|
+
ucpmsg=Ucp58Operation.new(arr)
|
733
|
+
elsif operation_type.eql?("R")
|
734
|
+
#puts "parsing a result of a ucp58"
|
735
|
+
ucpmsg=Ucp58Result.new(arr)
|
736
|
+
end
|
737
|
+
elsif operation.eql?("60")
|
738
|
+
if operation_type.eql?("O")
|
739
|
+
#puts "parsing a ucp60"
|
740
|
+
ucpmsg=Ucp60Operation.new(arr)
|
741
|
+
elsif operation_type.eql?("R")
|
742
|
+
#puts "parsing a result of a ucp60"
|
743
|
+
ucpmsg=Ucp60Result.new(arr)
|
744
|
+
end
|
745
|
+
elsif operation.eql?("61")
|
746
|
+
if operation_type.eql?("O")
|
747
|
+
#puts "parsing a ucp61"
|
748
|
+
ucpmsg=Ucp61Operation.new(arr)
|
749
|
+
elsif operation_type.eql?("R")
|
750
|
+
#puts "parsing a result of a ucp61"
|
751
|
+
ucpmsg=Ucp61Result.new(arr)
|
752
|
+
end
|
753
|
+
end
|
754
|
+
|
755
|
+
#ucpmsg.trn=trn
|
756
|
+
return ucpmsg
|
757
|
+
end
|
758
|
+
|
759
|
+
|
760
|
+
|
761
|
+
|
762
|
+
# usado para construir uma resposta UCP a partir dum UCP
|
763
|
+
def self.make_ucp_result(ucp)
|
764
|
+
puts "make_ucp_result(#{ucp.to_s})"
|
765
|
+
|
766
|
+
if ucp.nil?
|
767
|
+
return nil
|
768
|
+
end
|
769
|
+
|
770
|
+
trn=ucp.trn
|
771
|
+
#puts "#{trn}"
|
772
|
+
# length
|
773
|
+
operation_type=ucp.operation_type
|
774
|
+
#puts "#{operation_type}"
|
775
|
+
operation=ucp.operation
|
776
|
+
#puts "#{operation}"
|
777
|
+
|
778
|
+
ucpmsg=nil
|
779
|
+
|
780
|
+
if operation.eql?("01")
|
781
|
+
ucpmsg=Ucp01Result.new
|
782
|
+
elsif operation.eql?("30")
|
783
|
+
ucpmsg=Ucp30Result.new
|
784
|
+
elsif operation.eql?("31")
|
785
|
+
ucpmsg=Ucp31Result.new
|
786
|
+
elsif operation.eql?("51")
|
787
|
+
ucpmsg=Ucp51Result.new
|
788
|
+
elsif operation.eql?("52")
|
789
|
+
ucpmsg=Ucp52Result.new
|
790
|
+
elsif operation.eql?("53")
|
791
|
+
ucpmsg=Ucp53Result.new
|
792
|
+
elsif operation.eql?("54")
|
793
|
+
ucpmsg=Ucp54Result.new
|
794
|
+
elsif operation.eql?("55")
|
795
|
+
ucpmsg=Ucp55Result.new
|
796
|
+
elsif operation.eql?("56")
|
797
|
+
ucpmsg=Ucp56Result.new
|
798
|
+
elsif operation.eql?("57")
|
799
|
+
ucpmsg=Ucp57Result.new
|
800
|
+
elsif operation.eql?("58")
|
801
|
+
ucpmsg=Ucp58Result.new
|
802
|
+
elsif operation.eql?("60")
|
803
|
+
ucpmsg=Ucp60Result.new
|
804
|
+
elsif operation.eql?("61")
|
805
|
+
ucpmsg=Ucp61Result.new
|
806
|
+
else
|
807
|
+
return nil
|
808
|
+
end
|
809
|
+
|
810
|
+
ucpmsg.trn=trn
|
811
|
+
return ucpmsg
|
812
|
+
end
|
813
|
+
|
814
|
+
def self.hex2str(hexstr)
|
815
|
+
str=""
|
816
|
+
hexstr.scan(/../).each { | tuple | str+=tuple.hex.chr }
|
817
|
+
return str
|
818
|
+
end
|
819
|
+
|
820
|
+
def self.decode_ucp_msg(ucp)
|
821
|
+
text=nil
|
822
|
+
dcs=ucp.dcs.to_i(16)
|
823
|
+
|
824
|
+
if (dcs & 0x0F == 0x01) || (dcs & 0x0F == 0x00)
|
825
|
+
|
826
|
+
if ucp.operation.eql?("30")
|
827
|
+
text=UCP.decode_ira(ucp.get_field(:amsg))
|
828
|
+
else
|
829
|
+
|
830
|
+
if ucp.operation.eql?("51") || ucp.operation.eql?("52") || ucp.operation.eql?("53")
|
831
|
+
mt=ucp.get_field(:msg)
|
832
|
+
if mt.eql?("2")
|
833
|
+
# numeric message.. return it as it is
|
834
|
+
text=ucp.get_field(:msg)
|
835
|
+
elsif mt.eql?("3")
|
836
|
+
text=UCP.decode_ira(ucp.get_field(:msg))
|
837
|
+
else
|
838
|
+
# unexpected "mt" value. return nil explicitely
|
839
|
+
return nil
|
840
|
+
end
|
841
|
+
elsif ucp.operation.eql?("01")
|
842
|
+
text=UCP.decode_ira(ucp.get_field(:msg))
|
843
|
+
else
|
844
|
+
# unexpected operation. return nil explicitely
|
845
|
+
return nil
|
846
|
+
end
|
847
|
+
|
848
|
+
end
|
849
|
+
elsif (dcs & 0x0F == 0x08) || (dcs & 0x0F == 0x09)
|
850
|
+
str=UCP.hex2str(ucp.get_field(:msg))
|
851
|
+
text=Iconv.iconv("utf-8","utf-16be",str).first
|
852
|
+
else
|
853
|
+
# cant decode text; unsupported DCS
|
854
|
+
return nil
|
855
|
+
end
|
856
|
+
|
857
|
+
return text
|
858
|
+
end
|
859
|
+
|
860
|
+
def self.decode_ucp_oadc(ucp)
|
861
|
+
otoa=nil
|
862
|
+
oadc=ucp.get_field(:oadc)
|
863
|
+
|
864
|
+
if ucp.is_a?(Ucp51Operation) || ucp.is_a?(Ucp52Operation) || ucp.is_a?(Ucp53Operation) || ucp.is_a?(Ucp54Operation) || ucp.is_a?(Ucp55Operation) || ucp.is_a?(Ucp56Operation) || ucp.is_a?(Ucp57Operation) || ucp.is_a?(Ucp58Operation)
|
865
|
+
otoa=ucp.get_field(:otoa)
|
866
|
+
end
|
867
|
+
|
868
|
+
if otoa.nil? || otoa.eql?("1139")
|
869
|
+
return oadc
|
870
|
+
elsif otoa.eql?("5039")
|
871
|
+
#useful_nibbles=oadc[0,2].to_i(16)
|
872
|
+
return UCP.decode7bitgsm(oadc[2..-1])
|
873
|
+
else
|
874
|
+
#
|
875
|
+
end
|
876
|
+
|
877
|
+
# by default, return oadc
|
878
|
+
return oadc
|
879
|
+
end
|
880
|
+
|
881
|
+
|
882
|
+
# initialize tables on first class reference, in fact when loading it
|
883
|
+
initialize_ascii2ira()
|
884
|
+
|
885
|
+
end
|