Apache-WebDAV

 view release on metacpan or  search on metacpan

lib/Apache/WebDAV.pm  view on Meta::CPAN

    #trace    => 1,
    #lock     => 1,
    #unlock   => 1,
);

#
# Constructor.  Does nothing.
#
sub new
{
    my $class = shift;

    bless {}, $class;
}

#
# Specify which modules will handle which paths.
#
sub register_handlers
{
    my ($self, @handlers) = @_;

    $self->{'handlers'} = \@handlers;
}

#
# Process the request.  The $r is the apache object passed in from the mod_perl
# handler.
#
sub process
{
    my ($self, $r) = @_;

    my $uri    = $r->uri();
    my $method = lc($r->method());

    my $handler = $self->get_handler_for_path($uri);

    if($implemented{$method})
    {
        return $self->$method($r, $handler);
    }
    else
    {
        return DECLINED;
    }
}

#
# Started working on this, targetted clients don't need it, never finished.
#

# sub proppatch
# {
#     my ($self, $r, $handler) = @_;
# 
#     $r->status(200);
#     $r->header_out("Allow",
#                    "OPTIONS, HEAD, GET, PUT, " .
#                    "DELETE, MKCOL, PROPPATCH, PROPFIND, COPY, MOVE");
#     $r->header_out("DAV", "1,<http://apache.org/dav/propset/fs/1>");
#     $r->send_http_header();
# 
#     return OK;
# }

#
# Copy a resource to another location.
#
sub copy
{
    my ($self, $r, $handler) = @_;

    my $path = $r->uri();

    my $destination = $r->header_in('Destination');
    my $depth       = $r->header_in('Depth');
    my $overwrite   = $r->header_in('Overwrite');

    # Default according to the book is overwrite = T
    if(!defined($overwrite))
    {
        $overwrite = 'T';
    }

    # Translate the destination into a usable format
    $destination = URI->new($destination)->path();

    # If it's a regular file, don't sweat it
    if($handler->test('f', $path))
    {
        return $self->copy_file($r, $handler, $path, $destination, $overwrite);
    }

    # Otherwise, we're copying a directory and we have to do it recursively.
    # The logic for this was taken from Net::DAV::Server.  It's creepy.

    # We can't really go to infinity, but we can fake it.
    $depth = 100 if defined($depth) && $depth eq 'infinity';

    # Search for source files that we have to copy
    my @files = map { s|/+|/|g; $_ }
        File::Find::Rule::Filesys::Virtual->virtual($handler)->file->maxdepth($depth)->in($path);

    # Search for source directories that we have to copy (didn't I tell you it
    # was creepy?)
    my @dirs = reverse sort
        grep { $_ !~ m|/\.\.?$| }
         map { s|/+|/|g; $_ }
        File::Find::Rule::Filesys::Virtual->virtual($handler)->directory->maxdepth($depth)->in($path);

    push @dirs, $path;

    # Create all required directories first
    foreach my $dir (sort @dirs)
    {
        my $dest_dir = $dir;

        $dest_dir =~ s/^$path/$destination/;

        if($overwrite eq 'F' && $handler->test('e', $dest_dir))

lib/Apache/WebDAV.pm  view on Meta::CPAN

    {
        if($overwrite eq 'T')
        {
            if($handler->test('d', $destination))
            {
                $overwrote_collection = 1;
            }

            $r->uri($destination); # Specify the URI for the following deletion

            my $result = $self->delete($r, $handler);

            $r->uri($path);        # Reset URI to original value
        }
    }

    my $copy_result = $self->copy($r, $handler);

    if($copy_result != 201)
    {
        if($copy_result == 412)
        {
            return 412;
        }
        elsif($copy_result == HTTP_NO_CONTENT) # Directory already existed
        {
            return 403;
        }
        else
        {
            return FORBIDDEN;
        }
    }

    my $delete_result = $self->delete_resource($r, $handler, $path);

    # Did the delete work properly?
    if(!$delete_result)
    {
        return FORBIDDEN;
    }

    if($already_exists)
    {
        return 204;
    }
    else
    {
        return 201;
    }
}

#
# Specify the options this WebDAV server supports.
#
sub options
{
    my ($self, $r, $handler) = @_;

    $r->header_out('Allow'         => join(',', map { uc } keys %implemented));
    $r->header_out('DAV'           => '1,2,<http://apache.org/dav/propset/fs/1>');
    $r->header_out('MS-Author-Via' => 'DAV');
    $r->header_out('Keep-Alive'    => 'timeout=15, max=96');

    $r->send_http_header();

    return OK;
}

#
# Get information about a file or a directory (or the contents of a directory).
#
sub propfind
{
    my ($self, $r, $handler) = @_;

    my $depth = $r->header_in('Depth');
    my $uri   = $r->uri();

    # Make sure the resource exists
    if(!$handler->test('e', $uri))
    {
        return NOT_FOUND;
    }

    $r->status(207);
    $r->content_type('text/xml; charset="utf-8"');

    my @files;

    if($depth == 0)
    {
        @files = ($uri);
    }
    elsif($depth == 1)
    {
        $uri =~ s/\/$//; # strip trailing slash, we don't store it in the db

        @files = $handler->list($uri);

        # remove . and .. from the list
        @files = grep( $_ !~ /^\.\.?$/, @files );

        # Add a trailing slash to the directory if there isn't one already
        if($uri !~ /\/$/)
        {
            $uri .= '/';
        }

        # Add the current folder to the front of the filename
        @files = map { "$uri$_" } @files;

        # Goliath only doesn't want to see the current/base directory in the
        # response.
        if($r->header_in('User-Agent') !~ /Goliath/)
        {
            push @files, $uri;
        }
    }

    my %wanted_properties = $self->get_wanted_properties($r);



( run in 0.706 second using v1.01-cache-2.11-cpan-71847e10f99 )