File Coverage

blib/lib/TAP3/Tap3edit.pm
Criterion Covered Total %
statement 213 280 76.0
branch 87 132 65.9
condition 13 29 44.8
subroutine 27 31 87.1
pod 0 15 0.0
total 340 487 69.8


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