Apache-WebDAV

 view release on metacpan or  search on metacpan

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

    $multistat->setAttribute('xmlns:D', 'DAV:');
    $doc->setDocumentElement($multistat);

    foreach my $file (@$files)
    {
        my $path = $file->{'path'};
        my $stat = $file->{'stat'};
        my $resp = $doc->createElement('D:response');

        $multistat->addChild($resp);

        my $href = $doc->createElement('D:href');

        $href->appendText(
            File::Spec->catdir(
                map { uri_escape encode_utf8 $_ } File::Spec->splitdir($path)
            )
        );

        $resp->addChild($href);

        my $okprops = $doc->createElement('D:prop');

        foreach my $wanted_prop (keys %$stat)
        {
            # We set these down there automatically (we are faking quota
            # support to keep webdrive happy).
            next if $wanted_prop eq 'quota';
            next if $wanted_prop eq 'quotaused';
            next if $wanted_prop eq 'quota-available-bytes';
            next if $wanted_prop eq 'quota-used-bytes';
            next if $wanted_prop eq 'quota-assigned-bytes';

            my $prop = $doc->createElement("D:$wanted_prop");

            if($wanted_prop eq 'resourcetype')
            {
                if($stat->{$wanted_prop} eq 'collection')
                {
                    my $collection = $doc->createElement('D:collection');

                    $prop->addChild($collection);
                }
            }
            else
            {
                if(defined($stat->{$wanted_prop}))
                {
                    $prop->appendText($stat->{$wanted_prop});
                }
                else
                {
                    $prop->appendText('');
                }
            }

            $okprops->addChild($prop);
        }

        # Add quota information.  This doesn't appear to be in the WebDAV
        # spec, but if it's not here, WebDrive won't allow any uploads.
        #
        # Update: I found it in a proposal here:
        #
        # http://www.greenbytes.de/tech/webdav/draft-ietf-webdav-quota-07.html
        # 
        # But it doesn't say anything about quota, quotaused, or
        # quota-assigned-bytes - I found out that webdrive was looking for those
        # from its log file.
        my $quota                 = $doc->createElement('D:quota');
        my $quota_used            = $doc->createElement('D:quotaused');
        my $quota_available_bytes = $doc->createElement('D:quota-available-bytes');
        my $quota_used_bytes      = $doc->createElement('D:quota-used-bytes');
        my $quota_assigned_bytes  = $doc->createElement('D:quota-assigned-bytes');

        $quota->appendText('2000000000');
        $quota_used->appendText('0');
        $quota_available_bytes->appendText('2000000000');
        $quota_used_bytes->appendText('0');
        $quota_assigned_bytes->appendText('2000000000');

        $okprops->addChild($quota);
        $okprops->addChild($quota_used);
        $okprops->addChild($quota_available_bytes);
        $okprops->addChild($quota_used_bytes);
        $okprops->addChild($quota_assigned_bytes);

        if($okprops->hasChildNodes())
        {
            my $propstat = $doc->createElement('D:propstat');
            $propstat->addChild($okprops);

            my $stat = $doc->createElement('D:status');
            $stat->appendText('HTTP/1.1 200 OK');

            $propstat->addChild($stat);
            $resp->addChild($propstat);
        }
    }

    $r->send_http_header();
    $r->print($doc->toString(1));

    return OK;
}

#
# Parse an incoming PROPFIND request to see what information the client wants.
#
sub get_wanted_properties
{
    my ($self, $r) = @_;

    # Grab the content of the request so we can parse it and look for which
    # properties they are requesting.
    my $content = $self->get_request_content($r);

    # NSExpand expands namespaces so, xmlns:D eq '{DAV:}' in front of every
    # element in that namespace.
    my $xml;

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

    # Based on the requested path ($uri), figure out which module will
    # handle the request.  The modules must be subclasses of
    # Filesys::Virtual.
    my $module;
    my $path_handled;
    my %args;

    foreach my $mod (@{$self->{'handlers'}})
    {
        my $path = $mod->{'path'};

        if($uri =~ /^$path/)
        {
            $module       = $mod->{'module'};
            $path_handled = $path;
            %args         = %{$mod->{'args'}} if defined($mod->{'args'});
        }
    }

    my $handler = $module->new({
        root_path => $path_handled,
        cwd       => $uri,
        %args
    });

    return $handler;
}

1;
__END__

=head1 NAME

Apache::WebDAV - Extensible WebDAV server for Apache.

=head1 SYNOPSIS

  use Apache::WebDAV;

=head1 ABSTRACT

Write perl modules to handle file transfers through WebDAV.

=head1 DESCRIPTION

Apache::WebDAV is a WebDAV server implementation.  It was originally based on Net::DAV::Server (which isn't compatible with Apache), but has undergone significant architectural changes.  Apache::WebDAV can be used with a simple mod_perl handler and t...

It is also possible to use different Filesys::Virtual subclasses to respond to different paths under your WebDAV root.  This allows you to have some sections interact with the filesystem, others with a database, etc.

=head1 WebDAV Standards Compatibility

The WebDAV protocol is unclear and client behavior differs drastically.  During development of this module, the following clients were identified as targets for support:

 WebDrive  (windows)
 Transmit  (osx)
 Goliath   (osx)
 Cadaver   (linux)
 Konqueror (linux)
 HTTP::DAV (perl)

The MacOSX Finder is also supported, assuming your Filesys::Virtual subclass is fully and correctly implemented.  Specifically, you can't expect the Finder to "PUT" a file in one nice step, rather, it takes multiple requests and it's difficult to pro...

In addition, depending on your Filesys::Virtual subclass, of course, this module passes most of the WebDAV Litmus tests (http://www.webdav.org/neon/litmus/) without errors or warnings.  Specifically:

 OPTIONS for DAV: header 
 PUT, GET with byte comparison 
 MKCOL 
 DELETE (collections, non-collections) 
 COPY, MOVE using combinations of: 
  overwrite t/f 
  destination exists/doesn't exist 
  collection/non-collection

However, there is currently no support for LOCKING or PROPERTY MANIPULATION.

Finally, there are certain pieces of code in this module that purposefully break from the WebdAV protocol in order to support a specific client.  As of this writing, both Goliath and WebDrive require these hacks.  (Both are commented in the code.)

Microsoft Internet Explorer "Web Folders" do not seem to work and no effort has been made to figure out why.

Here is the output of the Litmus Test when running basic, copymove, and http:

    $ echo $TESTS
    basic copymove http
    lozier@ruggles:~$ litmus http://pg.ruggles:8080/ApacheDAV
    -> running `basic':
     0. init.................. pass
     1. begin................. pass
     2. options............... pass
     3. put_get............... pass
     4. put_get_utf8_segment.. pass
     5. mkcol_over_plain...... pass
     6. delete................ pass
     7. delete_null........... pass
     8. delete_fragment....... WARNING: DELETE removed collection resource with Request-URI including fragment; unsafe
        ...................... pass (with 1 warning)
     9. mkcol................. pass
    10. mkcol_again........... pass
    11. delete_coll........... pass
    12. mkcol_no_parent....... pass
    13. mkcol_with_body....... pass
    14. finish................ pass
    <- summary for `basic': of 15 tests run: 15 passed, 0 failed. 100.0%
    -> 1 warning was issued.
    -> running `copymove':
     0. init.................. pass
     1. begin................. pass
     2. copy_init............. pass
     3. copy_simple........... pass
     4. copy_overwrite........ pass
     5. copy_nodestcoll....... pass
     6. copy_cleanup.......... pass
     7. copy_coll............. pass
     8. move.................. pass
     9. move_coll............. pass
    10. move_cleanup.......... pass
    11. finish................ pass
    <- summary for `copymove': of 12 tests run: 12 passed, 0 failed. 100.0%
    -> running `http':
     0. init.................. pass
     1. begin................. pass
     2. expect100............. pass



( run in 1.310 second using v1.01-cache-2.11-cpan-b16cb0d3907 )