File Coverage

blib/lib/Device/Gsm/Sms/Token/SCA.pm
Criterion Covered Total %
statement 39 64 60.9
branch 6 14 42.8
condition 1 6 16.6
subroutine 4 5 80.0
pod n/a
total 50 89 56.1


line stmt bran cond sub pod time code
1             # Sms::Token::SCA - SMS SCA token (service center address)
2             # Copyright (C) 2002-2006 Cosimo Streppone, cosimo@cpan.org
3             #
4             # This program is free software; you can redistribute it and/or modify
5             # it only under the terms of Perl itself.
6             #
7             # This program is distributed in the hope that it will be useful,
8             # but WITHOUT ANY WARRANTY; without even the implied warranty of
9             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10             # Perl licensing terms for details.
11             #
12             # $Id$
13              
14             package Sms::Token::SCA;
15 6     6   32 use integer;
  6         13  
  6         28  
16 6     6   152 use strict;
  6         14  
  6         159  
17 6     6   28 use Device::Gsm::Sms::Token;
  6         15  
  6         3940  
18              
19             @Sms::Token::SCA::ISA = ('Sms::Token');
20              
21             # takes (scalar message (string) reference)
22             # returns success/failure of decoding
23             # if all ok, removes SCA from message
24             sub decode {
25 9     9   23 my ($self, $rMessage) = @_;
26 9         13 my $ok = 0;
27 9         17 my ($length, $type, $address);
28 9         17 my $msg = $$rMessage;
29 9         15 my $msg_copy = $msg;
30              
31             # .------------.----------.---------------------------------.
32             # | LENGTH (1) | TYPE (1) | ADDRESS BCD DIGITS (0-8 octets) |
33             # `------------'----------'---------------------------------'
34 9         19 $length = substr $msg, 0, 2;
35              
36             # If length is `00', SCA = default end decoding ends
37 9 100       27 if ($length eq '00') {
38 2         8 $self->data('');
39 2         6 $self->state(Sms::Token::DECODED);
40              
41             # Remove length-octet read from message
42 2         5 $$rMessage = substr($$rMessage, 2);
43 2         9 return 1;
44             }
45              
46             # Begin decoding (length is number of octets for the SCA + 1 (length) )
47 7         18 $length = hex $length;
48              
49             # Length > 9 is impossible; max is 8 + 1 (length)
50 7 50       33 if ($length > 9) {
51 0         0 $self->data(undef);
52 0         0 $self->state(Sms::Token::ERROR);
53 0         0 return 0;
54             }
55              
56 7         38 $self->set('length' => $length);
57              
58             # Get type of message (81 = national, 91 = international)
59 7         15 $type = substr $msg, 2, 2;
60 7 50 33     48 if ($type ne '81' and $type ne '91') {
61 0         0 $self->data(undef);
62 0         0 $self->state(Sms::Token::ERROR);
63 0         0 return 0;
64             }
65              
66 7         23 $self->set(type => $type);
67              
68             # Get rest of address
69 7         25 $address = substr $msg, 4, (($length - 1) << 1);
70              
71             # Reverse each pair of bcd digits
72 7         7 my $sca;
73 7         22 while ($address) {
74 40         57 $sca .= reverse substr($address, 0, 2);
75 40         83 $address = substr $address, 2;
76             }
77              
78             # Truncate last `F' if found (XXX)
79 7 50       24 chop $sca if substr($sca, -1) eq 'F';
80              
81             # If sca is international, put a '+' sign before
82 7 50       22 $sca = '+' . $sca if $type eq '91';
83              
84 7         34 $self->data($sca);
85 7         18 $self->set(type => $type);
86 7         23 $self->set('length' => $length);
87 7         29 $self->state(Sms::Token::DECODED);
88              
89             # Remove SCA info from message
90 7         32 $$rMessage = substr($msg, ($length + 1) << 1);
91              
92 7         52 return 1;
93             }
94              
95             #
96             # [token]->encode( [$data] )
97             #
98             # takes internal token data and encodes it, returning the result
99             # or undef value in case of errors
100             #
101             sub encode {
102 0     0     my $self = shift;
103              
104             # Take supplied data (optional) or object internal data
105 0           my $data = shift;
106 0 0 0       if (!defined $data || $data eq '') {
107 0           $data = $self->data();
108             }
109              
110             # Begin encoding as SCA
111 0           $data =~ s/\s+//g;
112              
113 0 0         my $type = index($data, '+') == 0 ? 91 : 81;
114              
115             # Remove all non-numbers
116 0           $data =~ s/\D//g;
117              
118 0           my $len = unpack 'H2' => chr(length $data);
119              
120 0           $data .= 'F';
121 0           my @digit = split // => $data;
122 0           my $encoded;
123              
124 0           while (@digit > 1) {
125 0           $encoded .= join '', reverse splice @digit, 0, 2;
126             }
127              
128 0           $data = uc $len . $type . $encoded;
129              
130 0           $self->data($data);
131 0           $self->set('length' => $len);
132 0           $self->set('type' => $type);
133 0           $self->state(Sms::Token::ENCODED);
134              
135 0           return $data;
136              
137             }
138              
139             1;