ruby_ucp 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|