File Coverage

lib/SMB/Parser.pm
Criterion Covered Total %
statement 66 69 95.6
branch 12 14 85.7
condition 11 13 84.6
subroutine 24 27 88.8
pod 21 22 95.4
total 134 145 92.4


line stmt bran cond sub pod time code
1             # SMB Perl library, Copyright (C) 2014-2018 Mikhael Goikhman, migo@cpan.org
2             #
3             # This program is free software: you can redistribute it and/or modify
4             # it under the terms of the GNU General Public License as published by
5             # the Free Software Foundation, either version 3 of the License, or
6             # (at your option) any later version.
7             #
8             # This program is distributed in the hope that it will be useful,
9             # but WITHOUT ANY WARRANTY; without even the implied warranty of
10             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11             # GNU General Public License for more details.
12             #
13             # You should have received a copy of the GNU General Public License
14             # along with this program. If not, see .
15              
16             package SMB::Parser;
17              
18 5     5   1980 use strict;
  5         9  
  5         143  
19 5     5   26 use warnings;
  5         10  
  5         140  
20              
21 5     5   550 use bytes;
  5         22  
  5         28  
22 5     5   2814 use if (1 << 32 == 1), 'bigint'; # support native uint64 on 32-bit platforms
  5         57  
  5         27  
23 5     5   1894 use Encode 'decode';
  5         27952  
  5         4954  
24              
25             sub new ($$) {
26 6     6 1 415 my $class = shift;
27 6   100     28 my $data = shift // "";
28              
29 6         14 my $self = bless {}, $class;
30              
31 6         20 return $self->set($data);
32             }
33              
34             sub reset ($;$) {
35 38     38 1 2328 my $self = shift;
36 38   100     137 my $offset = shift || 0;
37 38 50       83 die "Negative offset is invalid" if $offset < 0;
38              
39 38         62 $self->{offset} = $offset;
40              
41 38         99 return $self;
42             }
43              
44             sub set ($$;$) {
45 20     20 1 37 my $self = shift;
46              
47 20         52 $self->{data} = $_[0];
48 20         39 $self->{size} = length($_[0]);
49              
50 20         72 return $self->reset($_[1]);
51             }
52              
53             sub cut ($;$) {
54 3     3 1 4 my $self = shift;
55 3   66     9 my $offset = shift || $self->{offset};
56 3 50       9 die "Negative offset is invalid" if $offset < 0;
57              
58 3 100       12 $offset = $self->{size} if $offset > $self->{size};
59 3 100       11 $self->{offset} = $offset if $offset > $self->{offset};
60              
61 3         14 return $self->set(substr($self->{data}, $offset) . "", $self->{offset} - $offset);
62             }
63              
64 4     4 1 12 sub data { $_[0]->{data} }
65 5     5 1 14 sub size { $_[0]->{size} }
66 26     26 1 78 sub offset { $_[0]->{offset} }
67              
68             my %UINT_MODS = (
69             +1 => 'C',
70             +2 => 'v',
71             +4 => 'V',
72             -1 => 'C',
73             -2 => 'n',
74             -4 => 'N',
75             );
76              
77             sub uint ($$;$) {
78 257     257 0 300 my $self = shift;
79 257         268 my $n_bytes = shift;
80 257 100       355 my $be_factor = shift() ? -1 : 1;
81              
82 257         499 return unpack($UINT_MODS{$be_factor * $n_bytes}, $self->bytes($n_bytes));
83             }
84              
85             sub str ($$;$) {
86 18     18 1 29 my $self = shift;
87 18         37 my $n_bytes = shift;
88 18   50     60 my $enc = shift || 'UTF-16LE';
89              
90 18         41 return decode($enc, $self->bytes($n_bytes));
91             }
92              
93             sub bytes ($$) {
94 304     304 1 336 my $self = shift;
95 304         304 my $n_bytes = shift;
96              
97             my $n_avail = $self->{offset} + $n_bytes > $self->{size}
98 304 100       515 ? $self->{size} - $self->{offset} : $n_bytes;
99              
100 304 100       599 my $bytes = $self->{offset} > $self->{size} ? '' : substr($self->{data}, $self->{offset}, $n_avail);
101 304         344 $self->{offset} += $n_bytes;
102              
103 304         1035 return $bytes;
104             }
105              
106             sub skip ($) {
107 39     39 1 51 my $self = shift;
108 39         46 my $n_bytes = shift;
109              
110 39         52 $self->{offset} += $n_bytes;
111              
112 39         74 return $self;
113             }
114              
115             sub align ($;$$) {
116 12     12 1 16 my $self = shift;
117 12   100     36 my $offset = shift || 0;
118 12   100     24 my $step = shift || 4;
119              
120 12         22 $self->skip(($step - ($self->offset - $offset) % $step) % $step);
121             }
122              
123 38     38 1 5397 sub uint8 { uint($_[0], 1 ); }
124 64     64 1 2110 sub uint16 { uint($_[0], 2 ); }
125 146     146 1 1138 sub uint32 { uint($_[0], 4 ); }
126 6     6 1 2009 sub uint16_be { uint($_[0], 2, 1); }
127 3     3 1 801 sub uint32_be { uint($_[0], 4, 1); }
128 45     45 1 80 sub uint64 { uint32($_[0]) + (uint32($_[0]) << 32); }
129 0     0 1 0 sub utf16 { str($_[0], $_[1]); }
130 0     0 1 0 sub utf16_be { str($_[0], $_[1], 'UTF-16BE'); }
131 0     0 1 0 sub fid1 { uint16($_[0]); }
132 7     7 1 19 sub fid2 { [ uint64($_[0]), uint64($_[0]) ]; }
133              
134             1;
135              
136             __END__