File Coverage

blib/lib/Symantec/PCAnywhere/Profile/CHF.pm
Criterion Covered Total %
statement 35 35 100.0
branch n/a
condition n/a
subroutine 10 10 100.0
pod 1 1 100.0
total 46 46 100.0


line stmt bran cond sub pod time code
1             package Symantec::PCAnywhere::Profile::CHF;
2              
3 2     2   27324 use strict;
  2         4  
  2         74  
4 2     2   10 use warnings;
  2         4  
  2         97  
5              
6             =head1 NAME
7              
8             Symantec::PCAnywhere::Profile::CHF - Encodes and decodes Symantec pcAnywhere connection
9             profiles
10              
11             =head1 SYNOPSIS
12              
13             use Symantec::PCAnywhere::Profile::CHF;
14            
15             # Load CHF file from file
16             my $chf = new Symantec::PCAnywhere::Profile::CHF(filename => $filename);
17            
18             # Load CHF data directly
19             my $chf = new Symantec::PCAnywhere::Profile::CHF(data => $data);
20            
21             my $results = $chf->get_attrs(
22             Location,
23             Password,
24             Hostname,
25             DataPort
26             );
27             while (my ($attr, $value) = each (%$results)) {
28             print "$attr\t= $value\n";
29             }
30            
31             # Create an empty CHF
32             my $chf = new Symantec::PCAnywhere::Profile::CHF;
33             $chf->set_attrs(
34             PhoneNumber => 7652314,
35             AreaCode => 999,
36             IPAddress => '10.10.128.99',
37             ControlPort => 5900
38             );
39            
40             # Print the binary CHF file
41             print $chf->encode;
42              
43              
44             =head1 DESCRIPTION
45              
46             This module is responsible for decoding of a pcAnywhere .CHF file
47             that describes a remote system the client wishes to connect to.
48             CHF files seem to always be the same size (3308 bytes), which is helpful
49             for decoding.
50              
51             See this module's base class (L) for more
52             information on the decoding mechanism.
53              
54             =head1 VERSION
55              
56             Version 0.06
57              
58             =cut
59              
60             our $VERSION = '0.06';
61              
62 2     2   8 use strict;
  2         5  
  2         52  
63 2     2   8 use warnings;
  2         3  
  2         72  
64              
65 2     2   9 use base qw(Symantec::PCAnywhere::Profile);
  2         2  
  2         717  
66 2     2   4494 use Compress::Zlib;
  2         205761  
  2         721  
67 2     2   2280 use MIME::Base64;
  2         2381  
  2         853  
68              
69             # Compressed and encoded template CHF
70             my $chf_template = uncompress(decode_base64(<<'TEMPLATE'));
71             eJz7t4qB4Q0PAwMjEBpwMzA45STmZTOAgYJzYk4OwygYBaNgRADGgXYAkQDsTq6BdsUooBPg5Q5x
72             DtD3DKDACKSUzczAxAgElDpqFIyCUTAKhhL4P9AOGGAAAOhdCT4=
73             TEMPLATE
74              
75             my %FIELDS_CHF = (
76             # off len type
77             # ---- --- ----
78             ConnectionName => [ 16, 182, 0 ],
79             FilePassword => [ 280, 128, 0 ],
80             SaveSessionFile => [ 744, 128, 0 ],
81             ScriptFileName => [ 889, 128, 0 ],
82             PhoneNumber => [ 1038, 31, 0 ],
83             Location => [ 1069, 128, 0 ],
84             AreaCode => [ 1210, 40, 0 ],
85             IPAddress => [ 1324, 128, 0 ],
86             ConxType => [ 1701, 64, 0 ],
87             ConnCount => [ 1913, 1, 2 ],
88             RetrySecs => [ 1914, 1, 2 ],
89             Gateway => [ 1928, 24, 0 ],
90             Hostname => [ 1940, 128, 0 ],
91             Domain_Logname => [ 2093, 128, 0 ],
92             Password => [ 2222, 128, 0 ],
93             # TODO: Find what is missing between these
94             DenyLowerEncr => [ 3050, 1, 2 ],
95             EncrLevel => [ 3052, 1, 2 ],
96             PrivKeyContainer => [ 3053, 48, 0 ],
97             CertCommonName => [ 3103, 48, 0 ],
98             DataPort => [ 3154, 2, 3 ],
99             ControlPort => [ 3156, 2, 3 ],
100             );
101              
102             =head1 METHODS
103              
104             Here is the public API; see this module's base class documentation for more
105             information on the inner workings of the encoding and decoding process, as well
106             as additional useful methods.
107              
108             =over 4
109              
110             =item new
111              
112             my $chf = new Symantec::PCAnywhere::Profile::CHF;
113             my $chf = new Symantec::PCAnywhere::Profile::CHF(-filename => $filename);
114             my $chf = new Symantec::PCAnywhere::Profile::CHF(filename => $filename);
115             my $chf = new Symantec::PCAnywhere::Profile::CHF(-data => $chfdata);
116             my $chf = new Symantec::PCAnywhere::Profile::CHF(data => $chfdata);
117              
118             The "new" constructor takes any number of arguments and sets the appropriate
119             flags internally before returning a new object. The arguments are considered as
120             a list of key-value pairs which are inserted into the object data.
121              
122             =cut
123              
124             sub new {
125 3     3 1 781 my $type = shift;
126 3         21 my %defaults = (
127             fields => \%FIELDS_CHF,
128             template => $chf_template,
129             );
130              
131 3         31 my $self = $type->SUPER::new(%defaults, @_);
132 3         12 return $self;
133             }
134              
135             =item _decode_pca_file
136              
137             Provided with XOR-encoded CHF data, un-obscure the whole
138             thing into the "clear" format. The return value is the same
139             length as the input string, but after XOR decoding.
140              
141             =cut
142              
143             sub _decode_pca_file ($$) {
144 1     1   2 my $self = shift;
145 1         3 my $rawdata = $self->{data};
146              
147 1         3 my $part1 = substr($rawdata, 0, 444);
148 1         4 my $part2 = substr($rawdata, 444);
149              
150 1         16 return $self->_rawdecode(255, 0, $part1)
151             . $self->_rawdecode(255, 0x54, $part2);
152              
153             }
154              
155             =item _encode_pca_file
156              
157             Provided with XOR-unencoded CHF data, obscure the whole
158             thing into the "encrypted" format. The return value is the
159             same length as the input string, but after XOR encoding.
160              
161             =cut
162              
163             sub _encode_pca_file ($$) {
164 2     2   4 my $self = shift;
165 2         5 my $rawdata = $self->{decoded};
166              
167 2         5 my $part1 = substr($rawdata, 0, 444);
168 2         15 my $part2 = substr($rawdata, 444);
169              
170 2         15 return $self->_rawencode(255, 0, $part1)
171             . $self->_rawencode(255, 0x54, $part2);
172             }
173              
174             =back
175              
176             =head1 SEE ALSO
177              
178             This module is based very heavily on the work of Stephen Friedl at
179             http://www.unixwiz.net/tools/pcainfo.htmlZ<>.
180              
181             =head1 TO DO
182              
183             Very early in the file is a "description" field that we are not
184             quite decoding properly.
185              
186             The "hostname" and "IP Address" fields seem to be redundant,
187             and this requires more research.
188              
189             There are still plenty of big unused fields in the .CHF file,
190             and we ought to find out what they are used for. Try looking
191             at the other protocols (ISDN, SPX, NETBIOS, etc.)
192              
193             Based on http://www.cpan.org/modules/00modlist.long.html#ID2_GuidelinesfZ<>,
194             refactor code to pass references to lists instead of lists.
195              
196             =head1 BUGS / CAVEATS
197              
198             They're in there somewhere. Let me know what you find.
199              
200             =head1 AUTHOR
201              
202             Darren Kulp, Ekulp@thekulp.comE, based on code from
203             Stephen J. Friedl, (http://unixwiz.net/)
204              
205             =head1 COPYRIGHT AND LICENSE
206              
207             This code is in the public domain. Contains code placed in the public domain
208             2002 by Stephen Friedl.
209              
210             "Symantec" and "pcAnywhere" are trademarks of Symantec Corp.
211              
212             =cut
213              
214             1;
215             __END__