File Coverage

blib/lib/TAP3/Tap3edit.pm
Criterion Covered Total %
statement 215 283 75.9
branch 88 134 65.6
condition 15 29 51.7
subroutine 27 31 87.1
pod 0 15 0.0
total 345 492 70.1


line stmt bran cond sub pod time code
1             # Package Tap3edit (https://github.com/tap3edit/TAP3-Tap3edit)
2             # designed to decode, modify and encode Roaming GSM TAP/RAP/
3             # NRT files
4             #
5             # Copyright (c) 2004-2018 Javier Gutierrez. All rights
6             # reserved.
7             # This program is free software; you can redistribute
8             # it and/or modify it under the same terms as Perl itself.
9             #
10             # This program contains TAP, RAP and NRTRDE ASN.1
11             # Specification. The ownership of the TAP/RAP/NRTRDE ASN.1
12             # Specifications belong to the GSM MoU Association
13             # (http://www.gsm.org) and should be used under following
14             # conditions:
15             #
16             # Copyright (c) 2000 GSM MoU Association. Restricted − Con­
17             # fidential Information. Access to and distribution of this
18             # document is restricted to the persons listed under the
19             # heading Security Classification Category*. This document
20             # is confidential to the Association and is subject to copy­
21             # right protection. This document is to be used only for
22             # the purposes for which it has been supplied and informa­
23             # tion contained in it must not be disclosed or in any other
24             # way made available, in whole or in part, to persons other
25             # than those listed under Security Classification Category*
26             # without the prior written approval of the Association. The
27             # GSM MoU Association (âAssociationâ) makes no representa­
28             # tion, warranty or undertaking (express or implied) with
29             # respect to and does not accept any responsibility for, and
30             # hereby disclaims liability for the accuracy or complete­
31             # ness or timeliness of the information contained in this
32             # document. The information contained in this document may
33             # be subject to change without prior notice.
34              
35              
36              
37             package TAP3::Tap3edit;
38              
39 1     1   465 use strict;
  1         2  
  1         26  
40 1     1   398 use Convert::ASN1 qw(:io :debug); # Handler of ASN1 Codes. Should be installed first.
  1         27404  
  1         99  
41 1     1   8 use File::Spec;
  1         1  
  1         16  
42 1     1   4 use File::Basename;
  1         2  
  1         69  
43 1     1   5 use Carp;
  1         2  
  1         36  
44              
45              
46             BEGIN {
47 1     1   5 use Exporter;
  1         1  
  1         57  
48 1     1   2 our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
49 1         2107 $VERSION = "0.34";
50             }
51              
52              
53             sub new {
54 14     14 0 75 my $proto = shift;
55 14   33     67 my $class = ref($proto) || $proto ;
56 14         37 my $self = {};
57 14         36 $self->{_filename} = undef;
58 14         26 $self->{_spec_file} = undef;
59 14         38 $self->{_supl_spec_file} = undef;
60 14         85 $self->{_asn} = Convert::ASN1->new();
61 14         586 $self->{_dic_decode} = {}; # Stores the file decode with $self->{_dic_asn}
62 14         28 $self->{_dic_asn} = $self->{_asn}; # Stores the ASN Specification
63 14         2140 $self->{spec_path} = [ ( grep(-d $_, map(File::Spec->catdir($_, qw(TAP3 Spec)), @INC)), File::Spec->curdir) ];
64 14         74 $self->{_version} = undef;
65 14         69 $self->{_release} = undef;
66 14         32 $self->{_supl_version} = undef; # Tap version inside the RAP file
67 14         40 $self->{_supl_release} = undef; # Tap release inside the RAP file
68 14         32 $self->{_file_type} = undef; # TAP, RAP or NRT
69 14         30 $self->{error} = undef;
70 14         28 bless ($self, $class);
71 14         181 return $self;
72             }
73              
74              
75             #----------------------------------------------------------------
76             # Method: structure
77             # Description: Contains the structure of the TAP/RAP/NRT file
78             # into a HASH
79             # Parameters: N/A
80             # Returns: HASH
81             # Type: Public
82             # Restrictions: N/A
83             #----------------------------------------------------------------
84             sub structure {
85 14     14 0 33 my $self = shift;
86 14 50       35 if (@_) { $self->{_dic_decode} = shift }
  14         38  
87 14         56 return $self->{_dic_decode};
88             }
89              
90              
91             #----------------------------------------------------------------
92             # Method: version
93             # Description: contains and updates the main version of the
94             # TAP/RAP/NRT file
95             # Parameters: N/A
96             # Returns: SCALAR: version number
97             # Type: Public
98             # Restrictions: N/A
99             #----------------------------------------------------------------
100             sub version {
101 14     14 0 33 my $self = shift;
102 14 50       40 if ( @_ ) {
103 14 50       43 if ( ! $self->{_version} ) {
104 14         25 $self->{_version} = shift ;
105             } else {
106 0         0 $self->{error}="The Version cannot be changed";
107 0         0 croak $self->error();
108             }
109             }
110 14         48 return $self->{_version};
111             }
112              
113              
114             #----------------------------------------------------------------
115             # Method: supl_version
116             # Description: contains and updates the suplementary version of the
117             # RAP file
118             # Parameters: N/A
119             # Returns: SCALAR: release number
120             # Type: Public
121             # Restrictions: Valid just for RAP files
122             #----------------------------------------------------------------
123             sub supl_version {
124 5     5 0 13 my $self = shift;
125 5 50       18 if ( @_ ) {
126 5 50       19 if ( ! $self->{_supl_version} ) {
127 5         14 $self->{_supl_version} = shift ;
128             } else {
129 0         0 $self->{error}="The Suplementary Version cannot be changed";
130 0         0 croak $self->error();
131             }
132             }
133 5         18 return $self->{_supl_version};
134             }
135              
136             #----------------------------------------------------------------
137             # Method: release
138             # Description: contains and updates the main release of the
139             # TAP/RAP/NRT file
140             # Parameters: N/A
141             # Returns: SCALAR: release number
142             # Type: Public
143             # Restrictions: N/A
144             #----------------------------------------------------------------
145             sub release {
146 14     14 0 35 my $self = shift;
147 14 50       38 if ( @_ ) {
148 14 50       40 if ( ! $self->{_release} ) {
149 14         34 $self->{_release} = shift ;
150             } else {
151 0         0 $self->{error}="The Release cannot be changed";
152 0         0 croak $self->error();
153             }
154             }
155 14         47 return $self->{_release};
156             }
157              
158              
159             #----------------------------------------------------------------
160             # Method: supl_release
161             # Description: contains and updates the suplementary release of the
162             # RAP file
163             # Parameters: N/A
164             # Returns: SCALAR: release number
165             # Type: Public
166             # Restrictions: Valid just for RAP files
167             #----------------------------------------------------------------
168             sub supl_release {
169 5     5 0 10 my $self = shift;
170 5 50       15 if ( @_ ) {
171 5 50       19 if ( ! $self->{_supl_release} ) {
172 5         26 $self->{_supl_release} = shift ;
173             } else {
174 0         0 $self->{error}="The Suplementary Release cannot be changed";
175 0         0 croak $self->error();
176             }
177             }
178 5         20 return $self->{_supl_release};
179             }
180              
181             #----------------------------------------------------------------
182             # Method: file_type
183             # Description: contains and updates the type of the file
184             # the values can be: TAP/RAP/NRT.
185             # Parameters: N/A
186             # Returns: SCALAR: file type ("RAP","TAP","NRT")
187             # Type: Public
188             # Restrictions: N/A
189             #----------------------------------------------------------------
190             sub file_type {
191 119     119 0 197 my $self = shift;
192 119 100       243 if ( @_ ) {
193 14 50       42 if ( ! $self->{_file_type} ) {
194 14         24 my $file_type = shift;
195              
196 14 50       69 unless ($file_type =~ /^[TR]AP$|^NRT$/) {
197 0         0 croak("Unsupported File Type $file_type");
198             }
199              
200 14         49 $self->{_file_type} = $file_type ;
201             } else {
202 0         0 $self->{error}="The File Type cannot be changed";
203 0         0 croak $self->error();
204             }
205             }
206 119         485 return $self->{_file_type};
207             }
208              
209              
210             #----------------------------------------------------------------
211             # Method: get_info
212             # Description: gets the basic information of the TAP/RAP/NRT
213             # files: version, release, supl_version (for RAP
214             # files), supl_release (for RAP files), file type.
215             # Parameters: filename
216             # Returns: N/A
217             # Type: Public
218             # Restrictions: N/A
219             #----------------------------------------------------------------
220             sub get_info {
221 14     14 0 30 my $self = shift;
222 14         23 my $filename = shift;
223 14         54 $self->_filename($filename);
224 14 50       48 $self->_get_file_version || return undef ;
225             }
226              
227              
228             #----------------------------------------------------------------
229             # Method: _filename
230             # Description: contains and updates the name of the TAP/RAP/NRT
231             # files
232             # Parameters: filename
233             # Returns: filename
234             # Type: Private
235             # Restrictions: N/A
236             #----------------------------------------------------------------
237             sub _filename {
238 70     70   93 my $self = shift;
239 70 100       167 if (@_) { $self->{_filename} = shift }
  42         88  
240 70         97 return $self->{_filename};
241             }
242              
243              
244             #----------------------------------------------------------------
245             # Method: spec_file
246             # Description: contains and updates the name of the file
247             # with specifications ASN.1
248             # Parameters: filename of specifications ASN.1
249             # Returns: filename of specifications ASN.1
250             # Type: Public
251             # Restrictions: N/A
252             #----------------------------------------------------------------
253             sub spec_file {
254 98     98 0 129 my $self = shift;
255 98 100       154 if (@_) { $self->{_spec_file} = shift }
  14         25  
256 98         1735 return $self->{_spec_file};
257             }
258              
259              
260             #----------------------------------------------------------------
261             # Method: supl_spec_file
262             # Description: contains and updates the name of the file
263             # with specifications ASN.1 for the version of
264             # the TAP file included in the RAP file.
265             # Parameters: filename of specifications ASN.1
266             # Returns: filename of specifications ASN.1
267             # Type: Public
268             # Restrictions: Valid just for RAP files
269             #----------------------------------------------------------------
270             sub supl_spec_file {
271 53     53 0 96 my $self = shift;
272 53 100       114 if (@_) { $self->{_supl_spec_file} = shift }
  5         10  
273 53         648 return $self->{_supl_spec_file};
274             }
275              
276              
277             #----------------------------------------------------------------
278             # Method: _dic_decode
279             # Description: contains and updates the HASH which stores
280             # the decoded information from the TAP/RAP/NRT file.
281             # This variable is also used for the method:
282             # "structure".
283             # Parameters: HASH
284             # Returns: HASH
285             # Type: Private
286             # Restrictions: N/A
287             #----------------------------------------------------------------
288             sub _dic_decode {
289 14     14   25 my $self = shift;
290 14 50       38 if (@_) { $self->{_dic_decode} = shift }
  0         0  
291 14         71 return $self->{_dic_decode};
292             }
293              
294              
295             #----------------------------------------------------------------
296             # Method: _dic_asn
297             # Description: contains and updates the object used to store
298             # the tree of the specifictions ASN.1 starting
299             # from the DataInterChange/RapDataInterChange tag.
300             # Parameters: object
301             # Returns: object
302             # Type: Private
303             # Restrictions: N/A
304             #----------------------------------------------------------------
305             sub _dic_asn {
306 56     56   85 my $self = shift;
307 56 100       119 if (@_) { $self->{_dic_asn} = shift }
  28         11016  
308 56         253 return $self->{_dic_asn};
309             }
310              
311              
312             #----------------------------------------------------------------
313             # Method: _asn
314             # Description: contains and updates the object used to store
315             # the constructor of Convert::ASN1
316             # Parameters: object
317             # Returns: object
318             # Type: Private
319             # Restrictions: N/A
320             #----------------------------------------------------------------
321             sub _asn {
322 28     28   73 my $self = shift;
323 28 50       88 if (@_) { $self->{_asn} = shift }
  0         0  
324 28         66 return $self->{_asn};
325             }
326              
327              
328             #----------------------------------------------------------------
329             # Method: _asn_path
330             # Description: contains the list of PATH where
331             # to find the specifications ASN.1.
332             # The default values are "TAP3/Spec" from the insta-
333             # llation and "." (current directory). The used
334             # array (spec_path) can be updated with new PATHs
335             # Parameters: ARRAY
336             # Returns: ARRAY
337             # Type: Private
338             # Restrictions: N/A
339             #----------------------------------------------------------------
340             sub _asn_path {
341 19     19   62 my $self = shift;
342 19         46 return $self->{spec_path};
343             }
344              
345              
346              
347             #----------------------------------------------------------------
348             # Function: bcd_to_hexa
349             # Description: Converts the input binary format from the
350             # TAP/RAP/NRT files into Hexadecimal string.
351             # Parameters: binary_string
352             # Returns: hexadecimal value
353             # Type: Private
354             # Restrictions: N/A
355             #----------------------------------------------------------------
356             sub bcd_to_hexa
357             {
358 0     0 0 0 my $in=shift;
359 0         0 unpack("H*",$in);
360             }
361              
362              
363             #----------------------------------------------------------------
364             # Function: bcd_to_asc
365             # Description: Converts the input binary format from the
366             # TAP/RAP/NRT files into decimal.
367             # Parameters: binary_string
368             # Returns: ascii value
369             # Type: Private
370             # Restrictions: N/A
371             #----------------------------------------------------------------
372             sub bcd_to_asc
373             {
374 0     0 0 0 my $in=shift;
375 0         0 my $out=0;
376 0         0 for (my $i=0;$i
377 0         0 $out.=sprintf("%03d", ord(substr($in,$i,1)));
378             }
379 0         0 return $out;
380             }
381              
382              
383              
384             #----------------------------------------------------------------
385             # Method: _get_file_version
386             # Description: sets the file version/release of the TAP/RAP/NRT
387             # file by matching patterns
388             # Parameters: N/A
389             # Returns: N/A
390             # Type: Private
391             # Restrictions: N/A
392             #----------------------------------------------------------------
393             sub _get_file_version
394             {
395 28     28   39 my $self=shift;
396              
397 28         48 my $filename=$self->_filename;
398              
399 28         34 my $file_type=undef;
400 28         34 my $version=undef;
401 28         30 my $release=undef;
402 28         29 my $rap_version=undef;
403 28         26 my $rap_release=undef;
404 28         28 my $buf_in;
405              
406              
407             ##
408             ## 1. If we decode the file we just encoded the file type, version and release should be empty
409             ##
410              
411 28         43 $self->{_version} = undef;
412 28         40 $self->{_release} = undef;
413 28         36 $self->{_supl_version} = undef; # Tap version inside the RAP file
414 28         43 $self->{_supl_release} = undef; # Tap release inside the RAP file
415 28         34 $self->{_file_type}=undef;
416              
417              
418             ##
419             ## 2. We get the file_type, version and release by matching strings
420             ##
421              
422 28 50       906 open FILE, "<$filename" or do { $self->{error}="$! for file $filename" ; return undef };
  0         0  
  0         0  
423 28         128 binmode FILE;
424              
425             # 1 Kb should be more than enough to find the Release and Version
426 28         405 read FILE, $buf_in, 1000;
427              
428 28         207 close FILE;
429              
430 28         155 $buf_in=unpack("H*", $buf_in);
431              
432              
433             ##
434             ## 3. Here we scan the buffer matching the patterns
435             ##
436              
437 28         233 while ($buf_in =~ /(?:
438             (^61.+5f814405) (?# For Tap files)
439             |
440             (^62) (?# For Notification files)
441             |
442             (^7f8416) (?# For Rap files)
443             |
444             (^7f8417) (?# For Acknowledment files)
445             |
446             (?:5f814901)(..) (?# Will match: SpecificationVersionNumber )
447             |
448             (?:5f813d01)(..) (?# Will match: ReleaseVersionNumber )
449             |
450             (?:5f842001)(..) (?# Will match: RapSpecificationVersionNumber )
451             |
452             (?:5f841f01)(..) (?# Will match: RapReleaseVersionNumber )
453             |
454             (^61.+5f2901)(..) (?# For NRTRDE files, and SpecificationVersionNumber for NRTRDE)
455             |
456             (?:5f2501)(..) (?# Will match: ReleaseVersionNumber for NRTRDE )
457             |
458             .
459             )/sgxo ) {
460 6090 50       7771 if (defined $1) {
461 0         0 $file_type="TAP";
462             }
463 6090 100       7053 if (defined $2) {
464 16         20 $file_type="NOT";
465             }
466 6090 50       7073 if (defined $3) {
467 0         0 $file_type="RAP";
468             }
469 6090 100       7063 if (defined $4) {
470 10         16 $file_type="ACK";
471             }
472 6090 100       7059 if (defined $5) {
473 16         62 $version=ord(pack("H*",$5));
474             }
475 6090 100       7530 if (defined $6) {
476 16         21 $release=ord(pack("H*",$6));
477             }
478 6090 50       6892 if (defined $7) {
479 0         0 $rap_version=ord(pack("H*",$7));
480             }
481 6090 50       7099 if (defined $8) {
482 0         0 $rap_release=ord(pack("H*",$8));
483             }
484 6090 100       7288 if (defined $9) {
485 2         4 $file_type="NRT";
486             }
487 6090 100       7289 if (defined $10) {
488 2         8 $version=ord(pack("H*",$10));
489             }
490 6090 100       12937 if (defined $11) {
491 2         8 $release=ord(pack("H*",$11));
492             }
493             }
494              
495             ##
496             ## 4. According to what is found we set the file_type, version and release.
497             ##
498              
499 28 50       54 if (!defined $file_type) {
500 0         0 $self->{error}="Unknown File format. Cannot decode.";
501 0         0 croak $self->error();
502             }
503              
504 28 100 66     182 if ($file_type eq "TAP" or $file_type eq "NOT") {
    50          
    100          
    50          
505 16 50 33     58 if (! $release or ! $version ) {
506 0         0 $self->{error}="'specificationVersionNumer' or 'releaseVersionNumber' not found in TAP File";
507 0         0 croak $self->error();
508             } else {
509 16         36 $self->{_version}=$version;
510 16         22 $self->{_release}=$release;
511 16         32 $self->{_file_type}="TAP";
512             }
513             } elsif ($file_type eq "RAP") {
514 0 0 0     0 if ( $rap_version && $rap_release ) {
515 0 0 0     0 if (! $release or ! $version ) {
516 0         0 $self->{error}="'specificationVersionNumer' or 'releaseVersionNumber' not found in RAP File";
517 0         0 croak $self->error();
518             } else {
519 0         0 $self->{_version}=$rap_version;
520 0         0 $self->{_release}=$rap_release;
521 0         0 $self->{_supl_version}=$version;
522 0         0 $self->{_supl_release}=$release;
523 0         0 $self->{_file_type}="RAP";
524             }
525             }
526             } elsif ($file_type eq "ACK") {
527 10         25 $self->{_version}=1;
528 10         18 $self->{_release}=4;
529 10         16 $self->{_supl_version}=3;
530 10         18 $self->{_supl_release}=10;
531 10         18 $self->{_file_type}="RAP";
532             } elsif ($file_type eq "NRT") {
533 2 50 33     14 if (! $release or ! $version ) {
534 0         0 $self->{error}="'specificationVersionNumer' or 'releaseVersionNumber' not found in NRT File";
535 0         0 croak $self->error();
536             } else {
537 2         6 $self->{_version}=$version;
538 2         4 $self->{_release}=$release;
539 2         4 $self->{_file_type}="NRT";
540             }
541             } else {
542 0         0 $self->{error}="Unknown File format. Cannot decode.";
543 0         0 croak $self->error();
544             }
545            
546 28         133 1;
547             }
548              
549              
550             #----------------------------------------------------------------
551             # Method: _select_spec_file
552             # Description: Selects the file with the ASN Specifications
553             # according to the version of the file.
554             # Nomenclature specified: TAP0309.asn for the spec-
555             # ifications of the TAP3r9 and RAP0102.asn for the
556             # specifications of the RAP1r2.
557             # Parameters: version
558             # release
559             # file_type
560             # Returns: filename of the Specification ASN.1
561             # Type: Private
562             # Restrictions: N/A
563             #----------------------------------------------------------------
564             sub _select_spec_file
565             {
566 19     19   32 my $self=shift;
567              
568 19         23 my $version=shift;
569 19         25 my $release=shift;
570 19         27 my $file_type=shift;
571              
572 19         122 $version=sprintf("%02d", $version);
573 19         49 $release=sprintf("%02d", $release);
574              
575 19         27 my $spec_file;
576              
577 19         29 NEXT_CYCLE1: foreach ( @{$self->_asn_path} ) {
  19         62  
578 19         61 $spec_file=$_."/".$file_type.$version.$release.".asn";
579 19 50       47 if ( $spec_file ) {
580 19         72 last NEXT_CYCLE1;
581             }
582             }
583              
584 19   50     65 return $spec_file || return undef;
585             }
586              
587              
588              
589             #----------------------------------------------------------------
590             # Method: _select_asn_struct
591             # Description: Selects and prepares the ASN specification
592             # to be used.
593             # Parameters: N/A
594             # Returns: N/A
595             # Type: Private
596             # Restrictions: $self->version, $self->release and
597             # $self->file_type should defined.
598             #----------------------------------------------------------------
599             sub _select_asn_struct
600             {
601 28     28   58 my $self=shift;
602              
603 28         80 my $size;
604             my $spec_buf_in;
605 28         0 my $spec_buf_in_tmp;
606              
607             ##
608             ## 1. Select the ASN.1 structure
609             ##
610              
611             ##
612             ## 1.1. Main ASN.1 structure file.
613             ##
614              
615 28 100       82 if ( ! $self->spec_file ) {
616 14 50       44 $self->spec_file($self->_select_spec_file($self->{_version}, $self->{_release}, $self->file_type)) || return undef;
617             }
618              
619             ##
620             ## 1.2. If we are working with a RAP file we need to know also the version of TAP Inside the RAP.
621             ##
622              
623 28 100 100     93 if ( ! $self->supl_spec_file and $self->file_type eq "RAP" ) {
624 5 50       15 $self->supl_spec_file($self->_select_spec_file($self->{_supl_version}, $self->{_supl_release}, "TAP")) || return undef;
625             }
626              
627             ##
628             ## 2. The content of the definitions files are stored into a scalar.
629             ##
630              
631             ##
632             ## 2.1. First the definition file is opend and the content filtered and stored into $spec_buf_in
633             ##
634              
635 28 50       63 ($size) = (stat($self->spec_file))[7] or do { $self->{error}="$! reading ".$self->spec_file; return undef };
  0         0  
  0         0  
636 28 50       126 open FILE, "<".$self->spec_file or do { $self->{error}="$! opening ".$self->spec_file; return undef };
  0         0  
  0         0  
637              
638 28         1949 while () {
639 25172 100       32193 if ( /^...Structure of a (... batch|...... record)/.../END/ ) {
640 23812 100 100     45026 if ( $_ !~ m/Structure of a (Tap batch|NRTRDE)/ and $_ !~ m/END/ ) {
641 23766         33141 $spec_buf_in_tmp=$spec_buf_in_tmp.$_;
642             }
643             }
644             }
645              
646 28         272 close FILE;
647              
648             ##
649             ## 2.2. If it is a RAP file, we read as well the specification of its tap file.
650             ##
651              
652 28 100       125 if ( $self->file_type eq "RAP" ) {
653 10 50       30 ($size) = (stat($self->supl_spec_file))[7] or do { $self->{error}="$! reading ".$self->supl_spec_file; return undef };
  0         0  
  0         0  
654 10 50       45 open FILE, "<".$self->supl_spec_file or do { $self->{error}="$! opening ".$self->supl_spec_file; return undef };
  0         0  
  0         0  
655 10         188 while () {
656 16190 100       21299 if ( /^...Structure of a ... batch/.../END/ ) {
657 15710 100 100     32154 if ( $_ !~ m/Structure of a Tap batch/ and $_ !~ m/END/ ) {
658 15690         23644 $spec_buf_in_tmp=$spec_buf_in_tmp.$_;
659             }
660             }
661             }
662 10         105 close FILE;
663             }
664              
665             # Following algorithm will strip the chain ",\n..." since the three dots and a comma
666             # in the last element is not supported by Convert::ASN1
667              
668             ### 20120501: Following code was commented out because of performance.
669             ### The specifications were modified instead.
670              
671             # while($spec_buf_in_tmp =~ /(?:
672             # (,[^\n]*\n(?:\s|\t)*?\.\.\.[^\n,]*\n)
673             # |
674             # ([\s|\t]*?\.\.\.(?:\s|\t)*?,[^\n]*\n)
675             # |
676             # (\(SIZE\(\d+(?:\.\.\d+)*?\)\))
677             # |
678             # (.*?)
679             # )/sgxo) {
680             # if (defined $1 or defined $2 or defined $3) {
681             # $spec_buf_in=$spec_buf_in."\n";
682             # } else {
683             # $spec_buf_in=$spec_buf_in."$+";
684             # }
685             # }
686              
687 28         1083 $spec_buf_in = $spec_buf_in_tmp;
688              
689             ##
690             ## 3. let's prepare the asn difinition.
691             ##
692              
693 28         161 my $asn = $self->_asn;
694 28 50       169 $asn->prepare( $spec_buf_in ) or do { $self->{error}=$asn->error; return undef };
  0         0  
  0         0  
695              
696              
697             ##
698             ## 4. Initialization with DataInterChange
699             ##
700              
701 28         6212902 my $dic_asn;
702 28 100       181 if ( $self->file_type eq "TAP" ) {
    100          
703 16 50       72 $dic_asn = $asn->find('DataInterChange') or do { $self->{error}=$asn->error; return undef };
  0         0  
  0         0  
704             } elsif ( $self->file_type eq "NRT" ) {
705 2 50       12 $dic_asn = $asn->find('Nrtrde') or do { $self->{error}=$asn->error; return undef };
  0         0  
  0         0  
706             } else {
707 10 50       47 $dic_asn = $asn->find('RapDataInterChange') or do { $self->{error}=$asn->error; return undef };
  0         0  
  0         0  
708             }
709 28         611 $self->_dic_asn($dic_asn);
710              
711             }
712              
713              
714              
715             #----------------------------------------------------------------
716             # Method: decode
717             # Description: decodes the TAP/RAP/NRT file into a HASH for its
718             # later editing.
719             # Parameters: filename
720             # Returns: N/A
721             # Type: Public
722             # Restrictions: N/A
723             #----------------------------------------------------------------
724             sub decode {
725 14     14 0 36 my $self=shift;
726              
727 14         20 my $filename=shift;
728 14         24 my $buf_in;
729             my $size;
730            
731 14         41 $self->_filename($filename);
732              
733              
734             ##
735             ## 1. Get the version to decode the file.
736             ##
737              
738 14 50       43 $self->_get_file_version || return undef;
739              
740              
741             ##
742             ## 2. Selection of ASN Structure.
743             ##
744              
745 14 50       56 $self->_select_asn_struct || return undef;
746              
747              
748             ##
749             ## 3. We open and read all the TAP/RAP/NRT file at once.
750             ##
751              
752 14         49 my $FILE;
753 14 50       1391 open $FILE, "<$filename" or do { $self->{error}="$! opening $filename"; return undef };
  0         0  
  0         0  
754 14         101 binmode $FILE;
755 14         92 asn_read ($FILE, $buf_in);
756 14         1225 close $FILE;
757              
758              
759             ##
760             ## 4. Decode file buffer into the ASN1 tree.
761             ##
762              
763 14 50       64 $self->{_dic_decode} = $self->_dic_asn->decode($buf_in) or do { $self->{error}=$self->_dic_asn->error; croak $self->error() };
  0         0  
  0         0  
764              
765             }
766              
767              
768              
769             #----------------------------------------------------------------
770             # Method: encode
771             # Description: encode the HASH structure into a new TAP/RAP/NRT
772             # file
773             # Parameters: filename
774             # Returns: N/A
775             # Type: Public
776             # Restrictions: N/A
777             #----------------------------------------------------------------
778             sub encode {
779              
780 14     14 0 42 my $self = shift;
781              
782 14         30 my $filename=shift;
783 14         59 $self->_filename($filename);
784              
785              
786             ##
787             ## 1. _dic_decode will be the decoded tree of a real tap file
788             ##
789              
790             ##
791             ## 2. Select structure according to version, release and type.
792             ##
793              
794             ## In the case we want just to encode, we need to select and prepare
795             ## the structure we want to use. E.g If we want to get a TAP3r9
796             ## we need to select the ASN.1 structure for the TAP3r9
797 14 50       40 $self->_select_asn_struct || return undef;
798              
799              
800             ##
801             ## 3. Encode ASN1 tree into the file.
802             ##
803              
804 14 50       47 my $buf_out = $self->_dic_asn->encode($self->_dic_decode) or do { $self->{error}=$self->_dic_asn->error; croak $self->error() };
  0         0  
  0         0  
805              
806              
807             ##
808             ## 4. Write and close file
809             ##
810              
811 14 50       8277 open FILE_OUT, ">$filename" or do { $self->{error}="$! writing $filename"; croak $self->error() };
  0         0  
  0         0  
812 14         368 binmode FILE_OUT;
813 14         505 print FILE_OUT $buf_out ;
814 14         2712 close FILE_OUT;
815             }
816              
817       0     sub DESTROY {}
818              
819 0     0 0   sub error { $_[0]->{error} }
820              
821             1;