File Coverage

blib/lib/Tk/IPEntry.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             package Tk::IPEntry;
2             #------------------------------------------------
3             # automagically updated versioning variables -- CVS modifies these!
4             #------------------------------------------------
5             our $Revision = '$Revision: 1.9 $';
6             our $CheckinDate = '$Date: 2002/12/11 16:24:03 $';
7             our $CheckinUser = '$Author: xpix $';
8             # we need to clean these up right here
9             $Revision =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
10             $CheckinDate =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
11             $CheckinUser =~ s/^\$\S+:\s*(.*?)\s*\$$/$1/sx;
12             #-------------------------------------------------
13             #-- package Tk::Graph ----------------------------
14             #-------------------------------------------------
15            
16             # -------------------------------------------------------
17             #
18             # Tk/IPEntry.pm
19             #
20             # A Megawidget for Input Ip-Adresses Ipv4 and Ipv6
21             #
22            
23             =head1 NAME
24            
25             Tk::IPEntry - A megawidget for input of IP-Adresses IPv4 and IPv6
26            
27             =head1 SYNOPSIS
28            
29             use Tk;
30             use Tk::IPEntry;
31            
32             my $mw = MainWindow->new();
33             my $ipadress;
34            
35             my $entry = $mw->IPEntry(
36             -variable => \$ipadress,
37             )->pack(-side => 'left');
38            
39             $ipadress = '129.2.32.1';
40            
41             MainLoop;
42            
43             =cut
44            
45             # -------------------------------------------------------
46             # ------- S O U R C E -----------------------------------
47             # -------------------------------------------------------
48 1     1   779 use strict;
  1         2  
  1         30  
49 1     1   5 use Carp;
  1         1  
  1         126  
50            
51 1     1   1607 use Tk;
  0            
  0            
52             use Tk::NumEntry;
53             use Tk::HexEntry;
54             use Tie::Watch;
55             use Net::IP;
56            
57             # That's the Base
58             use base qw/Tk::Frame/;
59            
60             # ... and construct the Widget!
61             Construct Tk::Widget 'IPEntry';
62            
63             # ------------------------------------------
64             sub ClassInit {
65             # ------------------------------------------
66             # ClassInit is called once per MainWindow, and serves to
67             # perform tasks for the class as a whole. Here we create
68             # a Photo object used by all instances of the class.
69            
70             my ($class, $mw) = @_;
71            
72             $class->SUPER::ClassInit($mw);
73            
74             } # end ClassInit
75            
76             # ------------------------------------------
77             sub Populate {
78             # ------------------------------------------
79             my ($obj, $args) = @_;
80             my %specs;
81             #-------------------------------------------------
82             $obj->{type} = delete $args->{-type} || 'ipv4';
83            
84             =head2 -type (I|ipv6)
85            
86             The format of Ip-Number.
87            
88             =cut
89            
90             #-------------------------------------------------
91            
92            
93             =head1 METHODS
94            
95             Here come the methods that you can use with this Widget.
96            
97             =cut
98            
99            
100             #-------------------------------------------------
101            
102             #-------------------------------------------------
103             $specs{-variable} = [qw/METHOD variable Variable/, undef ];
104            
105             =head2 $IPEntry->I(\$ipnumber);
106            
107             Specifies the name of a variable. The value of the variable is a text string
108             to be displayed inside the widget; if the variable value changes then the widget
109             will automatically update itself to reflect the new value.
110             The way in which the string is displayed in the widget depends on the particular
111             widget and may be determined by other options, such as anchor or justify.
112            
113             =cut
114            
115             #-------------------------------------------------
116             $specs{-set} = [qw/METHOD set Set/, undef];
117            
118             =head2 $IPEntry->I($ipnumber);
119            
120             Set the IP number to display. You can use all standart format for IP-Adresses
121             in Version 4 and Version 6. Here comes some examples, please look also in perldoc
122             from Net::IP:
123            
124             A Net::IP object can be created from a single IP address:
125             $ip->set('193.0.1.46') || die ...
126            
127            
128             Or from a Classless Prefix (a /24 prefix is equivalent to a C class):
129             $ip->set('195.114.80/24') || die ...
130            
131             Or from a range of addresses:
132             $ip->set('20.34.101.207 - 201.3.9.99') || die ...
133            
134            
135             Or from a address plus a number:
136             $ip->set('20.34.10.0 + 255') || die ...
137            
138            
139             The set() function accepts IPv4 and IPv6 addresses
140             (it's necessary set -type option to 'ipv6'):
141             $ip->set('dead:beef::/32') || die ...
142            
143            
144             Very interesting feature, you can give Ip-Ranges and the user can only choice a
145             Ip-Adress in this Range. The other Numbers is disabled. I.E.:
146            
147             $ip->set('195.114.80/24') || die ...
148             $ip->set('dead:beef::/32') || die ...
149            
150            
151             =cut
152            
153             #-------------------------------------------------
154             $specs{-get} = [qw/METHOD get Get/, undef ];
155            
156             =head2 $IPEntry->I();
157            
158             Here you can get IP number from display. This is also a Interface to Net::IP,
159             in example you will get the binary code from displayed IP-Number then you can
160             call:
161            
162             $IPEntry->get('binip');
163            
164             Please look for all allow commands to Net::IP.
165            
166             =cut
167            
168             #-------------------------------------------------
169             $specs{-error} = [qw/METHOD error Error/, undef ];
170            
171             =head2 $IPEntry->I();
172            
173             This prints the last error.
174            
175             =cut
176            
177             # Ok, here the important structure from the widget ....
178             $obj->SUPER::Populate($args);
179            
180             $obj->ConfigSpecs(
181             -get => [qw/METHOD get Get/, undef ],
182             -error => [qw/METHOD error Error/, undef ],
183             %specs,
184             );
185            
186             # Widgets in the Megawidget
187             # Next, we need 4 NumEntrys(ipv4)
188             if(uc($obj->{type}) eq 'IPV4')
189             {
190             foreach my $n (0..3) {
191             $obj->{nummer}->[$n] = $obj->NumEntry(
192             -width => 3,
193             -minvalue => 0,
194             -maxvalue => 255,
195             -bell => 1,
196             )->pack(
197             -side => 'left'
198             );
199             # Bindings
200             $obj->{nummer}->[$n]->bind('', sub { $obj->fullip } );
201             $obj->{nummer}->[$n]->bind('
202             $obj->{nummer}->[$n]->bind('', sub { $obj->fullip } );
203             $obj->{nummer}->[$n]->bind('',sub { $obj->fullip } );
204             }
205             }
206             elsif(uc($obj->{type}) eq 'IPV6')
207             {
208             foreach my $n (0..7) {
209             $obj->{nummer}->[$n] = $obj->HexEntry(
210             -width => 4,
211             -minvalue => 0x0000,
212             -maxvalue => 0xFFFF,
213             -bell => 1,
214             )->pack(
215             -side => 'left'
216             );
217             }
218             }
219             $obj->clear;
220             }
221            
222             # ------------------------------------------
223             sub fullip {
224             # ------------------------------------------
225             my ($obj) = @_;
226             my $ok;
227             foreach my $v (@{$obj->{minivrefs}}) {
228             $ok = 1 if($v);
229             }
230            
231             if( $ok ) {
232             foreach my $v (@{$obj->{minivrefs}}) {
233             $v = 0 unless($v);
234             }
235             }
236            
237            
238             }
239            
240             # ------------------------------------------
241             sub clear {
242             # ------------------------------------------
243             my ($obj) = @_;
244             my $c = -1;
245             foreach my $w (@{$obj->{nummer}}) {
246             $c++;
247             $obj->{minivrefs}->[$c] = undef;
248             $obj->{nummer}->[$c]->configure(
249             -textvariable => \$obj->{minivrefs}->[$c]
250             );
251             $w->delete('0','end');
252             }
253             }
254            
255             # ------------------------------------------
256             sub set {
257             # ------------------------------------------
258             my ($obj, $adress) = @_;
259            
260             unless($adress) {
261             $obj->clear();
262             return;
263             }
264            
265             unless(defined $obj->{IP}) {
266             $obj->{IP} = Net::IP->new($adress)
267             || return $obj->error( Net::IP::Error() );
268             } else {
269             $obj->{IP}->set($adress)
270             || return $obj->error( $obj->{IP}->error() );
271             }
272            
273             my ($first_ip, $last_ip) = $obj->ip_to_range($adress);
274             # printf "First: %s, Last: %s\n",$first_ip, $last_ip;
275            
276             my $delm = (uc($obj->{type}) eq 'IPV4' ? '.' : ':');
277            
278             my @first = split( "\\$delm", $first_ip );
279             my @last = split( "\\$delm", $last_ip );
280            
281             my $c = -1;
282             foreach my $num ( split( "\\$delm", $obj->{IP}->ip ) ) {
283             $c++;
284             $obj->{minivrefs}->[$c] = $obj->check($num);
285             $obj->{nummer}->[$c]->configure(
286             -state => ( $first_ip ne $last_ip && $first[$c] eq $last[$c] ? 'disabled' : 'normal' ),
287             -minvalue => ( $first[$c] eq $last[$c] ? (uc($obj->{type}) eq 'IPV4' ? 0 : 0x0000) : (uc($obj->{type}) eq 'IPV4' ? $first[$c] : hex($first[$c])) ),
288             -maxvalue => ( $first[$c] eq $last[$c] ? (uc($obj->{type}) eq 'IPV4' ? 0xFF : 0xFFFF) : (uc($obj->{type}) eq 'IPV4' ? $last[$c] : hex($last[$c])) ),
289             -textvariable => \$obj->{minivrefs}->[$c]
290             );
291             }
292             }
293            
294             # ------------------------------------------
295             sub get {
296             # ------------------------------------------
297             my ($obj, $ip_common) = @_;
298             my ($addr);
299            
300             my $c = 0;
301             my $delm = (uc($obj->{type}) eq 'IPV4' ? '.' : ':');
302            
303             foreach my $num ( @{ $obj->{minivrefs} } ) {
304             next unless(defined $num);
305             $addr .= $delm if($c++);
306             $addr .= $obj->check($num);
307             }
308            
309             $obj->{IP}->set($addr)
310             || return $obj->error( $obj->{IP}->error() );
311            
312             if($ip_common) {
313             return $obj->{IP}->$ip_common()
314             || return $obj->error( $obj->{IP}->error() );
315             }
316            
317             return $addr;
318             }
319            
320             # ------------------------------------------
321             sub check {
322             # ------------------------------------------
323             my ($obj, $num) = @_;
324            
325             # Format
326             $num = substr(lc($num), 0, 4)
327             if(uc($obj->{type}) eq 'IPV6');
328            
329             # wrong?
330             if( uc($obj->{type}) eq 'IPV4' && ! $num ) {
331             return $num;
332             } elsif(uc($obj->{type}) eq 'IPV4' && (int($num) < 0 || int($num) > 255)) {
333             $obj->error("Number($num) incorrect in IpRange");
334             $num = ($num < 0 ? 0 : 255);
335             }
336             if(uc($obj->{type}) eq 'IPV6' && (! hex($num) && $num !~ /[0]+/)) {
337             $obj->error("Number($num) incorrect in IpRange");
338             $num = '0000';
339             }
340             return $num;
341             }
342            
343             # ------------------------------------------
344             sub variable {
345             # ------------------------------------------
346             my ($obj, $vref) = @_;
347            
348             $obj->{vref} = $vref
349             unless(defined $obj->{vref});
350            
351             my $st = [sub {
352             my ($watch, $new_val) = @_;
353             my $argv= $watch->Args('-store');
354             $argv->[0]->set($new_val);
355             $watch->Store($new_val);
356             }, $obj];
357            
358             my $fetch = [sub {
359             my($self, $new) = @_;
360             my $var = $self->Fetch;
361             my $getvar = $obj->get();
362             $self->Store($getvar)
363             if($getvar);
364             return ($getvar ? $getvar : $var);
365             }, $obj];
366            
367             $obj->{watch} = Tie::Watch->new(
368             -variable => $vref,
369             -store => $st,
370             -fetch => $fetch
371             );
372            
373             $obj->OnDestroy( [sub {$_[0]->{watch}->Unwatch}, $obj] );
374            
375             } # end variable
376            
377             # ------------------------------------------
378             sub ip_to_range {
379             # ------------------------------------------
380             my ($obj, $ip) = @_;
381            
382             my $addr = Net::IP->new($ip)
383             or return error("Cannot create IP object $_: ".Net::IP::Error());
384            
385             # printf ("%18s %15s - %-15s [%s]\n",$addr->print(),$addr->ip(),$addr->last_ip(), $addr->size());
386            
387             return ($addr->ip(),$addr->last_ip());
388             }
389            
390             # ------------------------------------------
391             sub error {
392             # ------------------------------------------
393             my $self = shift;
394             my ($package, $filename, $line, $subroutine, $hasargs,
395             $wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(1);
396             my $msg = shift || return undef;
397             warn sprintf("ERROR in %s:%s #%d: %s",
398             $package, $subroutine, $line, sprintf($msg, @_));
399             unless($msg) {
400             my $err = $self->{error};
401             $self->{error} = '';
402             return $err;
403             }
404             $self->{error} = $msg;
405             return undef;
406             }
407            
408            
409             1;
410             =head1 EXAMPLES
411            
412             Please see for examples in 'demos' directory in this distribution.
413            
414             =head1 AUTHOR
415            
416             xpix@netzwert.ag
417            
418             =head1 SEE ALSO
419            
420             Tk;
421             Tk::NumEntry;
422             Tie::Watch;
423             Net::IP;
424            
425             __END__