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.
Files changed (54) hide show
  1. data/CHANGELOG +42 -0
  2. data/LICENSE +505 -0
  3. data/README +10 -0
  4. data/Rakefile +118 -0
  5. data/Rakefile.orig +45 -0
  6. data/VERSION +1 -0
  7. data/lib/ruby_ucp.rb +42 -0
  8. data/lib/samples/main.rb +182 -0
  9. data/lib/ucp/base.rb +24 -0
  10. data/lib/ucp/pdu/base.rb +22 -0
  11. data/lib/ucp/pdu/ucp01.rb +37 -0
  12. data/lib/ucp/pdu/ucp01_operation.rb +61 -0
  13. data/lib/ucp/pdu/ucp01_result.rb +60 -0
  14. data/lib/ucp/pdu/ucp30.rb +28 -0
  15. data/lib/ucp/pdu/ucp30_operation.rb +59 -0
  16. data/lib/ucp/pdu/ucp30_result.rb +63 -0
  17. data/lib/ucp/pdu/ucp31.rb +29 -0
  18. data/lib/ucp/pdu/ucp31_operation.rb +50 -0
  19. data/lib/ucp/pdu/ucp31_result.rb +61 -0
  20. data/lib/ucp/pdu/ucp51_operation.rb +167 -0
  21. data/lib/ucp/pdu/ucp51_result.rb +64 -0
  22. data/lib/ucp/pdu/ucp52_operation.rb +31 -0
  23. data/lib/ucp/pdu/ucp52_result.rb +31 -0
  24. data/lib/ucp/pdu/ucp53_operation.rb +31 -0
  25. data/lib/ucp/pdu/ucp53_result.rb +31 -0
  26. data/lib/ucp/pdu/ucp54_operation.rb +31 -0
  27. data/lib/ucp/pdu/ucp54_result.rb +31 -0
  28. data/lib/ucp/pdu/ucp55_operation.rb +31 -0
  29. data/lib/ucp/pdu/ucp55_result.rb +31 -0
  30. data/lib/ucp/pdu/ucp56_operation.rb +31 -0
  31. data/lib/ucp/pdu/ucp56_result.rb +31 -0
  32. data/lib/ucp/pdu/ucp57_operation.rb +31 -0
  33. data/lib/ucp/pdu/ucp57_result.rb +31 -0
  34. data/lib/ucp/pdu/ucp58_operation.rb +31 -0
  35. data/lib/ucp/pdu/ucp58_result.rb +31 -0
  36. data/lib/ucp/pdu/ucp5x.rb +40 -0
  37. data/lib/ucp/pdu/ucp60.rb +30 -0
  38. data/lib/ucp/pdu/ucp60_operation.rb +58 -0
  39. data/lib/ucp/pdu/ucp60_result.rb +60 -0
  40. data/lib/ucp/pdu/ucp61.rb +31 -0
  41. data/lib/ucp/pdu/ucp61_operation.rb +49 -0
  42. data/lib/ucp/pdu/ucp61_result.rb +60 -0
  43. data/lib/ucp/pdu/ucp_operation.rb +27 -0
  44. data/lib/ucp/pdu/ucp_result.rb +26 -0
  45. data/lib/ucp/pdu/ucpmessage.rb +125 -0
  46. data/lib/ucp/util/base.rb +22 -0
  47. data/lib/ucp/util/gsm_packed_msg.rb +50 -0
  48. data/lib/ucp/util/packed_msg.rb +34 -0
  49. data/lib/ucp/util/sms_request.rb +48 -0
  50. data/lib/ucp/util/ucp.rb +885 -0
  51. data/lib/ucp/util/ucp_client.rb +207 -0
  52. data/lib/ucp/util/ucp_server.rb +122 -0
  53. data/lib/ucp/util/ucs2_packed_msg.rb +29 -0
  54. metadata +120 -0
@@ -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