"Fossies" - the Fresh Open Source Software Archive 
Member "HTTP-DAV-0.49/bin/dave" (28 Nov 2018, 27853 Bytes) of package /linux/www/HTTP-DAV-0.49.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Perl source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
See also the latest
Fossies "Diffs" side-by-side code changes report for "dave":
0.48_vs_0.49.
1 #!/usr/bin/perl
2
3 =pod
4
5 =head1 NAME
6
7 dave - DAV Explorer
8
9 =head1 SYNOPSIS
10
11 dave [OPTIONS] URL
12
13 E.g.
14
15 $ dave -u pcollins -p mypass www.host.org/dav_dir/
16 ...
17 dave> get file.txt
18
19 Use C<dave -h> to get help on options.
20
21 Use C<perldoc dave> for the whole manpage.
22
23 =cut
24
25 use strict;
26 use vars '$AUTOLOAD';
27
28 use AutoLoader;
29 use Cwd;
30 use Getopt::Long;
31 use HTTP::DAV;
32 use Pod::Usage;
33 use Term::ReadLine;
34 use Text::ParseWords;
35 use Time::Local;
36 use URI::file;
37
38 my $VERSION = "2.01";
39 my $TMP_DIR = "/tmp";
40 my $LOCK_OWNER = "dave/v$VERSION (pid $$)";
41 my $USER_AGENT = "dave/v$VERSION (perldav)";
42
43 ## Setup/parse options
44 ## Parse options and print usage if there is a syntax error.
45 ## Note pod2usage comes from Pod::Usage
46 my $opt_h=0;
47 my $opt_man=0;
48 my $user='';
49 my $pass='';
50 my $debug=0;
51 GetOptions(
52 'help|?' => \$opt_h,
53 'man|?' => \$opt_man,
54 'debug:i' => \$debug,
55 'u|username=s' => \$user,
56 'p|password=s' => \$pass,
57 'tmpdir:s' => \$TMP_DIR,
58 ) or Pod::Usage::pod2usage(2);
59
60 # Basic sanity check for /tmp dir
61 if (! $TMP_DIR or ! -d $TMP_DIR or ! -w $TMP_DIR) {
62 die "Can't write into temp dir '$TMP_DIR': $!\n";
63 }
64
65 ## Setup the Terminal
66 my $prompt = "dave> ";
67 my $term = Term::ReadLine->new('DAV Terminal');
68 $term->ornaments(0);
69 # Catch ^C
70 my $OUT = $term->OUT || *STDOUT;
71 $SIG{INT} = sub { print $OUT "\nType q, bye or quit\n$prompt"; };
72
73 ## Setup the HTTP::DAV client
74 my $useragent = DAVE::UserAgent->new();
75 $useragent->agent($USER_AGENT);
76 my $gdc = HTTP::DAV->new(-useragent=>$useragent);
77 HTTP::DAV::DebugLevel($debug);
78
79 ## Setup the help system
80 my $help = Pod2HelpParser->new();
81 $help->parse_from_filehandle(\*DATA);
82
83 ## Setup the valid commands and synonyms
84 my @valid_commands = qw( cd cat copy delete edit get help
85 lcd lls ls lock mkcol move open options propfind put pwd
86 quit set sh showlocks steal unlock unset );
87
88 my %command_synonyms = qw(
89 ! sh
90 ? help
91 q quit
92 bye quit
93 h help
94 dir ls
95 mkdir mkcol
96 rmdir delete
97 rm delete
98 cp copy
99 mv move
100 );
101
102 # Make a full populated hash from those given above.
103 # %commands = (
104 # quit => quit,
105 # q => quit,
106 # help => help,
107 # ? => help,
108 my %commands;
109 foreach my $command (@valid_commands) {
110 $commands{$command} = $command;
111 }
112
113 # Invert the command_synonyms for easy lookup.
114 foreach my $synonym (keys %command_synonyms ) {
115 $commands{$synonym} = $command_synonyms{$synonym};
116 }
117
118 ###########################################################################
119 # MAIN
120
121 pod2usage(-verbose => 1) if ($opt_h);
122 pod2usage(-verbose => 2) if ($opt_man);
123
124 # Barf if more than one URL
125 if (@ARGV > 1) {
126 pod2usage( -message => "$0: You must only specify one URL.\n")
127 }
128
129 print $OUT <<END;
130
131 dave -- DAV Explorer (v$VERSION)
132 Try "help", or "open http://host.com/dav_enabled_dir/"
133
134 END
135
136 # Put the credentials into HTTP::DAV for $url
137 my $url=shift @ARGV;
138 if ($user && $url) {
139 $gdc->credentials( -user=>$user, -pass=>$pass, -url=>$url );
140 }
141 &command_open($url) if ($url );
142
143 ######################################################################
144 # WHILE dave> command
145 my $line;
146 while ( defined ($line = $term->readline($prompt)) ) {
147
148 # Hack. Put a space between the ! shellout command and the next arg
149 $line =~ s/^([!])/$1 /g;
150
151 # Parse the user's typed command and return a parsed list of words.
152 my @args = &shellwords($line);
153
154 # Remove empty elements from the list
155 @args = grep( ! /^\s*$/,@args);
156
157 # If the user has entered nothing then back to while
158 # loop and throw another command prompt.
159 next if ( ! @args );
160
161 # Get the first argument. It should be the command.
162 my $command = shift @args;
163
164 # Check the validity of the command in our lookup.
165 if ( &is_valid_command($command) ) {
166
167 # This is so we can do the ref'ed function call
168 no strict 'refs';
169
170 $command = &get_command($command);
171
172 print $OUT "Valid Command: \"$command\"\n" if $HTTP::DAV::DEBUG>2;
173
174 # Call the command. e.g. &command_put(@args)
175 my $function_name = "command_" . $command;
176 my $return_code = &$function_name(@args);
177
178 } else {
179 print $OUT "Unrecognised command. Try 'help or h' for a list of commands.\n";
180 }
181 }
182
183 ######################################################################
184 # Command implementations
185
186 # This is a simple "print message" (pm) routine.
187 # Keeps things neat.
188 sub pm { print $OUT "** $_[0] **\n"; }
189
190 sub command_cd { $gdc->cwd (@_); pm($gdc->message()) }
191 sub command_copy { $gdc->copy (@_); pm($gdc->message()) }
192
193 sub command_delete {
194 $gdc->delete(-url=> $_[0], -callback=>\&cb);
195 pm($gdc->message());
196 }
197
198 sub command_mkcol { $gdc->mkcol (@_); pm($gdc->message()) }
199 sub command_move { $gdc->move (@_); pm($gdc->message()) }
200 sub command_open { $gdc->open (@_); pm($gdc->message()) }
201 sub command_steal { $gdc->steal (@_); pm($gdc->message()) }
202 sub command_unlock { $gdc->unlock (@_); pm($gdc->message()) }
203
204 sub command_set {
205 my ($url,$pn,$pv,$ns) = @_;
206 $gdc->set_prop (-url=>$url, -namespace=>$ns,
207 -propname=>$pn, -propvalue=>$pv);
208 pm($gdc->message())
209 }
210
211 sub command_unset {
212 my ($url,$pn,$ns) = @_;
213 $gdc->unset_prop (-url=>$url, -namespace=>$ns, -propname=>$pn);
214 pm($gdc->message())
215 }
216
217 sub command_lock {
218 my ($url,$timeout,$depth ) = @_;
219 $gdc->lock (-url=>$url,
220 -timeout=>$timeout,
221 -depth=>$depth,
222 -owner=>$LOCK_OWNER);
223 pm($gdc->message())
224 }
225
226 sub command_showlocks {
227 my $rl = $gdc->get_lockedresourcelist();
228 if ($rl) {
229 my $l = $rl->showlocks;
230 print $OUT ($l ne "") ? $l : "No locks\n";
231 }
232 }
233
234 sub command_cat {
235 my ($url) = @_;
236 $gdc->get(-url=>$url, -callback=>\&cat_callback,-chunk=>128);
237 }
238
239 sub command_edit {
240 my $remote_file = shift;
241
242 my $EDITOR= $ENV{DAV_EDITOR} || $ENV{EDITOR} || 'vi';
243 my $local_file = HTTP::DAV::_tempfile('dave', $TMP_DIR);
244
245 my $resource = $gdc->propfind($remote_file);
246 if ( $resource && $resource->is_collection() ) {
247 pm("Can't edit collections");
248 return;
249 }
250
251 my $locked=0;
252 # Try a lock with a 10h timeout first.
253 # If that doesn't work then try it without a timeout.
254 if ( $gdc->lock(-url=>$remote_file, -timeout=>"10h",-owner=>$LOCK_OWNER ) ) {
255 $locked=1;
256 pm( "Locked with 10 hour timeout" );
257 } elsif ( $gdc->lock(-url=>$remote_file, -owner=>$LOCK_OWNER) ) {
258 $locked=1;
259 pm( "Locked with infinite timeout" );
260 } else {
261 my $resp = $gdc->get_last_response();
262 if ($resp->messages =~ /Locked/ ) {
263 pm("$remote_file is locked. Can't edit.");
264 return;
265 } else {
266 pm("Couldn't lock $remote_file for editing (" . $gdc->message . ")" );
267 }
268 }
269
270
271 if ( $gdc->get($remote_file,$local_file) ) {
272 pm( $gdc->message());
273
274 pm("Using $EDITOR to edit $local_file");
275 my $file_date_at_start = (stat($local_file))[9];
276
277 sleep 2;
278 system("$EDITOR $local_file") == 0 ||
279 pm("$EDITOR $local_file failed: $!");
280
281 my $file_date_at_end = (stat($local_file))[9];
282
283 if ( $file_date_at_start eq $file_date_at_end ) {
284 pm ("File unchanged");
285 } else {
286 $gdc->put($local_file,$remote_file);
287 pm( $gdc->message());
288 }
289
290 unlink $local_file || pm("Couldn't remove $local_file: $!");
291 }
292 else {
293 pm( $gdc->message());
294 }
295
296 if ($locked) {
297 $gdc->unlock($remote_file);
298 pm( $gdc->message());
299 }
300 }
301
302
303
304 sub command_get {
305 my ($remote,$local) = @_;
306 $local ||= ".";
307 $gdc->get(-url=>$remote,
308 -to =>$local,
309 -callback=>\&cb
310 );
311 }
312
313 sub command_put {
314 my ($local,$remote) = @_;
315 $remote ||= ".";
316 $gdc->put(-local=>$local,
317 -url =>$remote,
318 -callback=>\&cb
319 );
320 }
321
322 # PWD
323 sub command_pwd {
324 my $uri = $gdc->get_workingurl();
325 if ($uri) {
326 print $OUT "$uri\n";
327 return 1;
328 } else {
329 pm("Not connected. Type \"help open\"");
330 return 0;
331 }
332 }
333
334 # OPTIONS
335 sub command_options{
336 my $options = $gdc->options(@_);
337 print $OUT "$options\n" if ($options);
338 pm($gdc->message);
339 return $options;
340 }
341
342 # HELP
343 sub command_help {
344 my (@args) = @_;
345
346 # If they just typed help with no arguments then give them generic help
347 if ( $#args < 0 ) {
348 print $OUT "Type \"help <command>\" for more detail:\n";
349 foreach my $i (sort @valid_commands ) {
350 my($sect,$title,$first_line,$body) = $help->get_help($i);
351 if ($sect) {
352 printf $OUT (" %-10s%s\n",$i,$first_line);
353 } else {
354 printf $OUT (" %-10s%s\n",$i,"no help");
355 }
356 }
357 print $OUT "\n";
358 }
359
360 # If they type "help <topic>" then look for help on <topic>.
361 else {
362 my $help_topic = shift @args;
363 my $format = shift @args || "verbose";
364
365 my ($sect,$title,$first_line,$help_body) =
366 $help->get_help( &get_command($help_topic) || $help_topic );
367 my $help_text;
368 if ( defined $sect && $sect ne "" ) {
369 if ($format eq "verbose" ) {
370 $help_body =~ s/\n/\n /gs;
371 $help_text = "\n $title\n $help_body\n";
372 } else {
373 $help_text = "\n $sect - $first_line\n";
374 }
375 } else {
376 $help_text = "\nNo help for \"$help_topic\"\n";
377 }
378 print $OUT $help_text;
379 }
380 }
381
382 # LCD
383 sub command_lcd {
384 my (@args) = @_;
385
386 my $args = join(' ', @args) || "";
387 chdir($args);
388 }
389
390 # LLS
391 sub command_lls {
392 my (@args) = @_;
393
394 my $args = join(' ', @args) || "";
395 system("ls @args");
396 }
397
398 # LS (client)
399 sub command_ls {
400 my $resource = $gdc->propfind(@_);
401 if ($resource) {
402 if ($resource->is_collection) {
403 print $OUT $resource->get_property('short_ls');
404 } else {
405 print $OUT $resource->get_property('long_ls');
406 }
407 } else {
408 pm($gdc->message);
409 }
410 }
411
412 sub command_propfind {
413 my $resource = $gdc->propfind(@_);
414 if ($resource) {
415 print $OUT $resource->get_property('long_ls');
416 } else {
417 pm($gdc->message);
418 }
419 }
420
421 # QUIT
422 sub command_quit {
423 my (@args) = @_;
424 print $OUT "Bye\n";
425 exit;
426 }
427
428 # SH (!)
429 sub command_sh {
430 my (@args) = @_;
431
432 my $args = join(' ', @args) || "";
433 system("$args");
434 }
435
436 sub AUTOLOAD {
437 my $sub = $AUTOLOAD || "";
438 #my @args = @{$_[0]} || ();
439 die "Fatal Error. No function defined $sub ?!\n";
440 }
441
442 ######################################################################
443 # CALLBACKS for cat,get and put
444 {
445 my $in_transfer=0;
446
447 sub cat_callback {
448 my($status,$mesg,$url,$so_far,$length,$data) = @_;
449 $|=1;
450 if ($status == 1) {
451 print "\n" if ($in_transfer);
452 print "**$mesg (success)\n";
453 $in_transfer=0;
454 }
455 if ($status == 0) {
456 print "**$mesg\n";
457 $in_transfer=0;
458 }
459 if ($status == -1) {
460 print $OUT $data;
461 $in_transfer++;
462 }
463 }
464
465 # Used for get and put. put doesn't support chunking though.
466 sub cb {
467 my($status,$mesg,$url,$so_far,$length,$data) = @_;
468 $|=1;
469 if ($status == 1) {
470 print "\n" if ($in_transfer);
471 print " $mesg (success)\n";
472 $in_transfer=0;
473 }
474 if ($status == 0) {
475 print "**$mesg\n";
476 $in_transfer=0;
477 }
478 if ($status == -1) {
479 if (!$in_transfer++) {
480 print " Transferring $url ($length bytes):\n";
481 }
482 my $width = 60;
483 if ($length>0) {
484 my $num = int($so_far/$length * $width);
485 my $space = $width-$num;
486 print " [" . "#"x$num . " "x$space . "]";
487 }
488 print " $so_far bytes\r";
489 }
490 }
491 }
492
493 ###########################################################################
494 sub is_valid_command {
495 my ($command) = @_;
496 $command = lc($command);
497 return 1 if defined $commands{$command};
498 }
499
500 sub get_command {
501 my ($command) = @_;
502 $command = lc($command);
503 return $commands{$command};
504 }
505
506 BEGIN {
507 # We make our own specialization of HTTP::DAV::UserAgent (which in turn is already a specialisation of LWP::UserAgent).
508 # This user agent is able to:
509 # - interact with the user on the command line to get user/pass's
510 # - allow the user to try 3 times before failing.
511 {
512 package DAVE::UserAgent;
513 use vars qw(@ISA);
514 @ISA = qw(HTTP::DAV::UserAgent);
515
516 sub new {
517 my $self = HTTP::DAV::UserAgent::new(@_);
518 #$self->agent("DAVE/v$VERSION");
519 $self->{_failed_logins} = ();
520 return $self;
521 }
522
523 sub request {
524 my($self) = shift;
525 my $resp = $self->SUPER::request(@_);
526
527 # Only if we did not get a 401 back from the server
528 # do we go and
529 # commit the user's details to memory.
530 $self->_commit_credentials() if ($resp->code() != 401);
531 return $resp;
532 }
533
534 sub _set_credentials {shift->{_temp_credentials} = \@_; }
535 sub _commit_credentials {
536 my ($self)=@_;
537 if (defined $self->{_temp_credentials} ) {
538 $self->credentials(@{$self->{_temp_credentials}});
539 $self->{_temp_credentials} = undef;
540 }
541 }
542
543 sub get_basic_credentials {
544 my($self, $realm, $url) = @_;
545 my $userpass;
546
547 # First, try to get the details from our memory.
548 my @mem_userpass = $self->SUPER::get_basic_credentials($realm,$url);
549 return @mem_userpass if @mem_userpass;
550
551 if (-t) {
552
553 my $netloc = $url->host_port;
554 if ($self->{_failed_logins}->{$realm . $netloc}++ > 3) {
555 return (undef,undef)
556 }
557
558 print "\nEnter username for $realm at $netloc: ";
559 my $user = <STDIN>;
560 chomp($user);
561 return (undef, undef) unless length $user;
562 print "Password: ";
563 system("stty -echo");
564 my $password = <STDIN>;
565 system("stty echo");
566 print "\n"; # because we disabled echo
567 chomp($password);
568
569 $self->_set_credentials($netloc, $realm,$user,$password);
570 #print "Returning $user, $password\n";
571 return ($user, $password);
572 } else {
573 return (undef, undef)
574 }
575 }
576 }
577
578 ######################################################################
579 # Setup our help system with this nifty Pod::Parser from the
580 # Pod at the end of this script.
581 #
582 {
583 package Pod2HelpParser;
584
585 use vars qw(@ISA);
586 use Pod::Parser;
587 @ISA = qw(Pod::Parser);
588
589 ######
590 # Pod2HelpParser - public help access methods.
591 #
592 # get_help() will return from the pod any items
593 # that start with $command as help
594 #
595 # For instance:
596 # my($sect,$title,$terse,$long) = $parser->get_help("open");
597 sub get_help {
598 my ($self,$command) = @_;
599 foreach my $sect (keys %{$self->{_help_text}} ) {
600 if ( $sect =~ /^$command\b/i ) {
601 my $title = $self->{_title} {$sect} ||"";
602 my $first_line = $self->{_first_line}{$sect} ||"";
603 my $help_text = $self->{_help_text} {$sect} ||"";
604 $help_text=~ s/\n*$//gs;
605 return ($sect,$title,$first_line,$help_text);
606 }
607 }
608 return ();
609 }
610
611 sub get_help_list {
612 my ($self) = @_;
613 my @return;
614 foreach my $sect (keys %{$self->{_help_text}} ) {
615 next if $sect eq "OTHER";
616 push (@return,$sect);
617 }
618 return @return;
619 }
620
621 ######
622 # INIT
623 # These methods are all overriden from Pod::Parser.
624 # They are effectively call-backs to handle pod.
625 # Specifically, we're building a hash to provide convenient
626 # access to the pod data as help information.
627 sub command {
628 my ($parser, $command, $paragraph, $line_num) = @_;
629 my $title = $parser->interpolate($paragraph, $line_num);
630
631 # Remove extraneous whitespace
632 $title =~ s/^[\s\n]*(.*?)[\s\n]*$/$1/gis;
633
634 my $section = $title;
635 $section =~ s/^\s*(.+?)\s.*$/$1/;
636 $section= ($command eq "item") ? $section : "OTHER";
637 $parser->{_last_section} = $section;
638 $parser->{_help_text}{$section} = "";
639 $parser->{_title}{$section} = $title;
640 }
641
642 # Overrriden from Pod::Parser - interprets section text
643 sub verbatim {
644 my ($parser, $paragraph, $line_num) = @_;
645 my $expansion = $parser->interpolate($paragraph, $line_num);
646
647 # Get the first line
648 my $first_line = $expansion;
649 $first_line =~ s/^(.*?)\n.*/$1/gis;
650
651 my $section_head = $parser->_get_last_section;
652 $parser->{_help_text} {$section_head} .= $expansion;
653 if (!defined $parser->{_first_line}{$section_head} ) {
654 $parser->{_first_line}{$section_head} = $first_line;
655 }
656 }
657
658 # Overrriden from Pod::Parser - do nothing with normal body text
659 sub textblock { shift->verbatim(@_); }
660 sub interior_sequence { return $_[2]; }
661 sub _get_last_section { $_[0]->{_last_section}; }
662 }
663
664 } # END BEGIN
665
666 ######################################################################
667 # PERLDOC
668 __END__
669
670 =head1 DESCRIPTION
671
672 dave is a powerful command-line program for interacting with WebDAV-enabled webservers. With dave you can:
673
674 =over 4
675
676 =item * get and put files
677
678 =item * make directories on a remote webserver
679
680 =item * remove files and directories from a remote webserver
681
682 =item * edit a file on the webserver with a single command
683
684 =item * recursively get a remote directory
685
686 =item * recursively put a local directory
687
688 =item * lock and unlock remote files and directories
689
690 =item * securely transfer over https
691
692 =item * authenticate using the safer Digest authentication
693
694 =back
695
696 Dave is a part of the PerlDAV project (http://www.webdav.org/perldav/) and is built on top of the HTTP::DAV perl API.
697
698 If you would like to script webdav interactions in Perl checkout the HTTP::DAV API as it's commands are the basis for dave's.
699
700 =head1 OPTIONS
701
702 =over 4
703
704 =item C<-debug N>
705
706 Sets the debug level to N. 0=none. 3=noisy.
707
708 =item C<-h>
709
710 Prints basic help and options.
711
712 =item C<-man>
713
714 Prints the full manual (equivalent to perldoc dave).
715
716 You will need to use a pager like C<more> or C<less>. e.g.
717
718 dave -man |less
719
720 =item C<< -p <password> >>
721
722 Sets the password to be used for the URL.
723 You must also supply a user. See C<-u>.
724
725 =item C<< -u <username> >>
726
727 Sets the username to be used for the URL.
728 You must also supply a pass. See C<-p>.
729
730 =item C<-tmpdir /some/path>
731
732 Create temporary files in C</some/path> instead of the default C</tmp>.
733
734 =back
735
736 =head1 COMMANDS
737
738 =over 4
739
740 =item B<cd URL>
741
742 changes directories
743
744 dave> open host.org/dav_dir/
745 dave> cd dir1
746 dave> cd ../dir2
747
748 =item B<cat URL>
749
750 shows the contents of a remote file
751
752 dave> open host.org/dav_dir/
753 dave> cat index.html
754
755 Note: you cannot cat a directory (collection).
756
757 =item B<cp>
758
759 =item B<copy SOURCE_URL DEST_URL>
760
761 copies one remote resource to another
762
763 dave> open host.org/dav_dir/
764
765 Create a copy of dir1/ as dav2/
766
767 dave> cp dir1 dav2
768
769 Create a copy of dir1/file.txt as dav2/file.txt
770
771 dave> cd dir1
772 dave> copy file.txt ../dav2
773
774 Create a copy of file.txt as ../dav2/new_file.txt
775
776 dave> copy file.txt dav2/new_file.txt
777
778 Aliases: cp
779
780 =item B<rmdir URL>
781
782 =item B<rm URL>
783
784 =item B<delete URL>
785
786 deletes a remote resource
787
788 dave> open host.org/dav_dir/
789 dave> delete index.html
790 dave> rmdir ./dir1
791 dave> delete /dav_dir/dir2/
792 dave> delete /dav_dir/*.html
793
794 This command recursively deletes directories. BE CAREFUL :)
795
796 This command supported wildcards (globbing). See get.
797
798 Aliases: rm, rmdir
799
800 =item B<edit URL>
801
802 edits the contents of a remote file
803
804 dave> open host.org/dav_dir/
805 dave> edit index.html
806
807 Edit is equivalent to the following sequence of commands:
808
809 LOCK index.html (if allowed)
810 GET index.html /tmp/dave.perldav.421341234124
811 sh $EDITOR /tmp/dave.perldav.421341234124
812 PUT index.html (if modified)
813 UNLOCK index.html (if locked)
814
815 Where $EDITOR is determined from the environment variables
816 DAV_EDITOR or EDITOR.
817
818 If DAV_EDITOR is set, it will use that, otherwise it will
819 use EDITOR. If neither variables are set, then "vi" will
820 be used.
821
822 Notes:
823
824 The lock only lasts for 10 hours.
825
826 You cannot edit a directory (collection).
827
828 The temporary save directory is editable by
829 editing dave and changing TMP_DIR
830
831 =item B<get URL [FILE]>
832
833 downloads the file or directory at URL
834
835 If FILE is not specified it will be saved to your
836 current working directory using the same name as
837 the remote name.
838
839 dave> open host.org/dav_dir/
840
841 Recursively get remote my_dir/ to .
842
843 dave> get my_dir/
844
845 Recursively get remote my_dir/ to /tmp/my_dir/
846
847 dave> get my_dir /tmp
848
849 Get remote my_dir/index.html to /tmp/index.html
850
851 dave> get /dav_dir/my_dir/index.html /tmp
852
853 Get remote index.html to /tmp/index1.html
854
855 dave> get index.html /tmp/index1.html
856
857 Use globs and save to /tmp
858
859 dave> get index* /tmp # Gets index*.html, index*.txt, etc.
860 dave> get index*.html /tmp/index1.html # Gets index*.html
861 dave> get index[12].htm? # Gets file1 and file2, .htm and .html
862
863 =item B<? [CMD]>
864
865 =item B<h [CMD]>
866
867 =item B<help [CMD]>
868
869 prints list of commands or help for CMD
870
871 dave> ?
872
873 dave> help get
874
875 Aliases: ?, h
876
877 =item B<lcd [DIR]>
878
879 changes local directory
880
881 dave> lcd /tmp
882
883 =item B<lls [DIR]>
884
885 lists local directory contents
886
887 dave> lcd /tmp
888 dave> lls
889 dave> lls /home
890
891 This command simply execs the local ls command and is
892 equivalent to "!ls"
893
894 =item B<dir [URL]>
895
896 =item B<ls [URL]>
897
898 lists remote directory contents or file props
899
900 dave> ls
901 Listing of http://host.org/dav_dir/
902 ./ Aug 29 02:26 <dir>
903 mtx_0.04.tar.gz 52640 Aug 11 11:45
904 index.html 4580 Aug 11 11:45
905 index0.04.html 4936 Nov 11 2000
906 mydir/ Aug 19 21:14 <dir>,<locked>
907
908 dave> ls index.html
909 URL: http://www.webdav.org/perldav/index.html
910 Content-type: text/html
911 Creation date: Sun Aug 12 21:58:02 2001
912 Last modified:
913 Size: 4580 bytes
914 Locks supported: write/exclusive write/shared
915 Locks:
916
917 Use propfind to get a similar printout of a
918 collection (directory).
919
920 Aliases: dir
921
922 =item B<lock [URL [TIMEOUT] [DEPTH]]>
923
924 locks a resource
925
926 Without a URL you will lock the current remote
927 collection.
928
929 TIMEOUT can be any of the following formats:
930 30s 30 seconds from now
931 10m ten minutes from now
932 1h one hour from now
933 1d tomorrow
934 3M in three months
935 10y in ten years time
936 2000-02-31 00:40:33
937 2000-02-31
938
939 Default is an infinite timeout
940
941 See perldoc C<HTTP::DAV::Resource> for more information
942 about timeouts.
943
944 DEPTH can be either "0" or "infinity" (default)
945
946 Seeting the lock Scope and Type is not currently
947 implemented. Let me know if you need it as it shouldn't
948 be too much effort.
949
950 =item B<mkdir URL>
951
952 =item B<mkcol URL>
953
954 make a remote collection (directory)
955
956 dave> open host.org/dav_dir/
957 dave> mkcol new_dir
958 dave> mkdir /dav_dir/new_dir
959
960 Aliases: mkdir
961
962 =item B<mv>
963
964 =item B<move SOURCE_URL DEST_URL>
965
966 moves a remote resource to another
967
968 dave> open host.org/dav_dir/
969
970 Move dir1/ to dav2/
971
972 dave> move dir1 dav2
973
974 Move file dir2/file.txt to ../file.txt
975
976 dave> cd dir2
977 dave> move file.txt ..
978
979 Move file.txt to dav2/new_file.txt
980
981 dave> move file.txt dav2/new_file.txt
982
983 Aliases: mv
984
985 =item B<open URL>
986
987 connects to the WebDAV-enabled server at URL
988
989 dave> open host.org/dav_dir/
990
991 Note that if authorization details are required you will
992 be prompted for them.
993
994 https and Digest authorization are not currently
995 supported. Please let me know if you need it.
996
997
998 =item B<options [URL]>
999
1000 show the HTTP methods allowed for a URL
1001
1002 dave> options index.html
1003 OPTIONS, GET, HEAD, POST, DELETE, TRACE, PROPFIND,
1004 PROPPATCH, COPY, MOVE, LOCK, UNLOCK
1005
1006 Note that Microsoft's IIS does not support LOCK on
1007 collections (directories). Nor does it support PROPPATCH.
1008
1009 =item B<propfind [URL]>
1010
1011 show the properties of a resource
1012
1013 dave> propfind test
1014 URL: http://host.org/dav_dir/test/
1015 Content-type: httpd/unix-directory
1016 Creation date: Wed Aug 29 00:36:42 2001
1017 Last modified:
1018 Size: bytes
1019 Locks supported: write/exclusive write/shared
1020 Locks:
1021
1022 Using ls will get you the same printout if you ls
1023 a file. But ls'ing a collection will show you the
1024 collections contents.
1025
1026 =item B<put FILE [URL]>
1027
1028 uploads a local file or directory to URL
1029 or the currently opened location.
1030
1031 If URL is an existing collection then the dir/file will
1032 be copied INTO that collection.
1033
1034 dave> open host.org/dav_dir/
1035
1036 Recursively put local my_dir/ to host.org/dav_dir/my_dir/:
1037
1038 dave> put my_dir/
1039
1040 Put local index.html to host.org/dav_dir/index1.html:
1041
1042 dave> put /tmp/index.html index1.html
1043
1044 Put * to remote directory
1045
1046 dave> put *
1047
1048 Put index[12].htm? to remote directory /dav_dir (/dav_dir must exist)
1049
1050 dave> put index[12].htm? /dav_dir
1051
1052 Put index[1234].htm? to remote directory /dav_dir (/dav_dir must exist)
1053
1054 dave> put index[1-4].htm? /dav_dir
1055
1056 Glob types supported are, * (matches any characters), ? (matches any one character), [...] (matches any characters in the set ...).
1057
1058 =item B<pwd>
1059
1060 prints the currently opened URL (working directory)
1061
1062 dave> open host.org/dav_dir/
1063 dave> cd new_dir/
1064 dave> pwd
1065 http://host.org/dav_dir/new_dir/
1066
1067 =item B<q>
1068
1069 =item B<bye>
1070
1071 =item B<quit>
1072
1073 exits dave
1074
1075 Note that dave does not unlock any locks created
1076 during your session.
1077
1078 Aliases: q, quit
1079
1080 =item B<set URL PROPERTY VALUE [NAMESPACE]>
1081
1082 sets a custom property on a resource
1083
1084 dave> set file.txt author "Patrick Collins"
1085 dave> set file.txt author "Patrick Collins" "mynamespace"
1086
1087 The NAMESPACE by default is "DAV:".
1088
1089 =item B<!>
1090
1091 =item B<sh>
1092
1093 executes a local command (alias !)
1094
1095 dave> sh cat localfile
1096 dave> !gzip localfile.gz
1097 dave> ! "cat localfile | less"
1098
1099 Aliases: !
1100
1101 =item B<showlocks>
1102
1103 show my locks on a resource
1104
1105 Shows any locked resources that you've locked in this
1106 session.
1107
1108 See C<propfind> if you'd like to see anyone's locks held
1109 against a particular resource.
1110
1111 =item B<steal [URL]>
1112
1113 remove ANY locks on a resource
1114
1115 Useful if you accidentally forgot to unlock a resource
1116 from a previous session or if you think that somebody
1117 has forgotten to unlock a resource.
1118
1119 =item B<unlock [URL]>
1120
1121 unlocks a resource
1122
1123 Note that unlock will only unlock locks that you have
1124 created. Use steal if you want to forcefully unlock
1125 somebody else's lock.
1126
1127 =item B<unset URL PROPERTY [NAMESPACE]>
1128
1129 unsets a property from a resource
1130
1131 dave> unset file.txt author
1132 dave> unset file.txt author "mynamespace"
1133
1134 The NAMESPACE by default is "DAV:".
1135
1136 =back
1137
1138 =head1 GETTING HELP
1139
1140 The perldav mailing list
1141 There is a mailing list for PerlDAV and dave for use by Developers and Users.
1142 Please see http://mailman.webdav.org/mailman/listinfo/perldav
1143
1144 =head1 INSTALLATION
1145
1146 dave is installed to /usr/local/bin by default when you
1147 install the PerlDAV library. See
1148 http://www.webdav.org/perldav/ for installation details
1149 of PerlDAV.
1150
1151 =head1 WHAT PLATFORMS WILL IT WORK ON?
1152
1153 dave is pure perl so only needs Perl5.003 (or later) and
1154 the C<PerlDAV> library to be installed.
1155
1156 I have not ported dave to Windows but would like somebody
1157 to have a shot at it.
1158
1159 =head1 SEE ALSO
1160
1161 The C<PerlDAV> perl API at http://www.webdav.org/perldav/
1162 or by typing "perldoc HTTP::DAV" on your command line.
1163
1164 =head1 AUTHOR AND COPYRIGHT
1165
1166 This module is Copyright (C) 2001 by
1167
1168 Patrick Collins
1169 G03 Gloucester Place, Kensington
1170 Sydney, Australia
1171
1172 Email: pcollins@cpan.org
1173 Phone: +61 2 9663 4916
1174
1175 All rights reserved.
1176
1177 You may distribute this module under the terms of either the GNU General Public License or the Artistic License, as specified in the Perl README file.
1178
1179 =head1 MAINTAINER
1180
1181 Cosimo Streppone, E<lt>cosimo@cpan.orgE<gt>
1182
1183 =cut