Skip Menu |

This queue is for tickets about the Net-DAV-Server CPAN distribution.

Report information
The Basics
Id: 46865
Status: resolved
Priority: 0/
Queue: Net-DAV-Server

People
Owner: cpan [...] cpanel.net
Requestors: dmuey [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: (no value)
Fixed in: (no value)



Subject: copy() depth problem and source/target path alteration problem
problem 1: if you rename a directory and the client doesn't send a Depth header it does zero depth and blows away files problem 2: When the $source has a trailing slash and the target does not, any files get copied as $target$file not $target/$file patch coming soon
@dirs, @files == $VAR1 = [ '/case29042/subfolder2', '/case29042/subfolder1', '/case29042/' ]; $VAR2 = [ '/case29042/.DS_Store', '/case29042/file1', '/case29042/file2', '/case29042/file3', '/case29042/subfolder1/file4', '/case29042/subfolder1/file5', '/case29042/subfolder1/file6', '/case29042/subfolder2/file7', '/case29042/subfolder2/file8', '/case29042/subfolder2/file9' ]; Ding! both @dirs && @files get xformed with this: s{^/case29042/}{/case29042-2}
Subject: copy() depth problem, source/target path alteration problem, delete() dirs won't remove
problem 3: rmdir() won't delete paths that are not empty so delete() needs to do files first
this patch resolves all 3 problems of this this case
--- /usr/local/lib/perl5/site_perl/5.8.9/Net/DAV/Server.pm.orig 2006-07-18 22:35:23.000000000 -0500 +++ /usr/local/lib/perl5/site_perl/5.8.9/Net/DAV/Server.pm 2009-06-11 19:59:38.000000000 -0500 @@ -169,14 +169,9 @@ my $dom = XML::LibXML::Document->new("1.0", "utf-8"); my @error; - foreach my $part ( - grep { $_ !~ m{/\.\.?$} } - map { s{/+}{/}g; $_ } - File::Find::Rule::Filesys::Virtual->virtual($fs)->in($path), - $path - ) - { + # see rt 46865: files first since rmdir() only removed empty directories + foreach my $part ( _get_files($fs, $path), _get_dirs($fs, $path), $path ) { next unless $fs->test("e", $part); if ($fs->test("f", $part)) { @@ -205,35 +200,31 @@ sub copy { my ($self, $request, $response) = @_; my $path = decode_utf8 uri_unescape $request->uri->path; + $path =~ s{/+$}{}; # see rt 46865 + my $fs = $self->filesys; my $destination = $request->header('Destination'); $destination = URI->new($destination)->path; - my $depth = $request->header('Depth') || 0; + $destination =~ s{/+$}{}; # see rt 46865 + + my $depth = $request->header('Depth'); + $depth = '' if !defined $depth; + my $overwrite = $request->header('Overwrite') || 'F'; if ($fs->test("f", $path)) { return $self->copy_file($request, $response); } - # it's a good approximation - $depth = 100 if defined $depth && $depth eq 'infinity'; - - my @files = - map { s{/+}{/}g; $_ } - File::Find::Rule::Filesys::Virtual->virtual($fs)->file->maxdepth($depth) - ->in($path); - - my @dirs = reverse sort - grep { $_ !~ m{/\.\.?$} } - map { s{/+}{/}g; $_ } - File::Find::Rule::Filesys::Virtual->virtual($fs) - ->directory->maxdepth($depth)->in($path); + my @files = _get_files($fs, $path, $depth); + my @dirs = _get_dirs($fs, $path, $depth); push @dirs, $path; foreach my $dir (sort @dirs) { my $destdir = $dir; $destdir =~ s/^$path/$destination/; + if ($overwrite eq 'F' && $fs->test("e", $destdir)) { return HTTP::Response->new(401, "ERROR", $response->headers); } @@ -243,6 +234,7 @@ foreach my $file (reverse sort @files) { my $destfile = $file; $destfile =~ s/^$path/$destination/; + my $fh = $fs->open_read($file); my $file = join '', <$fh>; $fs->close_read($fh); @@ -315,9 +307,9 @@ my $destexists = $self->filesys->test("e", $destination); $response = $self->copy($request, $response); + $response = $self->delete($request, $response) if $response->is_success; - $response->code(201) unless $destexists; return $response; @@ -581,6 +573,26 @@ return $response; } +sub _get_files { + my ($fs, $path, $depth) = @_; + reverse map { s{/+}{/}g;s{/$}{}; $_ } + $depth =~ m{\A\d+\z} ? + File::Find::Rule::Filesys::Virtual->virtual($fs)->file->maxdepth($depth)->in($path) + : File::Find::Rule::Filesys::Virtual->virtual($fs)->file->in($path) + ; +} + +sub _get_dirs { + my ($fs, $path, $depth) = @_; + return reverse sort + grep { $_ !~ m{/\.\.?$} } + map { s{/+}{/}g;s{/$}{}; $_ } + $depth =~ m{\A\d+\z} ? + File::Find::Rule::Filesys::Virtual->virtual($fs)->directory->maxdepth($depth)->in($path) + : File::Find::Rule::Filesys::Virtual->virtual($fs)->directory->in($path) + ; +} + 1; __END__
Applied patches and updated.