File Coverage

blib/lib/Filesys/SmbClientParser.pm
Criterion Covered Total %
statement 31 408 7.6
branch 12 340 3.5
condition 2 52 3.8
subroutine 4 37 10.8
pod 30 34 88.2
total 79 871 9.0


line stmt bran cond sub pod time code
1             package Filesys::SmbClientParser;
2              
3             # Module Filesys::SmbClientParser : provide function to reach
4             # Samba ressources
5             # Copyright 2000-2002 A.Barbet alian@alianwebserver.com. All rights reserved.
6              
7             # $Log: SmbClientParser.pm,v $
8             # Revision 2.7 2004/04/14 21:53:18 alian
9             # - fix rt#5896: Will Not work on shares that contain spaces in names
10             #
11             # Revision 2.6 2004/01/28 22:58:42 alian
12             # - Fix Auth that only allow \w in password
13             # - Fix mget & mput bug with ';' (reported by Nathan Vonnahme).
14             # - Fix bug if password contain & => quote password (reported by Gael LEPETIT).
15             # - Fix du and incorrect order at return time in array context (reported by
16             # rachinsky at vdesign.ru).
17             # - Fix dir method that didn't allow space in directory name => quote dir.
18             # (fixed by torstei at linpro.no).
19             # - Add test for Auth, mget, mput.
20             #
21             # Revision 2.5 2002/11/12 18:53:44 alian
22             # Update POD documentation
23             #
24             # Revision 2.4 2002/11/08 23:51:19 alian
25             # - Correct a bug that didn't set smbclient path when pass as arg of new.
26             # (thanks to Andreas Dahl for report and patch).
27             # - Correct a bug in error parsing that disable use of file or dir with
28             # ERR in his name. Eg: JERRY. (Thanks to Jason Sloderbeck for report).
29             #
30             # Revision 2.3 2002/08/13 13:44:00 alian
31             # - Update smbclient detection (scan path and try wich)
32             # - Update get, du method for perl -w mode
33             # - Update command method for perl -T mode
34             # - Update all exec command: add >&1 for Solaris output on STDERR
35             # - Add NT_STATUS_ message detection for error
36              
37 4     4   118984 use strict;
  4         12  
  4         190  
38 4     4   23 use vars qw($VERSION @ISA @EXPORT @EXPORT_OK);
  4         8  
  4         34366  
39              
40             require Exporter;
41              
42             @ISA = qw(Exporter);
43             @EXPORT = qw();
44             $VERSION = ('$Revision: 2.7 $ ' =~ /(\d+\.\d+)/)[0];
45              
46             #------------------------------------------------------------------------------
47             # new
48             #------------------------------------------------------------------------------
49             sub new
50             {
51 3     3 1 1297 my $class = shift;
52 3         10 my $self = {};
53 3         9 bless $self, $class;
54             sub search_it {
55 6     6 0 29 my $self = shift;
56 6         28 foreach my $p (@_) {
57 26 50       453 if (-x "$p/smbclient") {
58 0           $self->{SMBLIENT} = $p."/smbclient";
59 0           last;
60             }
61             }
62             }
63             # Search path of smbclient
64 3         8 my $pat = shift;
65 3         15 my @common = qw!/usr/bin /usr/local/bin /opt/bin /opt/local/bin
66             /usr/local/samba/bin /usr/pkg/bin!;
67 3 100 66     54 if (!$pat or !(-x $pat)) {
68             # Try common location
69 2         13 $self->search_it(@common);
70             # Try path
71 2 50       336 $self->search_it(split(/:/,$ENV{PATH})) if (!-x $self->{SMBLIENT});
72             # May be taint mode ...
73 2 50       12473 $self->search_it(split(/:/,`which smbclient`))
74             if (!-x $self->{SMBLIENT});
75 2 50       309 goto 'ERROR' if (!-x $self->{SMBLIENT});
76             }
77 1         24 else { $self->{SMBLIENT} = $pat;}
78             # fix others parameters
79 1         2 my %ref = @_;
80 1 50       5 $self->Host($ref{host}) if ($ref{host});
81 1 50       7 $self->User($ref{user}) if ($ref{user});
82 1 50       5 $self->Share($ref{share}) if ($ref{share});
83 1 50       4 $self->Password($ref{password}) if ($ref{password});
84 1 50       4 $self->Workgroup($ref{workgroup}) if ($ref{workgroup});
85 1 50       6 $self->IpAdress($ref{ipadress}) if ($ref{ipadress});
86 1         2 $self->{DIR}='/';
87 1         3 $self->{"DEBUG"} = 0;
88 1         5 return $self;
89 2         709 ERROR :
90             die "Can't found smbclient.\nUse new('/path/of/smbclient')";
91             }
92              
93             #------------------------------------------------------------------------------
94             # Fields methods
95             #------------------------------------------------------------------------------
96 0 0   0 1   sub Host {if ($_[1]) {$_[0]->{HOST}=$_[1];} return $_[0]->{HOST};}
  0            
  0            
97 0 0   0 1   sub User { if ($_[1]) { $_[0]->{USER}=$_[1];} return $_[0]->{USER};}
  0            
  0            
98 0 0   0 1   sub Share {if ($_[1]) {$_[0]->{SHARE}=$_[1];} return $_[0]->{SHARE};}
  0            
  0            
99 0 0   0 1   sub Password {if ($_[1]) {$_[0]->{PASSWORD}=$_[1];} return $_[0]->{PASSWORD};}
  0            
  0            
100 0 0   0 1   sub Workgroup {if ($_[1]) {$_[0]->{WG}=$_[1];} return $_[0]->{WG};}
  0            
  0            
101 0 0   0 1   sub IpAdress {if ($_[1]) {$_[0]->{IP}=$_[1];} return $_[0]->{IP};}
  0            
  0            
102             sub LastResponse {
103 0 0   0 1   if ($_[1]) {$_[0]->{LAST_REP}=$_[1];} return $_[0]->{LAST_REP};}
  0            
  0            
104             sub err {
105 0 0   0 1   if ($_[1]) {$_[0]->{LAST_ERR}=$_[1];} return $_[0]->{LAST_ERR};}
  0            
  0            
106              
107             #------------------------------------------------------------------------------
108             # Debug mode
109             #------------------------------------------------------------------------------
110             sub Debug
111             {
112 0     0 1   my ($self,$deb)=@_;
113 0 0         $self->{"DEBUG"} = $1 if ($deb =~ /^(\d+)$/);
114 0           return $self->{"DEBUG"};
115             }
116              
117             #------------------------------------------------------------------------------
118             # Auth
119             #------------------------------------------------------------------------------
120             sub Auth {
121 0     0 1   my ($self,$auth)=@_;
122 0 0         print "In auth with $auth\n" if ($self->{DEBUG});
123 0 0 0       if ($auth && -r $auth) {
124 0 0         open(AUTH, $auth) || die "Can't read $auth:$!\n";
125 0           while () {
126 0           chomp;
127 0 0         if ($_ =~ /^(\w+)\s*=\s*(.+)\s*$/) {
128 0           my ($key,$value) = ($1,$2);
129 0 0         if ($key =~ /^password$/i) {$_[0]->Password($value);}
  0 0          
  0            
130             elsif ($key =~ /^username$/i) {$_[0]->User($value);}
131             }
132             }
133 0           close(AUTH);
134 0           return 1;
135             }
136 0           return 0;
137             }
138              
139              
140             #------------------------------------------------------------------------------
141             # _List
142             #------------------------------------------------------------------------------
143             sub _List
144             {
145 0     0     my ($self, $host, $user, $pass, $wg, $ip) = @_;
146 0 0         if (!$host) {$host=$self->Host;} undef $self->{HOST};
  0            
  0            
147 0           my $tmp = $self->Share; undef $self->{SHARE};
  0            
148 0           my $commande = "-L '\\\\$host' ";
149 0 0         $self->SmbOption($commande, undef, undef, undef, $user, $pass, $wg, $ip)
150             || return undef;
151 0           $self->Host($host); $self->Share($tmp);
  0            
152 0           return $self->LastResponse;
153             }
154              
155             #------------------------------------------------------------------------------
156             # GetShr
157             #------------------------------------------------------------------------------
158             sub GetShr
159             {
160 0     0 1   my ($self, $host, $user, $pass, $wg, $ip) = @_;
161 0   0       my $out = _List(@_) || return undef;
162 0           my @out = @$out;
163 0           my @ret = ();
164 0           my $line = shift @out;
165 0   0       while ( (not $line =~ /^\s+Sharename/) and ($#out >= 0) )
  0            
166             {$line = shift @out;}
167 0 0         if ($#out >= 0)
168             {
169 0           $line = shift @out;
170 0           $line = shift @out;
171 0   0       while ( (not $line =~ /^$/) and ($#out >= 0) )
172             {
173 0 0         if ( $line =~ /^\s+([\S ]*\S)\s+(Disk)\s+([\S ]*)/ )
174             {
175 0           my $rec = {};
176 0           $rec->{name} = $1;
177 0           $rec->{type} = $2;
178 0           $rec->{comment} = $3;
179 0           push @ret, $rec;
180             }
181 0           $line = shift @out;
182             }
183             }
184 0           return sort byname @ret;
185             }
186              
187              
188             #------------------------------------------------------------------------------
189             # GetHosts
190             #------------------------------------------------------------------------------
191             sub GetHosts
192             {
193 0     0 1   my ($self,$host,$user,$pass,$wg,$ip) = @_;
194 0   0       my $out = _List(@_) || return undef;
195 0           my @out = @$out;
196 0           my @ret = ();
197 0           my $line = shift @out;
198              
199 0   0       while ((not $line =~ /Server\s*Comment/) and ($#out >= 0) )
  0            
200             {$line = shift @out;}
201 0 0         if ($#out >= 0)
202             {
203 0           $line = shift @out;$line = shift @out;
  0            
204 0   0       while ((not $line =~ /^$/) and ($#out >= 0))
205             {
206 0           chomp($line);
207 0 0         if ( $line =~ /^\t([\S ]*\S) {5,}(\S|.*)$/ )
208             {
209 0           my $rec = {};
210 0           $rec->{name} = $1;
211 0           $rec->{comment} = $2;
212 0           push @ret, $rec;
213             }
214 0           $line = shift @out;
215             }
216             }
217 0           return sort byname @ret;
218             }
219              
220             #------------------------------------------------------------------------------
221             # GetGroups
222             #------------------------------------------------------------------------------
223             sub GetGroups
224             {
225 0     0 1   my ($self,$host,$user,$pass,$wg,$ip) = @_;
226 0   0       my $out = _List(@_) || return undef;
227 0           my @ret = ();
228 0           my @out = @$out;
229 0           my $line = shift @out;
230 0   0       while ((not $line =~ /Workgroup/) and ($#out >= 0) )
  0            
231             {$line = shift @out;}
232 0 0         if ($#out >= 0)
233             {
234 0           $line = shift @out;
235 0   0       while ((not $line =~ /^$/) and ($#out >= 0) )
236             {
237 0           $line = shift @out;
238 0 0         if ( $line =~ /^\t([\S ]*\S) {2,}(\S[\S ]*)$/ )
239             {
240 0           my $rec = {};
241 0           $rec->{name} = $1;
242 0           $rec->{master} = $2;
243 0           push @ret, $rec;
244             }
245             }
246             }
247 0           return sort byname @ret;
248             }
249              
250             #------------------------------------------------------------------------------
251             # sendWinpopupMessage
252             #------------------------------------------------------------------------------
253             sub sendWinpopupMessage
254             {
255 0     0 1   my ($self, $dest, $text) = @_;
256 0           my $args = "/bin/echo \"$text\" | ".$self->{SMBLIENT}." -M $dest";
257 0           return $self->command($args,"winpopup message");
258             }
259              
260             #------------------------------------------------------------------------------
261             # cd
262             #------------------------------------------------------------------------------
263             sub cd
264             {
265 0     0 1   my $self = shift;
266 0           my $dir = shift;
267 0 0         if ($dir)
268 0           {
269 0           my $commande;
270 0 0         if ($dir ne ".."){$commande = "cd \"$dir\""; }
  0            
271 0           else { $commande = "cd .."; }
272 0 0         $self->SmbScript($commande, undef, @_) || return undef;
273 0 0         if ($dir=~/^\//) {$self->{DIR}=$dir;}
  0 0          
  0 0          
274             elsif ($dir=~/^..$/)
275 0 0         {if ($self->{DIR}=~/(.*\/)(.+?)$/) {$self->{DIR}=$1;}}
276 0           elsif($self->{DIR}=~/\/$/){ $self->{DIR}.=$dir; }
  0            
277             else{$self->{DIR}.='/'.$dir;}
278 0           return 1;
279             }
280             else {return $self->{DIR};}
281             }
282              
283             #------------------------------------------------------------------------------
284             # dir
285             #------------------------------------------------------------------------------
286             sub dir {
287 0     0 1   my $self = shift;
288 0           my $dir = shift;
289 0           my (@dir,@files);
290 0 0         $dir = $self->{DIR} unless $dir;
291 0           my $cmd = "ls \"$dir/*\"";
292 0 0         $self->SmbScript($cmd,undef,@_) || return undef;
293 0           my $out = $self->LastResponse;
294 0           foreach my $line ( @$out ) {
295 0 0         if ($line=~/^ ([\S ]*\S|[\.]+) {5,}([HDRSA]+) +([0-9]+) (\S[\S ]+\S)$/g){
    0          
296 0           my $rec = {};
297 0           $rec->{name} = $1;
298 0           $rec->{attr} = $2;
299 0           $rec->{size} = $3;
300 0           $rec->{date} = $4;
301 0 0         if ($rec->{attr} =~ /D/) {push @dir, $rec;}
  0            
  0            
302             else {push @files, $rec;}
303             }
304             elsif ($line =~ /^ ([\S ]*\S|[\.]+) {6,}([0-9]+) (\S[\S ]+\S)$/) {
305 0           my $rec = {};
306 0           $rec->{name} = $1;
307 0           $rec->{attr} = "";
308 0           $rec->{size} = $2;
309 0           $rec->{date} = $3;
310 0           push @files, $rec; # No attributes at all, so it must be a file
311             }
312             }
313 0           return (sort byname @dir, sort byname @files);
314             }
315              
316             #------------------------------------------------------------------------------
317             # mkdir
318             #------------------------------------------------------------------------------
319             sub mkdir
320             {
321 0     0 1   my $self = shift;
322 0           my $masq = shift;
323 0           my $commande = "mkdir $masq";
324 0           return $self->SmbScript($commande,@_);
325             }
326              
327             #------------------------------------------------------------------------------
328             # get
329             #------------------------------------------------------------------------------
330             sub get {
331 0     0 1   my $self = shift;
332 0           my $file = shift;
333 0           my $target = shift;
334 0           $file =~ s/^(.*)\/([^\/]*)$/$1$2/ ;
335 0           my $commande = "get \"$file\" ";
336 0 0         $commande.=$target if ($target);
337 0           return $self->SmbScript($commande,@_);
338             }
339              
340             #------------------------------------------------------------------------------
341             # mget
342             #------------------------------------------------------------------------------
343             sub mget
344             {
345 0     0 1   my $self = shift;
346 0           my $file = shift;
347 0           my $recurse = shift;
348 0 0         $file = ref($file) eq 'ARRAY' ? join (' ',@$file) : $file;
349 0 0         $recurse = $recurse ? 'recurse;' : " " ;
350 0           my $commande = "prompt off; $recurse mget $file";
351 0           return $self->SmbScript($commande,@_);
352             }
353              
354             #------------------------------------------------------------------------------
355             # put
356             #------------------------------------------------------------------------------
357             sub put
358             {
359 0     0 1   my $self = shift;
360 0           my $orig = shift;
361 0   0       my $file = shift || $orig;
362 0           $file =~ s/^(.*)\/([^\/]*)$/$1$2/ ;
363 0           my $commande = "put \"$orig\" \"$file\"";
364 0           return $self->SmbScript($commande,@_);
365             }
366              
367              
368             #------------------------------------------------------------------------------
369             # mput
370             #------------------------------------------------------------------------------
371             sub mput
372             {
373 0     0 1   my $self = shift;
374 0           my $file = shift;
375 0           my $recurse = shift;
376 0 0         $file = ref($file) eq 'ARRAY' ? join (' ',@$file) : $file;
377 0 0         $recurse = $recurse ? 'recurse;' : " " ;
378 0           my $commande = "prompt off; $recurse mput $file";
379 0           return $self->SmbScript($commande,@_);
380             }
381              
382             #------------------------------------------------------------------------------
383             # del
384             #------------------------------------------------------------------------------
385             sub del
386             {
387 0     0 1   my $self = shift;
388 0           my $masq = shift;
389 0           my $commande = "del $masq";
390 0           return $self->SmbScript($commande,@_);
391             }
392              
393             #------------------------------------------------------------------------------
394             # rmdir
395             #------------------------------------------------------------------------------
396             sub rmdir
397             {
398 0     0 1   my $self = shift;
399 0           my $masq = shift;
400 0           my $commande = "rmdir $masq";
401 0           return $self->SmbScript($commande,@_);
402             }
403              
404             #------------------------------------------------------------------------------
405             # rename
406             #------------------------------------------------------------------------------
407             sub rename
408             {
409 0     0 1   my $self = shift;
410 0           my $source = shift;
411 0           my $target = shift;
412 0           my $command = "rename $source $target";
413 0           return $self->SmbScript($command,@_);
414             }
415              
416             #------------------------------------------------------------------------------
417             # pwd
418             #------------------------------------------------------------------------------
419             sub pwd
420             {
421 0     0 1   my $self = shift;
422 0           my $command = "pwd";
423 0 0         if ($self->SmbScript($command,@_))
424             {
425 0           my $out = $self->LastResponse;
426 0           foreach ( @$out )
427             {
428 0 0         if ($_ =~m !^\s*Current directory is \\\\[^\\]*(\\.*)$!)
  0            
429             {return $1; }
430             }
431             }
432 0           return undef;
433             }
434              
435             #------------------------------------------------------------------------------
436             # du
437             #------------------------------------------------------------------------------
438             sub du {
439 0     0 1   my $self = shift;
440 0           my $dir = shift;
441 0   0       my $blk = shift || 'k';
442 0           my $blksize;
443 0 0 0       if ($blk !~ /\D/ && $blk > 0) {
    0          
444 0           $blksize = $blk;
445             }
446             elsif ($blk =~ /^([kbsmg])/i) {
447 0 0         $blksize = 512 if ($blk =~ /b/i); ## Posix blocks
448 0 0         $blksize = 1024 if ($blk =~ /k/i); ## 1Kbyte blocks
449 0 0         $blksize = 1024*512 if ($blk =~ /s/i); ## Samba blocks
450 0 0         $blksize = 1024*1024 if ($blk =~ /m/i); ## 1Mbyte blocks
451 0 0         $blksize = 1024*1024*1024 if ($blk =~ /g/i); ## 1Gbyte blocks
452             } else {
453 0           die "Invalid argument for blocksize: $blk\n";
454             }
455 0   0       $blksize ||= 1024; ## Default to 1Kbyte blocks
456              
457 0 0         $dir =~ s#(.*)(^|/)\.(/|$)(.*)#$1$2$4#g if ($dir);
458 0 0         $dir = $self->{DIR} unless ($dir);
459              
460 0           my $cmd = "du $dir/*";
461 0 0         $self->SmbScript($cmd,undef,@_) || return undef;
462 0           my $out = $self->LastResponse;
463 0           my $rec = {};
464 0           foreach my $line ( @$out ) {
465 0 0         if ($line =~ /^\s*(\d+)\D+(\d+)\D+(\d+)\D+$/) {
466 0 0         my $blksz = (defined $2) ? $2 : 512 * 1024;
467 0           $rec->{ublks} = $1 * ($blksz / $blksize);
468 0           $rec->{fblks} = $3 * ($blksz / $blksize);
469 0           $rec->{blksz} = $blksize;
470             }
471 0 0         if ($line =~ /^\D+:\s+(\d+)\s*$/) {
472 0           $rec->{usage} = $1 / $blksize;
473             }
474             }
475              
476 0 0         return (wantarray() ? ($rec->{usage},
477             $rec->{fblks},
478             $rec->{blksz},
479             $rec->{ublks}) : $rec->{usage} );
480             }
481              
482             #------------------------------------------------------------------------------
483             # tar
484             #------------------------------------------------------------------------------
485             sub tar
486             {
487 0     0 1   my $self = shift;
488 0           my $command = shift;
489 0           my $target = shift;
490 0   0       my $dir = shift || $self->{DIR};
491 0           $self->{DIR}=undef;
492 0           my $cmd = " -T$command $target $dir";
493 0           $self->{DIR}=$dir;
494 0           return $self->SmbOption($cmd,undef,@_);
495             }
496              
497             #------------------------------------------------------------------------------
498             # rearrange_param
499             #------------------------------------------------------------------------------
500             sub rearrange_param {
501 0     0 0   my ($self,$command,$dir, $host, $share, $user, $pass, $wg, $ip) = @_;
502 0 0         if (!$user) {$user=$self->User;}
  0            
503 0 0         if (!$host) {$host=$self->Host;}
  0            
504 0 0         if (!$share){$share=$self->Share;}
  0            
505 0 0         if (!$pass) {$pass=$self->Password;}
  0            
506 0 0         if (!$wg) {$wg=$self->Workgroup; }
  0            
507 0 0         if (!$ip) {$ip =$self->IpAdress; }
  0            
508 0 0         if (!$dir) {$dir=$self->{DIR}; }
  0            
509 0 0         my $debug = ($self->{DEBUG} ? " -d".$self->{DEBUG} : ' -d0 ');
510 0 0         $wg = ($wg ? ("-W ".$wg." ") : ' '); # Workgroup
511 0 0         $ip = ($ip ? ("-I ".$ip." ") : ' '); # Ip adress of server
512 0 0         $dir = ($dir ? (' -D "'.$dir.'"') : ' '); # Path
513             # User / Password
514 0 0 0       if (($user)&&($pass)) { $user = '-U "'.$user.'%'.$pass.'" '; }
  0 0 0        
  0            
515             # Don't prompt for password
516             elsif ($user && !$pass) {$user = '-U '.$user.' -N ';}
517             # Server/share
518 0           my $path=' "';
519 0 0         if ($host) {$host='//'.$host; $path.=$host; }
  0            
  0            
520 0 0         if ($share) {$share='/'.$share;$path.=$share; }
  0            
  0            
521 0           $path.='" ';
522 0           my $prefix = $self->{SMBLIENT}.$path.$user.$wg.$ip.$debug;
523 0           return ($self, $command, $prefix, $dir);
524             }
525              
526             #------------------------------------------------------------------------------
527             # SmbScript
528             #------------------------------------------------------------------------------
529             sub SmbScript {
530 0     0 0   my ($self,$command,$prefix,$dir) = rearrange_param(@_);
531             # Final command
532 0           my $args = $prefix." -c '$command' ".$dir;
533 0           return $self->command($args,$command,1);
534             }
535              
536             #------------------------------------------------------------------------------
537             # SmbOption
538             #------------------------------------------------------------------------------
539             sub SmbOption {
540 0     0 0   my ($self,$command,$prefix,$dir) = rearrange_param(@_);
541             # Final command
542 0           my $args = $prefix.$command.$dir;
543 0           return $self->command($args,$command);
544             }
545              
546             #------------------------------------------------------------------------------
547             # byname
548             #------------------------------------------------------------------------------
549 0     0 1   sub byname {(lc $a->{name}) cmp (lc $b->{name})}
550              
551             #------------------------------------------------------------------------------
552             # command
553             #------------------------------------------------------------------------------
554             sub command {
555 0     0 1   my ($self,$args,$command, $smbscript)=@_;
556 0           $command.=" >&1";
557 0 0         print " ==> SmbClientParser::command $args\n"
558             if ($self->{"DEBUG"} > 0);
559 0           my $er;
560              
561             # for -T
562             my $pargs;
563 0 0         if ($args=~/^([^;]*)$/) { # no ';' nickel
    0          
564 0           $pargs=$1;
565             } elsif ($smbscript) { # ';' is allowed inside -c ' '
566 0 0         if ($args=~/^([^;]* -c '[^']*'[^;]*)$/) {
567 0           $pargs=$1;
568             } else { # what that ?
569 0           die("Why a ';' here ? => $args");
570             }
571 0           } else { die("Why a ';' here ? => $args"); }
572              
573 0           my @var = `$pargs`;
574 0           my $var=join(' ',@var ) ;
575              
576             # Quick return if no answer
577 0 0         return 1 if (!$var);
578 0 0 0       if ($var=~/ERRnoaccess/) {
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
    0          
579 0           $er="Cmd $command: permission denied";
580             } elsif ($var=~/ERRbadfunc/) {
581 0           $er="Cmd $command: Invalid function.";
582             } elsif ($var=~/ERRbadfile/) {
583 0           $er="Cmd $command: File not found.";
584             } elsif ($var=~/ERRbadpath/) {
585 0           $er="Cmd $command: Directory invalid.";
586             } elsif ($var=~/ERRnofids/) {
587 0           $er="Cmd $command: No file descriptors available";
588             } elsif ($var=~/ERRnoaccess/) {
589 0           $er="Cmd $command: Access denied.";
590             } elsif ($var=~/ERRbadfid/) {
591 0           $er="Cmd $command: Invalid file handle.";
592             } elsif ($var=~/ERRbadmcb/) {
593 0           $er="Cmd $command: Memory control blocks destroyed.";
594             } elsif ($var=~/ERRnomem/) {
595 0           $er="Cmd $command: Insufficient server memory to perform the requested function.";
596             } elsif ($var=~/ERRbadmem/) {
597 0           $er="Cmd $command: Invalid memory block address.";
598             } elsif ($var=~/ERRbadenv/) {
599 0           $er="Cmd $command: Invalid environment.";
600             } elsif ($var=~/ERRbadformat/) {
601 0           $er="Cmd $command: Invalid format.";
602             } elsif ($var=~/ERRbadaccess/) {
603 0           $er="Cmd $command: Invalid open mode.";
604 0           } elsif ($var=~/ERRbaddata/) {
605 0           $er="Cmd $command: Invalid data.";
606             } elsif ($var=~/ERRbaddrive/)
607 0           {$er="Cmd $command: Invalid drive specified.";}
608             elsif ($var=~/ERRremcd/)
609 0           {$er="Cmd $command: A Delete Directory request attempted to remove the server's current directory.";}
610             elsif ($var=~/ERRdiffdevice/)
611 0           {$er="Cmd $command: Not same device.";}
612             elsif ($var=~/ERRnofiles/)
613 0           {$er="Cmd $command: A File Search command can find no more files matching the specified criteria.";}
614             elsif ($var=~/ERRbadshare/)
615 0           {$er="Cmd $command: The sharing mode specified for an Open conflicts with existing FIDs on the file.";}
616             elsif ($var=~/ERRlock/)
617 0           {$er="Cmd $command: A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.";}
618             elsif ($var=~/ERRunsup/)
619 0           {$er="Cmd $command: The operation is unsupported";}
620             elsif ($var=~/ERRnosuchshare/)
621 0           {$er="Cmd $command: You specified an invalid share name";}
622             elsif ($var=~/ERRfilexists/)
623 0           {$er="Error $command: The file named in a Create Directory, Make New File or Link request already exists.";}
624             elsif ($var=~/ERRbadpipe/)
625 0           {$er="Cmd $command: Pipe invalid.";}
626             elsif ($var=~/ERRpipebusy/)
627 0           {$er="Cmd $command: All instances of the requested pipe are busy.";}
628             elsif ($var=~/ERRpipeclosing/)
629 0           {$er="Cmd $command: Pipe close in progress.";}
630             elsif ($var=~/ERRnotconnected/)
631 0           {$er="Cmd $command: No process on other end of pipe.";}
632             elsif ($var=~/ERRmoredata/)
633 0           {$er="Cmd $command: There is more data to be returned.";}
634             elsif ($var=~/ERRinvgroup/)
635 0           {$er="Cmd $command: Invalid workgroup (try the -W option)";}
636             elsif ($var=~/ERRerror/)
637 0           {$er="Cmd $command: Non-specific error code.";}
638             elsif ($var=~/ERRbadpw/)
639 0           {$er="Cmd $command: Bad password - name/password pair in a Tree Connect or Session Setup are invalid.";}
640             elsif ($var=~/ERRbadtype/)
641 0           {$er="Cmd $command: reserved.";}
642             elsif ($var=~/ERRaccess/)
643 0           {$er="Cmd $command: The requester does not have the necessary access rights within the specified context for the requested function. The context is defined by the TID or the UID.";}
644             elsif ($var=~/ERRinvnid/)
645 0           {$er="Cmd $command: The tree ID (TID) specified in a command was invalid.";}
646             elsif ($var=~/ERRinvnetname/)
647 0           {$er="Cmd $command: Invalid network name in tree connect.";}
648             elsif ($var=~/ERRinvdevice/)
649 0           {$er="Cmd $command: Invalid device - printer request made to non-printer connection or non-printer request made to printer connection.";}
650             elsif ($var=~/ERRqfull/)
651 0           {$er="Cmd $command: Print queue full (files) -- returned by open print file.";}
652             elsif ($var=~/ERRqtoobig/)
653 0           {$er="Cmd $command: Print queue full -- no space.";}
654             elsif ($var=~/ERRqeof/)
655 0           {$er="Cmd $command: EOF on print queue dump.";}
656             elsif ($var=~/ERRinvpfid/)
657 0           {$er="Cmd $command: Invalid print file FID.";}
658             elsif ($var=~/ERRsmbcmd/)
659 0           {$er="Cmd $command: The server did not recognize the command received.";}
660             elsif ($var=~/ERRsrverror/)
661 0           {$er="Cmd $command: The server encountered an internal error, e.g., system file unavailable.";}
662             elsif ($var=~/ERRfilespecs/)
663 0           {$er="Cmd $command: The file handle (FID) and pathname parameters contained an invalid combination of values.";}
664             elsif ($var=~/ERRreserved/)
665 0           {$er="Cmd $command: reserved.";}
666             elsif ($var=~/ERRbadpermits/)
667 0           {$er="Cmd $command: The access permissions specified for a file or directory are not a valid combination. The server cannot set the requested attribute.";}
668             elsif ($var=~/ERRreserved/)
669 0           {$er="Cmd $command: reserved.";}
670             elsif ($var=~/ERRsetattrmode/)
671 0           {$er="Cmd $command: The attribute mode in the Set File Attribute request is invalid.";}
672             elsif ($var=~/ERRpaused/)
673 0           {$er="Cmd $command: Server is paused.";}
674             elsif ($var=~/ERRmsgoff/)
675 0           {$er="Cmd $command: Not receiving messages.";}
676             elsif ($var=~/ERRnoroom/)
677 0           {$er="Cmd $command: No room to buffer message.";}
678             elsif ($var=~/ERRrmuns/)
679 0           {$er="Cmd $command: Too many remote user names.";}
680             elsif ($var=~/ERRtimeout/)
681             {$er="Cmd $command: Operation timed out.";}
682             elsif ($var=~/ERRnoresource/)
683 0           { $er="Cmd $command: No resources currently available for request.";}
  0            
684             elsif ($var=~/ERRtoomanyuids/)
685             {$er="Cmd $command: Too many UIDs active on this session.";}
686             elsif ($var=~/ERRbaduid/)
687 0           {
688 0           $er="Cmd $command: The UID is not known as a valid ID on this session.";
689             }
690             elsif ($var=~/ERRusempx/)
691 0           {$er="Cmd $command: Temp unable to support Raw, use MPX mode."; }
692             elsif ($var=~/ERRusestd/)
693 0           {$er="Cmd $command: Temp unable to support Raw, use standard read/write.";}
694             elsif ($var=~/ERRcontmpx/)
695 0           {$er="Cmd $command: Continue in MPX mode.";}
696             elsif ($var=~/ERRreserved/)
697 0           {$er="Cmd $command: reserved.";}
698             elsif ($var=~/ERRreserved/)
699 0           {$er="Cmd $command: reserved.";}
700             elsif ($var=~/ERRnosupport/)
701 0           {print "Function not supported.";}
702             elsif ($var=~/ERRnowrite/)
703 0           {$er="Cmd $command: Attempt to write on write-protected diskette.";}
704             elsif ($var=~/ERRbadunit/)
705 0           {$er="Cmd $command: Unknown unit.";}
706             elsif ($var=~/ERRnotready/)
707 0           {$er="Cmd $command: Drive not ready.";}
708             elsif ($var=~/ERRbadcmd/)
709 0           {$er="Cmd $command: Unknown command.";}
710             elsif ($var=~/ERRdata/)
711 0           {$er="Cmd $command: Data error (CRC).";}
712             elsif ($var=~/ERRbadreq/)
713 0           {$er="Cmd $command: Bad request structure length.";}
714             elsif ($var=~/ERRseek/)
715 0           {$er="Cmd $command: Seek error.";}
716             elsif ($var=~/ERRbadmedia/)
717 0           {$er="Cmd $command: Unknown media type.";}
718             elsif ($var=~/ERRbadsector/)
719 0           {$er="Cmd $command: Sector not found.";}
720             elsif ($var=~/ERRnopaper/)
721 0           {$er="Cmd $command: Printer out of paper.";}
722             elsif ($var=~/ERRwrite/)
723 0           {$er="Cmd $command: Write fault.";}
724             elsif ($var=~/ERRread/)
725 0           {$er="Cmd $command: Read fault.";}
726             elsif ($var=~/ERRgeneral/)
727 0           {$er="Cmd $command: General failure.";}
728             elsif ($var=~/ERRbadshare/)
729 0           {$er="Cmd $command: An open conflicts with an existing open.";}
730             elsif ($var=~/ERRlock/)
731 0           {$er="Cmd $command: A Lock request conflicted with an existing lock or specified an invalid mode, or an Unlock requested attempted to remove a lock held by another process.";}
732             elsif ($var=~/ERRwrongdisk/)
733 0           {$er="Cmd $command: The wrong disk was found in a drive.";}
734             elsif ($var=~/ERRFCBUnavail/)
735 0           {$er="Cmd $command: No FCBs are available to process request.";}
736             elsif ($var=~/ERRsharebufexc/)
737 0           {$er="Cmd $command: A sharing buffer has been exceeded.";}
738             elsif ($var=~/ERRDOS - 183 renaming files/)
739             {$er="Cmd $command: File target already exist.";}
740             # elsif ($var=~/ERR/) {$er="Cmd $command: reserved.";}
741             elsif ($var=~/(NT_STATUS_[^ \n]*)/ && $1 ne 'NT_STATUS_OK') {
742 0           $er = $1; }
743 0           $self->{LAST_REP} = \@var;
744 0 0         $self->{LAST_ERR} = $er if ($er);
745 0 0         return (defined($er) ? undef : 1);
746             }
747              
748             #------------------------------------------------------------------------------
749             # POD DOCUMENTATION
750             #------------------------------------------------------------------------------
751              
752             =head1 NAME
753              
754             Filesys::SmbClientParser - Perl client to reach Samba ressources with smbclient
755              
756             =head1 SYNOPSIS
757              
758             use Filesys::SmbClientParser;
759             my $smb = new Filesys::SmbClientParser
760             (undef,
761             (
762             user => 'Administrateur',
763             password => 'password'
764             ));
765             # Or like -A parameters:
766             $smb->Auth("/home/alian/.smbpasswd");
767            
768             # Set host
769             $smb->Host('jupiter');
770            
771             # List host available on this network machine
772             my @l = $smb->GetHosts;
773             foreach (@l) {print $_->{name},"\t",$_->{comment},"\n";}
774            
775             # List share disk available
776             my @l = $smb->GetShr;
777             foreach (@l) {print $_->{name},"\n";}
778            
779             # Choose a shared disk
780             $smb->Share('games2');
781            
782             # List content
783             my @l = $smb->dir;
784             foreach (@l) {print $_->{name},"\n";}
785            
786             # Send a Winpopup message
787             $smb->sendWinpopupMessage('jupiter',"Hello world !");
788            
789             # File manipulation
790             $smb->cd('jdk1.1.8');
791             $smb->get("COPYRIGHT");
792             $smb->mkdir('tata');
793             $smb->cd('tata');
794             $smb->put("COPYRIGHT");
795             $smb->del("COPYRIGHT");
796             $smb->cd('..');
797             $smb->rmdir('tata');
798            
799             # Archive method
800             $smb->tar('c','/tmp/jdk.tar');
801             $smb->cd('..');
802             $smb->mkdir('tatz');
803             $smb->cd('tatz');
804             $smb->tar('x','/tmp/jdk.tar');
805              
806              
807             See test.pl file for others examples.
808              
809             =head1 DESCRIPTION
810              
811             SmbClientParser work with output of bin smbclient, so it doesn't work
812             on win platform. (but query of win platform work of course)
813              
814             A best method is work with a samba shared librarie and xs language,
815             but on Nov.2000 (Samba version prior to 2.0.8) there is no public
816             interface and shared library defined in Samba projet.
817              
818             Request has been submit and accepted on Samba-technical mailing list,
819             so I've build another module called Filesys-SmbClient that use features
820             of this library. (libsmbclient.so)
821              
822             For Samba client prior to 2.0.8, use this module !
823              
824             SmbClientParser is adapted from SMB.pm make by Remco van Mook
825             mook@cs.utwente.nl on smb2www project.
826              
827             =head1 INTERFACE
828              
829             =head2 Objects methods
830              
831             =over
832              
833             =item new [PATH_OF_SMBCLIENT], [HASH_OF_PARAM]
834              
835             Create a new FileSys::SmbClientParser instance. Search bin smbclient,
836             and fail if it can't find it in standard location.
837             (ENV{PATH}, /usr/bin, /usr/local/bin, /opt/bin or /usr/local/samba/bin/).
838             If it's on another directory, use parameter PATH_OF_SMBCLIENT.
839              
840             HASH_OF_PARAM is a hash with key user,host,password,workgroup,ipadress,share
841              
842             =item Host [HOSTNAME]
843              
844             Get or set the remote host to be used to HOSTNAME.
845              
846             =item User [USERNAME]
847              
848             Get or set the username to be used to USERNAME.
849              
850             =item Share [SHARENAME]
851              
852             Get or set the share to be used on the remote host to SHARENAME.
853              
854             =item Password [PASSWORD]
855              
856             Get or set the password to be used to PASSWORD.
857              
858             =item Workgroup [WORKGROUP]
859              
860             Get or set the workgroup to be used to WORKGROUP.
861             See -W switch in smbclient man page.
862              
863             =item IpAdress [IP]
864              
865             Set or get the IP adress of the server to contact to IP
866             See -I switch in smbclient man page.
867              
868             =item Debug [LEVEL]
869              
870             Set or get the debug verbosity
871              
872             0 = no output
873             1+ = more output
874              
875             =item Auth AUTH_FILE
876              
877             Use the file AUTH_FILE for username and password.
878             This uses User and Password instead of -A to be backwards
879             compatible. Return 1 if AUTH_FILE can be read, 0 else.
880              
881             =back
882              
883             =head2 Network methods
884              
885             =over
886              
887             =item GetGroups [HOSTNAME, USER, PASSWORD, WORKGROUP, IP]
888              
889             If no parameters is given, field will be used.
890              
891             Return an array with sorted workgroup listing that contains hashes;
892             keys: name, master
893              
894             =item GetShr [HOSTNAME, USER, PASSWORD, WORKGROUP, IP]
895              
896             If no parameters is given, field will be used.
897              
898             Return an array with sorted share listing, that contains hashes;
899             keys: name, type, comment
900              
901             =item GetHosts [HOSTNAME, USER, PASSWORD, WORKGROUP, IP]
902              
903             Return an array with sorted host listing, that contains hashes;
904             keys: name, comment
905              
906             =item sendWinpopupMessage DEST, TEXT
907              
908             This method allows you to send messages, using the "WinPopup" protocol,
909             to another computer. If the receiving computer is running WinPopup the
910             user will receive the message and probably a beep. If they are not
911             running WinPopup the message will be lost, and no error message will occur.
912              
913             The message is also automatically truncated if the message is over
914             1600 bytes, as this is the limit of the protocol.
915              
916             Parameters :
917              
918             DEST: name of host or user to send message
919             TEXT: text to send
920              
921             =back
922              
923             =head2 Operations
924              
925             =over
926              
927             =item cd [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
928              
929             If DIR is specified, the current working directory on the server
930             will be changed to the directory specified. This operation will fail if for
931             any reason the specified directory is inaccessible. Return list.
932              
933             If no directory name is specified, the current working directory on the server
934             will be reported.
935              
936             =item dir [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
937              
938             Return an array with sorted dir and filelisting that contains hashes;
939             keys: name, attr, size, date
940              
941             =item mkdir NAME, [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
942              
943             Create a new directory on the server with the specified name NAME
944              
945             =item rmdir NAME, [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
946              
947             Remove the specified directory NAME from the server. NAME can be a pattern.
948              
949             =item get FILE, [TARGET, DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
950              
951             Gets the file FILE from the server to the local machine, using USER and
952             PASSWORD, to TARGET on current SMB server and return the error code.
953              
954             If TARGET is unspecified, current directory will be used.
955             If specified, name the local copy TARGET.
956             For use STDOUT, set target to '-'.
957              
958             =item del FILE, [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
959              
960             The client will request that the server attempt to delete
961             all files matching FILE from the current working directory
962             on the server
963              
964             =item rename SOURCE, TARGET, [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
965              
966             The file matched by mask SOURCE will be moved to TARGET. These names
967             can be in different directories. It returns a return value.
968              
969             =item pwd
970              
971             Returns the present working directory on the remote system. If
972             there is an error it returns undef. If you are on smb://jupiter/doc/mysql/,
973             pwd return \doc\mysql\.
974              
975             =item du [DIR, UNIT]
976              
977             If no path is given current directory is used.
978              
979             UNIT can be in [kbsmg].
980              
981             =over
982              
983             =item b
984              
985             Posix blocks
986              
987             =item k
988              
989             1Kbyte blocks
990              
991             =item s
992              
993             Samba blocks
994              
995             =item m
996              
997             1Mbyte blocks
998              
999             =item g
1000              
1001             1Gbyte blocks
1002              
1003             =back
1004              
1005             If no unit given, k is used (1kb bloc)
1006              
1007             In scalar context, return the total size in units for files in
1008             current directory.
1009              
1010             In array context, return a list with total size in units for files in
1011             directory, size left in partition of share, block size used in bytes,
1012             total size of partition of share.
1013              
1014             =item mget FILE, [RECURSE]
1015              
1016             Gets file(s) FILE on current SMB server,directory and return
1017             the error code. If multiple file, push an array ref as first parameter
1018             or pattern * or file separated by space
1019              
1020             Syntax:
1021              
1022             $smb->mget ('file'); #or
1023             $smb->mget (join(' ',@file); #or
1024             $smb->mget (\@file); #or
1025             $smb->mget ("*",1);
1026              
1027             =item put ORIG,[FILE, DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP]
1028              
1029             Puts the file $orig to $file, using USER and PASSWORD on courant SMB
1030             server and return the error code. If no $file specified, use same
1031             name on local filesystem.
1032             If $orig is unspecified, STDIN is used (-).
1033              
1034             =item mput FILE, [RECURSE]
1035              
1036             Puts file(s) $file on current SMB server,directory and return
1037             the error code. If multiple file, push an array ref as first parameter
1038             or pattern * or file separated by space
1039              
1040             Syntax:
1041              
1042             $smb->mput ('file'); #or
1043             $smb->mput (join(' ',@file); #or
1044             $smb->mput (\@file); #or
1045             $smb->mput ("*",1);
1046              
1047             =back
1048              
1049             =head2 Archives methods
1050              
1051             =over
1052              
1053             =item tar($command, $target, [DIR, HOSTNAME ,USER, PASSWORD, WORKGROUP, IP])
1054              
1055             Execute TAR commande on //HOSTNAME/$share/DIR, using USER and PASSWORD
1056             and return the error code. $target is name of tar file that will be used
1057              
1058             Syntax: $smb->tar ($command,'/tmp/myar.tar') where command is in ('x','c',...).
1059             See smbclient man page for more details.
1060              
1061             =back
1062              
1063             =head2 Error methods
1064              
1065             All methods return undef on error and set err in $smb->err.
1066              
1067             =over
1068              
1069             =item err
1070              
1071             Return last text error that smbclient found
1072              
1073             =item LastResponse
1074              
1075             Return last buffer return by smbclient
1076              
1077             =back
1078              
1079             =head2 Private methods
1080              
1081             =over
1082              
1083             =item byname
1084              
1085             sort an array of hashes by $_->{name} (for GetSMBDir et al)
1086              
1087             =item command($args,$command)
1088              
1089             =back
1090              
1091             =head1 VERSION
1092              
1093             $Revision: 2.7 $
1094              
1095             =head1 TODO
1096              
1097             Write a wrapper for ActiveState release on win32
1098              
1099             Correct this documentation with a good english ...
1100              
1101             =head1 AUTHOR
1102              
1103             Alain BARBET alian@alianwebserver.com
1104              
1105             =head1 SEE ALSO
1106              
1107             smbclient(1) man pages.
1108              
1109             =cut