File Coverage

blib/lib/Net/IPP/IPPUtil.pm
Criterion Covered Total %
statement 38 138 27.5
branch 4 42 9.5
condition 0 18 0.0
subroutine 7 23 30.4
pod 0 18 0.0
total 49 239 20.5


line stmt bran cond sub pod time code
1             ###
2             # Copyright (c) 2004 Matthias Hilbig
3             # All rights reserved.
4             #
5             # This program is free software; you may redistribute it and/or modify it
6             # under the same terms as Perl itself.
7             #
8              
9             package Net::IPP::IPPUtil;
10              
11 2     2   12 use strict;
  2         4  
  2         75  
12 2     2   11 use warnings;
  2         4  
  2         70  
13              
14 2     2   11 use Net::IPP::IPP qw(:all);
  2         5  
  2         4351  
15              
16             require Exporter;
17             our @ISA = ("Exporter");
18             our @EXPORT_OK = qw(ippToString printIPP bytesToString printBytes searchGroup findAttribute findNextAttribute
19             findGroup findNextGroup isSuccessful printerStateToString jobStateToString operationToString groupToString
20             statusToString statusToDetailedString);
21             our %EXPORT_TAGS = ( 'all' => \@EXPORT_OK );
22              
23             ###
24             # convert group to string
25             #
26             # Parameter: $group - group to convert
27             #
28             # Return: $string with converted group
29             #
30             sub groupStructureToString($) {
31 0     0 0 0 my $group = shift;
32 0         0 my $string = "";
33 0         0 $string .= "GROUP " . groupToString($group->{&TYPE}) . "\n";
34 0         0 foreach my $key (sort keys %{$group}) {
  0         0  
35 0 0       0 if ($key ne &TYPE) {
36 0         0 my $value = $group->{$key};
37            
38 0 0       0 if (ref($value) eq 'HASH') {
39 0         0 $value = $value->{&VALUE};
40             }
41            
42 0 0       0 if (ref($value) eq 'ARRAY') {
43 0         0 $string .= " " . $key . " = [";
44 0         0 foreach my $val (@{$value}) {
  0         0  
45 0         0 $string .= "$val, ";
46             }
47 0         0 $string .= "]\n";
48             } else {
49 0         0 $string .= " " . $key . " = " . $value . "\n";
50             }
51             }
52             }
53 0         0 return $string;
54             }
55              
56             ###
57             # Convert perl structure to string
58             #
59             # Parameter: $ipp - IPP request to convert
60             #
61             # Return: $string with converted perl structure
62             #
63             sub ippToString($) {
64 0     0 0 0 my $ipp = shift;
65 0         0 my $string = "";
66 0 0       0 $string .= "URL: " . $ipp->{&URL} . "\n" if exists($ipp->{&URL});
67 0 0       0 $string .= "REQUEST-ID: " . $ipp->{&REQUEST_ID} . "\n" if exists($ipp->{&REQUEST_ID});
68 0 0       0 $string .= "STATUS: " . $ipp->{&STATUS} ." (" .statusToDetailedString($ipp->{&STATUS}) . ")\n" if exists($ipp->{&STATUS});
69 0 0       0 $string .= "OPERATION: " . operationToString($ipp->{&OPERATION}) . "\n" if exists($ipp->{&OPERATION});
70 0 0       0 $string .= "VERSION: " . $ipp->{&VERSION} . "\n" if exists($ipp->{&VERSION});
71 0 0       0 if (exists($ipp->{&GROUPS})) {
72 0         0 foreach my $group (@{$ipp->{&GROUPS}}) {
  0         0  
73 0         0 $string .= groupStructureToString($group);
74             }
75             }
76 0         0 return $string;
77             }
78              
79             ###
80             # print perl structure of IPP request/response
81             #
82             sub printIPP($) {
83 0     0 0 0 my $ipp = shift;
84 0         0 my $string = ippToString($ipp);
85 0         0 print $string;
86             }
87              
88             ###
89             # helper function to dump hexview of bytes
90             #
91             sub bytesToString($) {
92 2     2   40 use bytes;
  2         4  
  2         18  
93            
94 18     18 0 25 my $bytes = shift;
95 18         91 my @bytes = unpack("c*", $bytes);
96              
97 18         26 my $width = 16; #how many bytes to print per line
98 18         25 my $hexWidth = 3*$width;
99              
100 18         25 my $string = "";
101              
102 18         17 my $offset = 0;
103              
104 18         53 while ($offset *$width < length($bytes)) {
105 18         24 my $hexString = "";
106 18         20 my $charString = "";
107 18         42 for (my $i = 0; $i < $width; $i++) {
108 288 100       698 if ($offset*$width + $i < length($bytes)) {
109 113         106 my $char;
110 2     2   378 {use bytes;$char = substr($bytes, $offset*$width + $i, 1);}
  2         36  
  2         9  
  113         101  
  113         193  
111            
112 113         227 $hexString .= sprintf("%02X ", ord($char));
113 113 100       268 if ($char =~ /[\w\-\:]/) {
114 31         80 $charString .= $char;
115             } else {
116 82         194 $charString .= ".";
117             }
118             }
119             }
120            
121 18         85 $string .= sprintf("%-${hexWidth}s%s\n",$hexString,$charString);
122 18         57 $offset++;
123             }
124 18         1165 return $string;
125             }
126              
127             sub printBytes($) {
128 18     18 0 719 my $bytes = shift;
129 18         35 print bytesToString($bytes);
130             }
131              
132             ###
133             # Searches for attribute in group
134             #
135             # Parameter: $group - IPP group
136             # $name - name of IPP attribute
137             #
138             # Return: value of attribute if found, undef otherwise
139             #
140             sub searchGroup($$) {
141 0     0 0   my $group = shift;
142 0           my $name = shift;
143            
144 0           while (my ($key, $value) = each %{$group}) {
  0            
145 0 0         if ($key eq $name) {
146            
147             # reset hash iterator
148 0           keys %{$group};
  0            
149            
150 0           return $value;
151             }
152             }
153            
154 0           return undef;
155             }
156              
157              
158             ###
159             # Searches for next attribute in IPP structure
160             #
161             # Parameter: $ipp - IPP structure
162             # $name - name of IPP attribute
163             #
164             # Return: value of attribute if found, undef otherwise
165             #
166             # Each attribute must be unique in a group [RFC 2911 3.1.3],
167             # so it is only necessary to remember the last group that was searched.
168             #
169             my $lastAttributeIndex = -1;
170             sub findNextAttribute($$) {
171 0     0 0   my $ipp = shift;
172 0           my $name = shift;
173              
174 0           my @groups = @{$ipp->{&GROUPS}};
  0            
175 0           my $length = scalar(@groups);
176              
177             # search restarts automagically, because $lastAttributeIndex is
178             # initialized and resetted to -1
179 0           for (my $i = $lastAttributeIndex + 1; $i < $length; $i++) {
180 0           my $value = searchGroup($groups[$i], $name);
181 0 0         if (defined($value)) {
182 0           $lastAttributeIndex = $i;
183 0           return $value;
184             }
185             }
186              
187 0           $lastAttributeIndex = -1;
188 0           return undef;
189             }
190              
191             ###
192             # Search for first attribute in IPP structure
193             # Internally call findNextAttribute after resetting $lastIndex
194             #
195             # Parameter: $ipp - IPP structure
196             # $name - name of IPP attribute
197             #
198             # Return: value of attribute if found, undef otherwise
199             #
200             sub findAttribute($$) {
201 0     0 0   my $ipp = shift;
202 0           my $name = shift;
203            
204 0           $lastAttributeIndex = -1;
205              
206 0           return findNextAttribute($ipp, $name);
207             }
208              
209             ###
210             # Search for next group in IPP structure
211             #
212             # Parameter: $ipp - IPP structure
213             # $type - type of IPP group
214             #
215             # Return: group if a group with the specified type was found, undef otherwise
216             #
217             my $lastGroupIndex = -1;
218             sub findNextGroup($$) {
219 0     0 0   my $ipp = shift;
220 0           my $type = shift;
221 0           my @groups = @{$ipp->{&GROUPS}};
  0            
222 0           my $length = scalar(@groups);
223              
224             # search restarts automagically, because $lastGroupIndex is
225             # initialized and resetted to -1
226 0           for (my $i = $lastGroupIndex + 1; $i < $length; $i++) {
227 0           my $groupType = $groups[$i]->{&TYPE};
228 0 0         if ($groupType == $type) {
229 0           $lastGroupIndex = $i;
230 0           return $groups[$i];
231             }
232             }
233              
234 0           $lastGroupIndex = -1;
235 0           return undef;
236             }
237              
238             ###
239             # Search for first group in IPP structure
240             #
241             # Parameter: $ipp - IPP structure
242             # $type - type of IPP group
243             #
244             # Return: group if a group with the specified type was found, undef otherwise
245             #
246             sub findGroup($$) {
247 0     0 0   my $ipp = shift;
248 0           my $type = shift;
249            
250 0           $lastGroupIndex = -1;
251              
252 0           return findNextGroup($ipp, $type);
253             }
254              
255             ###
256             # returns 1 if IPP request was successful, 0 otherwise
257             #
258             # Parameter: $response - IPP response
259             #
260             # Return: 1 if successful request, 0 otherwise
261             #
262             sub isSuccessful($) {
263 0     0 0   my $response = shift;
264 0 0         if (exists($response->{&STATUS})) {
265 0           my $status = $response->{&STATUS};
266 0   0       return ($status >= 0x0000 and $status <= 0x00ff);
267             }
268 0           return 0;
269             }
270              
271             ###
272             # look for key in the specified hash and return value if the key exists.
273             #
274             # Parameter: $key - key for hash
275             # $hashref - reference to hash
276             #
277             # Return: value in hash if key exists, "unknown" otherwise
278             #
279             sub hashResolve($$) {
280 0     0 0   my $key = shift;
281 0           my $hashref = shift;
282              
283 0 0         if (exists($hashref -> {$key})) {
284 0           return $hashref->{$key};
285             } else {
286 0           return "unknown";
287             }
288             }
289              
290             ###
291             # The following functions are all build similar and could be made more complicated with AUTOLOADER :-)
292             # All functions use hashResolve to transform value to string.
293             #
294             # Parameter: $value - value to transform to string
295             #
296             # Return: $value transformed to string
297             #
298              
299             sub printerStateToString($) {
300 0     0 0   my $state = shift;
301 0           return hashResolve($state, \%Net::IPP::IPP::printerState);
302             }
303              
304             sub jobStateToString($) {
305 0     0 0   my $state = shift;
306 0           return hashResolve($state, \%Net::IPP::IPP::jobState);
307             }
308              
309             sub operationToString($) {
310 0     0 0   my $operation = shift;
311 0           return hashResolve($operation, \%Net::IPP::IPP::operation);
312             }
313              
314             sub groupToString($) {
315 0     0 0   my $group = shift;
316 0           return hashResolve($group, \%Net::IPP::IPP::group);
317             }
318              
319             sub statusToDetailedString($) {
320 0     0 0   my $status = shift;
321 0           return hashResolve($status, \%Net::IPP::IPP::statusCodes);
322             }
323              
324             ###
325             # returns type of IPP status.
326             #
327             # Parameter: $status - IPP status
328             #
329             # Return:
330             # "informational" - Request received, continuing process
331             # "successful" - The action was successfully received, understood, and accepted
332             # "redirection" - Further action must be taken in order to complete the request
333             # "client-error" - The request contains bad syntax or cannot be fulfilled
334             # "server-error" - The IPP object failed to fulfill an apparently valid request
335             #
336             sub statusToString($) {
337 0     0 0   my $status = shift;
338 0 0 0       if ($status >= 0x0000 and $status <= 0x00ff) {
    0 0        
    0 0        
    0 0        
    0 0        
339 0           return "successful";
340             } elsif ($status >= 0x0100 and $status <= 0x01ff) {
341 0           return "informational";
342             } elsif ($status >= 0x0200 and $status <= 0x02ff) {
343 0           return "redirection";
344             } elsif ($status >= 0x0400 and $status <= 0x04ff) {
345 0           return "client-error";
346             } elsif ($status >= 0x0500 and $status <= 0x05ff) {
347 0           return "server-error";
348             }
349             }
350              
351              
352             1;
353             __END__