• • no additional binaries needed, just pure PHP code • • not necessarily bound to a single server or API • • easy to extend • • all needed bits included XML parser, HTTP header and c
Trang 1• Web-based Distributed Authoring and
Versioning
• • Goal: enable interoperability of tools for
distributed web authoring
• • Turns the web into a writable medium
• • Applies to all kinds of content - not just HTML and images
• • Based on extensions to HTTP
• • Uses XML for properties, control, status
• • RFC 2518 (Core) and RFC 3253 (DeltaV)
How does it work?
• • Layered on HTTP/1.1 using its extension
facilities
• • New methods, for example: COPY, MKCOL, PROPFIND, CHECKOUT
• • New headers
• • Some slight changes to existing methods
semantics
• • RFC 2518 ("core"): pretty straight-forward
Trang 2• • RFC 3253 (versioning): complex
A sample request
Request all metadata for a directory and its contents
PROPFIND /container/ HTTP/1.1
Host: www.foo.bar
Depth: 1
Content-Type: text/xml; charset="utf-8"
Content-Length:
<?xml version="1.0" ?>
<D:propfind xmlns:D="DAV:">
<D:allprop/>
</D:propfind>
Shortened response
HTTP/1.1 207 Multi-Status
Content-Type: text/xml; charset="utf-8"
Content-Length:
<?xml version="1.0" encoding="utf-8" ?>
<D:multistatus xmlns:D="DAV:">
<D:response>
<D:href>http://www.foo.bar/container/</D:href>
<D:propstat>
<D:prop>
<D:getcontentlength>12345</getcontentlength>
</D:prop>
<D:prop xmlns:R="http://www.foo.bar/boxschema/">
<R:bigbox>
<R:BoxType>Box type A</R:BoxType>
</R:bigbox>
<R:author>
Trang 3
Why PHP?
Why PHP? Why not just use
Apache mod_dav?
• • no additional binaries needed, just pure PHP code
• • not necessarily bound to a single server or API
• • easy to extend
• • all needed bits included (XML parser, HTTP header and content access )
The WebDAV base class
The abstract HTTP_WebDAV_Server base class
The actual PHP framework for writing a customized
WebDAV server is implemented as an abstract base class The class already takes care of most of the protocol specific stuff like:
Trang 4• • HTTP header parsing
• • XML parsing and generation
• • authentication
• • type conversions
• • status codes
• • lock checks
• • the OPTIONS reply
• • partial GET and PUT requests
• • known client 'issues'
• •
Extending the base class
Extending the base class requires that you add methods to it that map to WebDAV specific request methods These
methods receive and return all relevant information in the form of PHP arrays You do not have to deal with XML and header parsing / generation as this is already taken care of by the baseclass
Trang 5Possible methods
• • GET()
• • PUT()
• • COPY()
• • MOVE()
• • DELETE()
• • PROPFIND()
• • PROPPATCH()
• • LOCK()
• • UNLOCK()
• • CHECKLOCK()
• • CHECKAUTH()
WebDAV conformance
For a minimal Server
you only need to implement GET(), PUT() and PROPFIND() Such a minimal server is not at all compliant to the sepcs but may already work with some clients
For a DAV level 1 compliant server
you also need COPY(), MOVE(), DELETE() and PROPPATCH()
A DAV level 2 complient server
has to implement locking, so you also need LOCK(), UNLOCK() and
CHECKLOCK()
Trang 6A versioning server
as specified in RFC 3253 is beyond the current scope of the this PHP package
A WebDAV GET request can be handled similar to a normal HTTP GET request Just make sure that you always set
appropriate Content-Length: and Last-Modified: headers before
returning the actual content
The path of the requested resource is passed to GET() in the parameter element 'path':
<?php
function GET (& $param ) {
$fspath = $this -> base $param [ "path" ];
if ( file_exists ( $fspath )) {
header ( "Content-Type: " mime_content_type ( $fspath );
header ( "Last-Modified: " date ( "D, j M Y H:m:s " , file_mtime ( $fspath )) "GMT
" );
header ( "Content-Length: " filesize ( $fspath ));
Trang 7readfile ( $fspath );
return true ;
} else {
return false ;
}
}
?>
GET()
As an alternative you may just return a readable PHP stream together with size and modification time information from the GET() method By doing so you do not have to deal with HTTP header generation yourself and get support for partial
GET requests without taking further action as an additional benefit
<?php
function GET (& $param )
{
$fspath = $this -> base $param [ "path" ];
if ( file_exists ( $fspath )) {
$param [ 'mimetype' ] = mime_content_type ( $fspath );
$param [ 'mtime' ] = filemtime ( $fspath );
$param [ 'size' ] = filesize ( $fspath );
$param [ 'stream' ] = fopen ( $fspath , "r" );
Trang 8
return true ;
} else {
return false ;
}
}
?>
Note that no further error checking is needed on calling fopen()
here The base class will take appropriate action if the
returned stream is not a PHP resource or not readable
The HTTP PUT request method is used to write data to a
resource on the server The PUT() method is called by the base class with the following elements of its parameter array
filled:
• • 'path': the resource the received data should be put into
• • 'content_length': the number of bytes transfered
• • 'content_type': the content type of the data transfered
• • 'stream': a PHP stream you can read the actual data from
Trang 9• • 'ranges': an array of byte range specifications to be written on partial requests
As with the GET() method you may either handle a PUT request yourself or just return a writable stream and have the base class write to it
PUT()
<?php
function PUT (& $params ) {
$fspath = $this -> base $params [ "path" ];
if(!@ is_dir ( dirname ( $fspath ))) {
return "409 Conflict" ;
}
$new = ! file_exists ( $fspath );
Trang 10
$fp = fopen ( $fspath , "w" );
if( is_resource ( $fp )
&& is_resource ( $params [ "stream" ])) {
while(! feof ( $params [ "stream" ])) {
fwrite ( $fp , fread ( $params [ "stream" ], 4096 )); }
fclose ( $fp );
}
return $new ? "201 Created" : "204 No Content" ; }
?>
PUT() (cont.)
function PUT (& $params ) {
$fspath = $this -> base $params [ "path" ];
if(!@ is_dir ( dirname ( $fspath ))) {
return false ;
}
$options [ "new" ] = ! file_exists ( $fspath );
$fp = fopen ( $fspath , "w" );
return $fp ;
}
?>