commit ab22f3fb8f2d23170e49dc336b6b05c4cf6bab51
Author: Jan Dankert <develop@jandankert.de>
Date: Mon, 15 Apr 2019 23:02:33 +0200
moved from repository openrat-cms into this fresh new repository.
Diffstat:
CMS.class.php | | | 80 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
Client.class.php | | | 178 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
Logger.class.php | | | 140 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
README.md | | | 15 | +++++++++++++++ |
WebDAV.class.php | | | 1134 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dav.ini | | | 17 | +++++++++++++++++ |
dav.log | | | 126 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
dav.php | | | 112 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
index.php | | | 6 | ++++++ |
9 files changed, 1808 insertions(+), 0 deletions(-)
diff --git a/CMS.class.php b/CMS.class.php
@@ -0,0 +1,79 @@
+<?php
+
+define('CMS_READ' ,'GET' );
+define('CMS_WRITE' ,'POST');
+
+class CMS extends Client
+{
+ var $login = false;
+ var $token;
+
+ function login($user, $password,$dbid )
+ {
+
+ // Erster Request der Sitzung muss ein GET-Request sein.
+ // Hier wird auch der Token gelesen.
+ $result = $this->call(CMS_READ,'login','login' );
+
+ $result = $this->call(CMS_WRITE,'login','login',array('login_name'=>$user,'login_password'=>$password,'dbid'=>$dbid) );
+
+ if ( $result['success'] != 'true' ) {
+ throw new Exception( 'Login failed. '.print_r($result['notices'],true));
+ }
+ }
+
+
+ function projectlist()
+ {
+ $result = $this->call(CMS_READ,'projectlist','edit' );
+
+// Logger::debug( print_r($result,true) );
+ return( $result['output'] );
+ }
+
+
+ function project($projectid)
+ {
+ $result = $this->call(CMS_READ,'project','edit',array('id'=>$projectid) );
+
+ return( $result['output'] );
+ }
+
+ function folder($id)
+ {
+ $result = $this->call(CMS_READ,'folder','edit',array('id'=>$id) );
+
+ return( $result['output'] );
+ }
+
+ function page($id)
+ {
+ $result = $this->call(CMS_READ,'page','edit',array('id'=>$id) );
+
+ return( $result['output'] );
+ }
+
+ function link($id)
+ {
+ $result = $this->call(CMS_READ,'link','edit',array('id'=>$id) );
+
+ return( $result['output'] );
+ }
+
+ function file($id)
+ {
+ $result = $this->call(CMS_READ,'file','edit',array('id'=>$id) );
+
+ return( $result['output'] );
+ }
+
+ function filevalue($id)
+ {
+ $result = $this->call(CMS_READ,'file','show',array('id'=>$id) );
+
+ return( $result['output'] );
+ }
+
+}
+
+?>+
\ No newline at end of file
diff --git a/Client.class.php b/Client.class.php
@@ -0,0 +1,177 @@
+<?php
+
+
+class Client
+{
+ protected $action;
+ protected $subaction;
+ protected $cookies = array();
+ protected $useCookies = false;
+
+ protected $sessionName;
+ protected $sessionId;
+ protected $token;
+
+ protected $method; // GET oder POST
+
+ protected $responseHeader;
+
+
+ protected function call($method,$action,$subaction,$parameter=array())
+ {
+ global $config;
+ $error = '';
+ $status = '';
+
+ $errno = 0;
+ $errstr = '';
+
+ $host = $config['cms.host'];
+ $port = $config['cms.port'];
+ $path = $config['cms.path'];
+
+ // Vorbedingungen checken:
+ // Slash an Anfang und Ende?
+ if ( substr($path,-1 ) != '/' )
+ $path = $path.'/';
+ if ( substr($path,0,1 ) != '/' )
+ $path = '/'.$path;
+ $path .= '/api/';
+
+ // Methode: Fallback GET
+ if ( empty($method))
+ $method='GET';
+
+ // Die Funktion fsockopen() erwartet eine Protokollangabe (bei TCP optional, bei SSL notwendig).
+ if ( $port == '443' || @$config['ssl'] )
+ $prx_proto = 'ssl://'; // SSL
+ else
+ $prx_proto = 'tcp://'; // Default
+
+ $fp = fsockopen ($prx_proto.$host,$port, $errno, $errstr, 30);
+
+ if ( !$fp || !is_resource($fp) )
+ {
+ echo "Connection refused: '".$prx_proto.$host.':'.$port." - $errstr ($errno)";
+ }
+ else
+ {
+ $lb = "\r\n";
+ $http_get = $path;
+
+ $parameter += array('action'=>$action,'subaction'=>$subaction);
+ if ( $method=='POST')
+ $parameter += array('token'=>$this->token);
+
+ $parameterString = '';
+
+ foreach( $parameter as $name=>$value )
+ {
+ if ( !empty($parameterString) )
+ $parameterString .= '&';
+
+ $parameterString .= urlencode($name).'='.urlencode($value);
+ }
+
+ if ( $method == 'GET')
+ $http_get .= '?'.$parameterString;
+
+ $header = array();
+
+ $header[] = $method.' '.$http_get.' HTTP/1.0';
+ $header[] = 'Host: '.$host;
+ $header[] = 'Accept: application/php-serialized';
+
+ if ( $this->useCookies)
+ foreach( $this->cookies as $cookieName=>$cookieValue)
+ $header[] = 'Cookie: '.$cookieName.'='.$cookieValue;
+
+ if ( ! empty($this->sessionName))
+ $header[] = 'Cookie: '.$this->sessionName.'='.$this->sessionId;
+
+ if ( $method == 'POST' )
+ {
+ $header[] = 'Content-Type: application/x-www-form-urlencoded';
+ $header[] = 'Content-Length: '.strlen($parameterString);
+ }
+
+ $http_request = implode($lb,$header).$lb.$lb;
+
+ if ( $method == 'POST' )
+ {
+ $http_request .= $parameterString;
+ }
+ if (!is_resource($fp)) {
+ $error = 'Connection lost after connect: '.$prx_proto.$host.':'.$port;
+ return false;
+ }
+ fputs($fp, $http_request); // Die HTTP-Anfrage zum Server senden.
+
+ // Jetzt erfolgt das Auslesen der HTTP-Antwort.
+ $isHeader = true;
+
+ // RFC 1945 (Section 6.1) schreibt als Statuszeile folgendes Format vor
+ // "HTTP/" 1*DIGIT "." 1*DIGIT SP 3DIGIT SP
+ if (!is_resource($fp)) {
+ echo 'Connection lost during transfer: '.$host.':'.$port;
+ }
+ elseif (!feof($fp)) {
+ $line = fgets($fp,1028);
+ $status = substr($line,9,3);
+ }
+ else
+ {
+ echo 'Unexpected EOF while reading HTTP-Response';
+ }
+
+ $body='';
+ while (!feof($fp)) {
+ $line = fgets($fp,1028);
+ if ( $isHeader && trim($line)=='' ) // Leerzeile nach Header.
+ {
+ $isHeader = false;
+ }
+ elseif( $isHeader )
+ {
+ list($headerName,$headerValue) = explode(': ',$line) + array(1=>'');
+ $this->responseHeader[$headerName] = trim($headerValue);
+ }
+ else
+ {
+ $body .= $line;
+ }
+ }
+ fclose($fp); // Verbindung brav schlie�en.
+
+ foreach( $this->responseHeader as $headerName => $headerValue)
+ {
+ if ( $headerName == 'Set-Cookie' )
+ {
+ $parts = explode(';',$headerValue);
+ $payload = $parts[0];
+ list( $cookieName,$cookieValue) = explode('=',$payload);
+ {
+ $this->cookies[trim($cookieName)] = trim($cookieValue);
+ }
+ }
+ }
+
+ $result = unserialize($body);
+ if ( $result === false )
+ {
+ error_log('Not unserializable: '.$body);
+ throw new RuntimeException('The server response cannot be unserialized into a PHP array');
+ }
+ else
+ {
+ $this->sessionName = $result['session']['name'];
+ $this->sessionId = $result['session']['id'];
+ $this->token = $result['session']['token'];
+// var_dump($result);
+ return $result;
+ }
+
+ }
+ }
+}
+?>+
\ No newline at end of file
diff --git a/Logger.class.php b/Logger.class.php
@@ -0,0 +1,139 @@
+<?php
+// OpenRat Content Management System
+// Copyright (C) 2002-2012 Jan Dankert, cms@jandankert.de
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+
+define('DAV_LOG_LEVEL_TRACE',5 );
+define('DAV_LOG_LEVEL_DEBUG',4 );
+define('DAV_LOG_LEVEL_INFO' ,3 );
+define('DAV_LOG_LEVEL_WARN' ,2 );
+define('DAV_LOG_LEVEL_ERROR',1 );
+
+define('DAV_LOG_LEVEL', constant('DAV_LOG_LEVEL_'.strtoupper($config['log.level'])));
+
+
+/**
+ * Schreiben eines Eintrages in die Logdatei
+ *
+ * @author $Author$
+ * @version $Rev: $
+ * @package openrat.services
+ */
+class Logger
+{
+ /**
+ * Schreiben einer Trace-Meldung in die Logdatei
+ *
+ * @param message Log-Text
+ */
+ function trace( $message )
+ {
+ if ( DAV_LOG_LEVEL >= DAV_LOG_LEVEL_TRACE )
+ Logger::doLog( 'trace',$message );
+ }
+
+
+ /**
+ * Schreiben einer Debug-Meldung in die Logdatei
+ *
+ * @param message Log-Text
+ */
+ function debug( $message )
+ {
+ if ( DAV_LOG_LEVEL >= DAV_LOG_LEVEL_DEBUG )
+ Logger::doLog( 'debug',$message );
+ }
+
+
+ /**
+ * Schreiben einer Information in die Logdatei
+ *
+ * @param message Log-Text
+ */
+ function info( $message )
+ {
+ if ( DAV_LOG_LEVEL >= DAV_LOG_LEVEL_INFO )
+ Logger::doLog( 'TemplateEngineInfo',$message );
+ }
+
+
+ /**
+ * Schreiben einer Warnung in die Logdatei
+ *
+ * @param message Log-Text
+ */
+ function warn( $message )
+ {
+ if ( DAV_LOG_LEVEL >= DAV_LOG_LEVEL_WARN )
+ Logger::doLog( 'warn',$message );
+ }
+
+
+ /**
+ * Schreiben einer normalen Fehlermeldung in die Logdatei
+ *
+ * @param message Log-Text
+ */
+ function error( $message )
+ {
+ if ( DAV_LOG_LEVEL >= DAV_LOG_LEVEL_ERROR )
+ Logger::doLog( 'error',$message );
+ }
+
+
+ /**
+ * Schreiben der Meldung in die Logdatei
+ *
+ * @author $Author$
+ * @param facility Schwere dieses Logdatei-Eintrages (z.B. warning)
+ * @param message Log-Text
+ * @access private
+ */
+ function doLog( $facility,$message )
+ {
+ global $config;
+
+ $filename = $config['log.file'];
+
+ if ( empty($filename) )
+ return;
+
+ if ( ! is_writable($filename) )
+ throw new \LogicException( "logfile $filename is not writable by the server" );
+
+ $thisLevel = strtoupper($facility);
+
+ $text = "%time %level %host %action %text"; // Format der Logdatei
+
+ // Ersetzen von Variablen
+ $text = str_replace( '%host',getenv('REMOTE_ADDR'),$text );
+
+ $action = strtoupper($_SERVER['REQUEST_METHOD']);
+
+ $text = str_replace( '%level' ,str_pad($thisLevel,5),$text );
+ $text = str_replace( '%agent' ,getenv('HTTP_USER_AGENT'),$text );
+ $text = str_replace( '%action',str_pad($action,12),$text );
+ $text = str_replace( '%text' ,$message,$text );
+ $text = str_replace( '%time' ,date('M j H:i:s'),$text );
+ $text = str_replace( "\n" ,"\n ",$text );
+
+ // Schreiben in Logdatei
+ error_log( $text."\n",3,$filename );
+ }
+}
+
+?>+
\ No newline at end of file
diff --git a/README.md b/README.md
@@ -0,0 +1,14 @@
+
+WebDAV für OpenRat Content Management System
+===
+
+**The virtual CMS file system is accessable via a DAV client**
+
+WebDAV is specified in [RFC 2518](http://www.ietf.org/rfc/rfc2518.txt).
+
+Implemented is DAV level 1 (without Locks).
+
+Following impliciments:
+- Login only with username/password
+- Only 1 database
+- DAV-client must support cookies (the most clients should)+
\ No newline at end of file
diff --git a/WebDAV.class.php b/WebDAV.class.php
@@ -0,0 +1,1134 @@
+<?php
+
+
+class WebDAV
+{
+ /**
+ * CMS-Client
+ * @var CMS
+ */
+ private $client;
+
+ // Zahlreiche Instanzvariablen, die im Konstruktor
+ // beim Zerlegen der Anfrag gef�llt werden.
+ var $defaultSubAction = 'show';
+ var $database;
+ var $depth;
+ var $projectid;
+ var $objectid;
+ var $filename;
+ var $pathnames = array();
+ var $uri;
+ var $headers;
+ var $requestType;
+ var $request;
+ var $destination = null;
+ var $fullSkriptName;
+ var $create;
+ var $readonly;
+ var $maxFileSize;
+ var $webdav_conf;
+ var $overwrite = false;
+
+ private $httpMethod;
+
+
+ /**
+ * Im Kontruktor wird der Request analysiert und ggf. eine Authentifzierung
+ * durchgefuehrt. Anschließend wird eine interne Methode mit dem Namen davXXX() aufgerufen.
+ */
+ function __construct()
+ {
+ global $config;
+
+ $this->httpMethod = strtoupper($_SERVER['REQUEST_METHOD']);
+
+ Logger::trace( 'WEBDAV request' );
+
+ if ( $config['dav.compliant_to_redmond'] )
+ header('MS-Author-Via: DAV' ); // Extrawurst fuer MS-Clients.
+
+ if ( $config['dav.expose_openrat'] )
+ header('X-Dav-powered-by: OpenRat CMS'); // Bandbreite verschwenden :)
+
+// Logger::trace( 'WEBDAV: URI='.$_SERVER['REQUEST_URI']);
+
+ if ( !$config['dav.enable'])
+ {
+ Logger::warn( 'WEBDAV is disabled by configuration' );
+
+ $this->httpStatus('403 Forbidden');
+ exit;
+ }
+
+ $this->create = $config['dav.create'];
+ $this->readonly = $config['dav.readonly'];
+ $this->maxFileSize = $config['cms.max_file_size'];
+
+ $this->headers = getallheaders();
+ /* DAV compliant servers MUST support the "0", "1" and
+ * "infinity" behaviors. By default, the PROPFIND method without a Depth
+ * header MUST act as if a "Depth: infinity" header was included. */
+ if ( !isset($this->headers['Depth']) )
+ $this->depth = 1;
+ elseif ( strtolower($this->headers['Depth'])=='infinity')
+ $this->depth = 1;
+ else
+ $this->depth = intval($this->headers['Depth']);
+
+ if ( isset($this->headers['Destination']) )
+ $this->destination = $this->headers['Destination'];
+
+ if ( isset($this->headers['Overwrite']) )
+ $this->overwrite = $this->headers['Overwrite'] == 'T';
+
+
+ session_start();
+ if ( !empty($_SESSION['DAV_CLIENT']) )
+ $this->client = $_SESSION['DAV_CLIENT'];
+ else
+ {
+ $this->client = new CMS();
+ $_SESSION['DAV_CLIENT'] = $this->client;
+ }
+
+ if ( $this->client->login )
+ {
+ // Benutzer ist bereits im CMS eingeloggt.
+ }
+ else
+ {
+ // Login
+ if ( $this->httpMethod != 'OPTIONS' ) // Bei OPTIONS kein Login anfordern
+ {
+ if ( isset($_SERVER['PHP_AUTH_USER']) )
+ {
+
+ $username = $_SERVER['PHP_AUTH_USER'];
+ $pass = $_SERVER['PHP_AUTH_PW' ];
+
+ try {
+ $this->client->login($username, $pass, $config['cms.database']);
+ }
+ catch( Exception $e )
+ {
+ $this->httpStatus('401 Unauthorized');
+ header('WWW-Authenticate: Basic realm="'.$config['dav.realm'].'"');
+ echo 'Failed login for user '.$username;
+ exit;
+ }
+ }
+ elseif ( $config['dav.anonymous'])
+ {
+ $username = $config['cms.user'];
+ $pass = $config['cms.password'];
+
+ $loginOk = $this->client->login($username, $pass, $config['cms.database']);
+ if ( !$loginOk ) {
+ $this->httpStatus('500 Internal Server Error');
+ echo 'Could not authenticate user '.$username;
+ exit;
+ }
+ }
+ else
+ {
+ // Client ist nicht angemeldet, daher wird nun die
+ // Authentisierung angefordert.
+ header('WWW-Authenticate: Basic realm="'.$config['dav.realm'].'"');
+ $this->httpStatus('401 Unauthorized');
+ echo 'Authentification required for '.$config['dav.realm'];
+ exit;
+
+ }
+ }
+ else
+ {
+ return; //
+ }
+ }
+
+
+ $scriptName = $_SERVER['SCRIPT_NAME'];
+
+// if ( substr($scriptName,-10) == '/index.php' )
+// $scriptName = substr($scriptName,0,-10);
+
+ $this->fullSkriptName = 'http://'.$_SERVER['HTTP_HOST'].$scriptName.'/';
+
+ // URL parsen.
+ $uri = substr($_SERVER['REQUEST_URI'],strlen($scriptName));
+
+ $uri = $this->parseURI( $uri );
+ $this->requestType = $uri['type' ];
+ $this->objectid = $uri['objectid' ];
+ $this->projectid = $uri['projectid'];
+
+// $this->fullSkriptName .= implode('/',$uri['path']);
+
+ if ( $this->requestType == 'folder' )
+ $this->fullSkriptName .= '/';
+
+ /*
+ * Verzeichnisse muessen mit einem '/' enden. Falls nicht, Redirect aussfuehren.
+ *
+ * RFC 2518, 5.2 Collection Resources, Page 11:
+ * "For example, if a client invokes a
+ * method on http://foo.bar/blah (no trailing slash), the resource
+ * http://foo.bar/blah/ (trailing slash) may respond as if the operation
+ * were invoked on it, and should return a content-location header with
+ * http://foo.bar/blah/ in it. In general clients SHOULD use the "/"
+ * form of collection names."
+ */
+ if ( $this->request == 'folder' &&
+ $_GET['subaction'] == 'get' &&
+ substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1 ) != '/' )
+ {
+ Logger::debug( 'Redirecting lame client to slashyfied URL' );
+
+ header('HTTP/1.1 302 Moved Temporarily');
+ header('Location: '.$_SERVER['REQUEST_URI'].'/');
+ exit;
+ }
+
+ // Falls vorhanden, den "Destination"-Header parsen.
+ if ( isset($_SERVER['HTTP_DESTINATION']) )
+ {
+ $destUri = parse_url( $_SERVER['HTTP_DESTINATION'] );
+
+ $uri = substr($destUri['path'],strlen($_SERVER['SCRIPT_NAME'])+$sos);
+
+ // URL parsen.
+ $this->destination = $this->parseURI( $uri );
+ }
+
+ // Den Request-BODY aus der Standardeingabe lesen.
+ $this->request = implode('',file('php://input'));
+ }
+
+ /**
+ * HTTP-Methode OPTIONS.<br>
+ * <br>
+ * Es werden die verfuegbaren Methoden ermittelt und ausgegeben.
+ */
+ public function davOPTIONS()
+ {
+ header('DAV: 1'); // Wir haben DAV-Level 1.
+ header('Allow: '.implode(', ',$this->allowed_methods()) );
+
+ Logger::trace('OPTIONS: '.'Allow: '.implode(', ',$this->allowed_methods()));
+
+ $this->httpStatus( '200 OK' );
+ }
+
+
+
+
+
+ /**
+ * WebDav-HEAD-Methode.
+ */
+ public function davHEAD()
+ {
+ if ( $this->objectid == null )
+ {
+ $this->httpStatus( '404 Not Found' );
+ }
+ elseif ( $this->requestType == 'folder' )
+ {
+ $this->httpStatus( '200 OK' );
+ }
+ elseif( $this->obj->isPage )
+ {
+ $this->httpStatus( '200 OK' );
+ }
+ elseif( $this->obj->isLink )
+ {
+ $this->httpStatus( '200 OK' );
+ }
+ elseif( $this->obj->isFile )
+ {
+ $this->httpStatus( '200 OK' );
+ }
+ }
+
+
+
+ /**
+ * WebDav-GET-Methode.
+ * Die gew�nschte Datei wird geladen und im HTTP-Body mitgeliefert.
+ */
+ public function davGET()
+ {
+ switch( $this->requestType )
+ {
+ case 'root':
+ case 'folder':
+ $this->getDirectoryIndex();
+ break;
+
+ case 'page':
+ $this->httpStatus( '200 OK' );
+ header('Content-Type: text/html');
+
+ echo '<html><head><title>OpenRat WEBDAV Access</title></head>';
+ echo '<body>';
+ echo '<h1>'.$this->requestType.'</h1>';
+ echo '<pre>';
+ echo 'No Content available';
+ echo '</pre>';
+ echo '</body>';
+ echo '</html>';
+ break;
+
+ case 'link':
+ $this->httpStatus( '200 OK' );
+
+ header('Content-Type: text/plain');
+
+ $link = $this->client->link( $this->objectid );
+ echo 'url: ' .$link['url'] ."\n";
+ echo 'target-id: '.$link['linkedObjectId']."\n";
+
+ break;
+
+ case 'file':
+ $this->httpStatus( '200 OK' );
+
+ $file = $this->client->file ( $this->objectid );
+ $filevalue = $this->client->filevalue( $this->objectid );
+
+ header('Content-Type: '.$file['mimetype']);
+ header('X-File-Id: ' .$this->objectid );
+
+ // Angabe Content-Disposition
+ // - Bild soll "inline" gezeigt werden
+ // - Dateiname wird benutzt, wenn der Browser das Bild speichern moechte
+ header('Content-Disposition: inline; filename='.$file['filename'].'.'.$file['extension'] );
+ header('Content-Transfer-Encoding: binary' );
+ header('Content-Description: '.$file['filename'].'.'.$file['extension'] );
+
+ // Groesse des Bildes in Bytes
+ // Der Browser hat so die Moeglichkeit, einen Fortschrittsbalken zu zeigen
+ header('Content-Length: '.$file['size'] );
+
+ echo base64_decode( $filevalue['value'] );
+
+ break;
+ }
+ }
+
+
+
+ /**
+ * Erzeugt ein Unix-�hnliche Ausgabe des Verzeichnisses als HTML.
+ */
+ private function getDirectoryIndex()
+ {
+ $this->httpStatus( '200 OK' );
+
+ // Verzeichnis ausgeben
+ header('Content-Type: text/html');
+ $nl = "\n";
+
+
+
+
+ $titel = 'Index of '.htmlspecialchars($this->fullSkriptName);
+ $format = "%15s %-19s %-s\n";
+
+ echo '<html><head><title>'.$titel.'</title></head>';
+ echo '<body>';
+ echo '<h1>'.$titel.'</h1>'.$nl;
+ echo '<pre>';
+
+ printf($format, "Size", "Last modified", "Filename");
+
+
+ switch( $this->requestType )
+ {
+ case 'root': // Projektliste
+
+ $result = $this->client->projectlist();
+ $projects = $result['projects'];
+ foreach( $projects as $projectid=>$p )
+ {
+ echo '<a href="'.$p['name'].'">'.$p['name'].'</a>'.$nl;
+ }
+ break;
+
+ case 'folder': // Verzeichnisinhalt
+
+ $folder = $this->client->folder( $this->objectid );
+
+ foreach( $folder['object'] as $object )
+ {
+
+ printf($format,
+ number_format(1),
+ strftime("%Y-%m-%d %H:%M:%S",$object['date'] ),
+ '<a href="'.$object['filename'].'">'.$object['filename'].'</a>');
+ echo $nl;
+
+ }
+ }
+
+ echo '</pre>';
+ echo '</body>';
+ echo '</html>';
+ }
+
+
+
+ /**
+ * Die Methode LOCK sollte garnicht aufgerufen werden, da wir nur
+ * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br>
+ * <br>
+ * Ausgabe von HTTP-Status 412 (Precondition failed)
+ */
+ function davLOCK()
+ {
+ $this->httpStatus('412 Precondition failed');
+ $this->davOPTIONS();
+ }
+
+
+
+ /**
+ * Die Methode UNLOCK sollte garnicht aufgerufen werden, da wir nur
+ * Dav-Level 1 implementieren und dies dem Client auch mitteilen.<br>
+ * <br>
+ * Ausgabe von HTTP-Status 412 (Precondition failed)
+ */
+ public function davUNLOCK()
+ {
+ $this->httpStatus('412 Precondition failed');
+ $this->davOPTIONS();
+ }
+
+
+
+ /**
+ * Die Methode POST ist bei WebDav nicht sinnvoll.<br>
+ * <br>
+ * Ausgabe von HTTP-Status 405 (Method Not Allowed)
+ */
+ public function davPOST()
+ {
+ // Die Methode POST ist bei Webdav nicht sinnvoll.
+ $this->httpStatus('405 Method Not Allowed' );
+ }
+
+
+
+ /**
+ * Verzeichnis anlegen.
+ */
+ public function davMKCOL()
+ {
+
+ if ( !empty($this->request) )
+ {
+ $this->httpStatus('415 Unsupported Media Type' ); // Kein Body erlaubt
+ }
+ elseif ( $this->readonly )
+ {
+ $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt
+ }
+ elseif ( !$this->folder->hasRight( ACL_CREATE_FOLDER ) )
+ {
+ $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht
+ }
+ elseif ( $this->obj == null )
+ {
+ // Die URI ist noch nicht vorhanden
+ $f = new Folder();
+ $f->filename = basename($this->fullSkriptName);
+ $f->parentid = $this->folder->objectid;
+ $f->projectid = $this->project->projectid;
+ $f->add();
+ $this->httpStatus('201 Created');
+ }
+ else
+ {
+ // MKCOL ist nicht moeglich, wenn die URI schon existiert.
+ Logger::warn('MKCOL-Request to an existing resource');
+ $this->httpStatus('405 Method Not Allowed' );
+ }
+ }
+
+
+
+ /**
+ * Objekt l�schen.
+ */
+ public function davDELETE()
+ {
+ if ( $this->readonly )
+ {
+ $this->httpStatus('403 Forbidden' ); // Kein Schreibzugriff erlaubt
+ }
+ else
+ {
+ if ( $this->obj == null )
+ {
+ // Nicht existente URIs kann man auch nicht loeschen.
+ $this->httpStatus('404 Not Found' );
+ }
+ elseif ( ! $this->obj->hasRight( ACL_DELETE ) )
+ {
+ $this->httpStatus('403 Forbidden' ); // Benutzer darf die Resource nicht loeschen
+ }
+ elseif ( $this->obj->isFolder )
+ {
+ $f = new Folder( $this->obj->objectid );
+ $f->deleteAll();
+ $this->httpStatus( true ); // OK
+ Logger::debug('Deleted folder with id '.$this->obj->objectid );
+ }
+ elseif ( $this->obj->isFile )
+ {
+ $f = new File( $this->obj->objectid );
+ $f->delete();
+ $this->httpStatus( true ); // OK
+ }
+ elseif ( $this->obj->isPage )
+ {
+ $p = new Page( $this->obj->objectid );
+ $p->delete();
+ $this->httpStatus( true ); // OK
+ }
+ elseif ( $this->obj->isLink )
+ {
+ $l = new Link( $this->obj->objectid );
+ $l->delete();
+ $this->httpStatus( true ); // OK
+ }
+
+ }
+ }
+
+
+
+ /**
+ * Kopieren eines Objektes.<br>
+ * Momentan ist nur das Kopieren einer Datei implementiert.<br>
+ * Das Kopieren von Ordnern, Verkn�pfungen und Seiten ist nicht moeglich.
+ */
+ public function davCOPY()
+ {
+ if ( $this->readonly || !$this->create )
+ {
+ error_log('WEBDAV: COPY request, but readonly or no creating');
+ $this->httpStatus('405 Not Allowed' );
+ }
+ elseif( $this->obj == null )
+ {
+ // Was nicht da ist, laesst sich auch nicht verschieben.
+ error_log('WEBDAV: COPY request, but Source not found');
+ $this->httpStatus('405 Not Allowed' );
+ }
+ elseif ( $this->destination == null )
+ {
+ error_log('WEBDAV: COPY request, but no "Destination:"-Header');
+ // $this->httpStatus('405 Not Allowed' );
+ $this->httpStatus('412 Precondition failed');
+ }
+ else
+ {
+ // URL parsen.
+ $dest = $this->destination;
+ $destinationProject = $dest['project'];
+ $destinationFolder = $dest['folder' ];
+ $destinationObject = $dest['object' ];
+
+ if ( $dest['type'] != 'object' )
+ {
+ Logger::debug('WEBDAV: COPY request, but "Destination:"-Header mismatch');
+ $this->httpStatus('405 Not Allowed');
+ }
+ elseif ( $this->project->projectid != $destinationProject->projectid )
+ {
+ // Kopieren in anderes Projekt nicht moeglich.
+ Logger::debug('WEBDAV: COPY request denied, project does not match');
+ $this->httpStatus('403 Forbidden');
+ }
+ elseif ( $destinationObject != null )
+ {
+ Logger::debug('WEBDAV: COPY request denied, Destination exists. Overwriting is not supported');
+ $this->httpStatus('403 Forbidden');
+ }
+ elseif ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) )
+ {
+ $this->httpStatus('403 Forbidden' ); // Benutzer darf das nicht
+ }
+ elseif ( is_object($destinationObject) && $destinationObject->isFolder)
+ {
+ Logger::debug('WEBDAV: COPY request denied, Folder-Copy not implemented');
+ $this->httpStatus('405 Not Allowed');
+ }
+ elseif ( is_object($destinationObject) && $destinationObject->isLink)
+ {
+ Logger::debug('WEBDAV: COPY request denied, Link copy not implemented');
+ $this->httpStatus('405 Not Allowed');
+ }
+ elseif ( is_object($destinationObject) && $destinationObject->isPage)
+ {
+ Logger::debug('WEBDAV: COPY request denied, Page copy not implemented');
+ $this->httpStatus('405 Not Allowed');
+ }
+ else
+ {
+ $f = new File();
+ $f->filename = basename($_SERVER['HTTP_DESTINATION']);
+ $f->name = '';
+ $f->parentid = $destinationFolder->objectid;
+ $f->projectid = $this->project->projectid;
+ $f->add();
+ $f->copyValueFromFile( $this->obj->objectid );
+
+ Logger::debug('WEBDAV: COPY request accepted' );
+ // Objekt wird in anderen Ordner kopiert.
+ $this->httpStatus('201 Created' );
+ }
+ }
+
+ }
+
+
+
+ /**
+ * Verschieben eines Objektes.<br>
+ * <br>
+ * Folgende Operationen sind m�glich:<br>
+ * - Unbenennen eines Objektes (alle Typen)<br>
+ * - Verschieben eines Objektes (alle Typen) in einen anderen Ordner.<br>
+ */
+ public function davMOVE()
+ {
+ if ( $this->readonly )
+ {
+ $this->httpStatus('403 Forbidden - Readonly Mode' ); // Schreibgeschuetzt
+ }
+ elseif ( !$this->create )
+ {
+ $this->httpStatus('403 Forbidden - No creation' ); // Schreibgeschuetzt
+ }
+ elseif( $this->obj == null )
+ {
+ // Was nicht da ist, laesst sich auch nicht verschieben.
+ $this->httpStatus('404 Not Found' );
+ }
+ elseif( is_object($this->obj) && ! $this->obj->hasRight( ACL_WRITE ) )
+ {
+ // Was nicht da ist, laesst sich auch nicht verschieben.
+ Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden');
+ $this->httpStatus('403 Forbidden' );
+ }
+ elseif ( $this->destination == null )
+ {
+ Logger::error('WEBDAV: MOVE request, but no "Destination:"-Header');
+ // $this->httpStatus('405 Not Allowed' );
+ $this->httpStatus('412 Precondition failed');
+ }
+ else
+ {
+ $dest = $this->destination;
+ $destinationProject = $dest['project'];
+ $destinationFolder = $dest['folder' ];
+ $destinationObject = $dest['object' ];
+
+ if ( $dest['type'] != 'object' )
+ {
+ Logger::debug('WEBDAV: MOVE request, but "Destination:"-Header mismatch');
+ $this->httpStatus('405 Not Allowed');
+ return;
+ }
+
+ if ( is_object($destinationFolder) && ! $destinationFolder->hasRight( ACL_CREATE_FILE ) )
+ {
+ Logger::error('Source '.$this->obj->objectid.' is not writable: Forbidden');
+ $this->httpStatus('403 Forbidden' );
+ }
+
+ if ( $destinationObject != null )
+ {
+ Logger::debug('WEBDAV: MOVE request denied, destination exists');
+ $this->httpStatus('412 Precondition Failed');
+ return;
+ }
+
+ if ( $this->project->projectid != $destinationProject->projectid )
+ {
+ // Verschieben in anderes Projekt nicht moeglich.
+ Logger::debug('WEBDAV: MOVE request denied, project does not match');
+ $this->httpStatus('405 Not Allowed');
+ return;
+ }
+
+ if ( $this->folder->objectid == $destinationFolder->objectid )
+ {
+ Logger::debug('WEBDAV: MOVE request accepted, object renamed');
+ // Resource bleibt in gleichem Ordner.
+ $this->obj->filename = basename($_SERVER['HTTP_DESTINATION']);
+ $this->obj->objectSave(false);
+ $this->httpStatus('201 Created' );
+ return;
+ }
+
+ if ( $destinationFolder->isFolder )
+ {
+ Logger::debug('WEBDAV: MOVE request accepted, Destination: '.$destinationFolder->filename );
+ // Objekt wird in anderen Ordner verschoben.
+ $this->obj->setParentId( $destinationFolder->objectid );
+ $this->httpStatus('201 Created' );
+ return;
+ }
+
+ Logger::warn('WEBDAV: MOVE request failed' );
+ $this->httpStatus('500 Internal Server Error' );
+ }
+ }
+
+
+
+ /**
+ * Anlegen oder �berschreiben Dateien �ber PUT.<br>
+ * Dateien k�nnen neu angelegt und �berschrieben werden.<br>
+ * <br>
+ * Seiten k�nnen nicht �berschrieben werden. Wird versucht,
+ * eine Seite mit PUT zu �berschreiben, wird der Status "405 Not Allowed" gemeldet.<br>
+ */
+ public function davPUT()
+ {
+ // TODO: 409 (Conflict) wenn �bergeordneter Ordner nicht da.
+
+ if ( $config['readonly'] )
+ {
+ $this->httpStatus('405 Not Allowed' );
+ }
+ elseif ( strlen($this->request) > $this->maxFileSize*1000 )
+ {
+ // Maximale Dateigroesse ueberschritten.
+ // Der Status 207 "Zuwenig Speicherplatz" passt nicht ganz, aber fast :)
+ $this->httpStatus('507 Insufficient Storage' );
+ }
+ elseif ( $this->obj == null )
+ {
+ // Neue Datei anlegen
+ if ( !$config['create'] )
+ {
+ Logger::warn('WEBDAV: Creation of files not allowed by configuration' );
+ $this->httpStatus('405 Not Allowed' );
+ }
+
+ if ( ! $this->folder->hasRight( ACL_CREATE_FILE ) )
+ {
+ $this->httpStatus('403 Forbidden');
+ return;
+ }
+
+ $file = new File();
+ $file->filename = basename($this->fullSkriptName);
+ $file->extension = '';
+ $file->size = strlen($this->request);
+ $file->parentid = $this->folder->objectid;
+ $file->projectid = $this->project->projectid;
+ $file->value = $this->request;
+ $file->add();
+ $this->httpStatus('201 Created');
+ return;
+ }
+ elseif ( $this->obj->isFile )
+ {
+ if ( ! $this->obj->hasRight( ACL_WRITE ) )
+ {
+ Logger::debug('PUT failed, parent folder not writable by user' );
+ $this->httpStatus('403 Forbidden');
+ return;
+ }
+
+ // Bestehende Datei ueberschreiben.
+ $file = new File( $this->obj->objectid );
+ $file->saveValue( $this->request );
+ $file->setTimestamp();
+ $this->httpStatus('204 No Content');
+ Logger::debug('PUT ok, file is created' );
+ return;
+ }
+ elseif ( $this->obj->isFolder )
+ {
+ Logger::error('PUT on folder is not supported, use PROPFIND. Lame client?' );
+ $this->httpStatus('405 Not Allowed' );
+ }
+ else
+ {
+ // Fuer andere Objekttypen (Links, Seiten) ist kein PUT moeglich.
+ Logger::warn('PUT only available for files. Pages and links are ignored' );
+ $this->httpStatus('405 Not Allowed' );
+ }
+ }
+
+
+
+ /**
+ * WebDav-Methode PROPFIND.
+ *
+ * Diese Methode wird
+ * - beim Ermitteln von Verzeichnisinhalten und
+ * - beim Ermitteln von Metainformationen zu einer Datei
+ * verwendet.
+ *
+ * Das Ergebnis wird in einer XML-Zeichenkette geliefert.
+ */
+ public function davPROPFIND()
+ {
+ switch( $this->requestType )
+ {
+ case 'root': // Projektliste
+
+ $inhalte = array();
+
+ $objektinhalt = array();
+ $z = 30*365.25*24*60*60;
+ $objektinhalt['createdate' ] = $z;
+ $objektinhalt['lastchangedate'] = $z;
+ $objektinhalt['size' ] = 1;
+ $objektinhalt['name' ] = $this->fullSkriptName;
+ $objektinhalt['displayname' ] = '';
+ $objektinhalt['type'] = 'folder';
+
+ $inhalte[] = $objektinhalt;
+
+ $result = $this->client->projectlist();
+ $projects = $result['projects'];
+ foreach( $projects as $projectid=>$p )
+ {
+ $objektinhalt = array();
+ $objektinhalt['createdate' ] = TIME_20000101;
+ $objektinhalt['lastchangedate'] = TIME_20000101;
+ $objektinhalt['size' ] = 1;
+ $objektinhalt['name' ] = $this->fullSkriptName.$p['name'].'/';
+ $objektinhalt['displayname' ] = $p['name'];
+ $objektinhalt['type'] = 'folder';
+ $inhalte[] = $objektinhalt;
+ }
+
+ $this->multiStatus( $inhalte );
+ break;
+
+ case 'folder': // Verzeichnisinhalt
+
+ $folder = $this->client->folder( $this->objectid );
+
+ $inhalte = array();
+
+ $objektinhalt = array();
+ $objektinhalt['createdate' ] = $folder['properties']['create_date'];
+ $objektinhalt['lastchangedate'] = $folder['properties']['lastchange_date'];
+ $objektinhalt['name' ] = $this->fullSkriptName;
+ $objektinhalt['displayname' ] = $folder['properties']['filename'];
+ $objektinhalt['type' ] = 'folder';
+ $objektinhalt['size' ] = 0;
+
+ $inhalte[] = $objektinhalt;
+
+ if ( $this->depth > 0 )
+ {
+
+ foreach( $folder['object'] as $object )
+ {
+ $objektinhalt = array();
+ $objektinhalt['createdate' ] = $object['date'];
+ $objektinhalt['lastchangedate'] = $object['date'];
+ $objektinhalt['displayname' ] = $object['filename'];
+
+ switch( $object['type'] )
+ {
+ case 'folder':
+ $objektinhalt['name'] = $this->fullSkriptName.$object['filename'].'/';
+ $objektinhalt['type'] = 'folder';
+ $objektinhalt['size'] = 0;
+ $inhalte[] = $objektinhalt;
+ break;
+ case 'file':
+ $objektinhalt['name'] = $this->fullSkriptName.$object['filename'];
+ $objektinhalt['type'] = 'file';
+ $objektinhalt['size'] = $object['size'];
+ $objektinhalt['mime'] = 'application/x-non-readable';
+ $inhalte[] = $objektinhalt;
+ break;
+ case 'link':
+ $objektinhalt['name'] = $this->fullSkriptName.$object['filename'];
+ $objektinhalt['type'] = 'file';
+ $objektinhalt['size'] = 0;
+ $objektinhalt['mime'] = 'application/x-non-readable';
+ $inhalte[] = $objektinhalt;
+ break;
+ case 'page':
+ $objektinhalt['name'] = $this->fullSkriptName.$object['filename'];
+ $objektinhalt['type'] = 'file';
+ $objektinhalt['size'] = 0;
+ $inhalte[] = $objektinhalt;
+ break;
+ default:
+ }
+ }
+ }
+ $this->multiStatus( $inhalte );
+ break;
+
+ case 'page':
+ $page = $this->client->page( $objectid );
+ $prop = $page['properties'];
+ $objektinhalt = array();
+ $objektinhalt['name'] = $this->fullSkriptName.'/'.$prop['filename'].'/';
+ $objektinhalt['displayname'] = $prop['filename'];
+ $objektinhalt['createdate' ] = $prop['date'];
+ $objektinhalt['lastchangedate'] = $prop['date'];
+
+ $objektinhalt['size' ] = 0;
+ $objektinhalt['type' ] = 'file';
+ break;
+
+ case 'file':
+ $file = $this->client->file( $objectid );
+ $objektinhalt = array();
+ $objektinhalt['name'] = $this->fullSkriptName.'/'.$file['filename'].'/';
+ $objektinhalt['displayname'] = $file['filename'];
+ $objektinhalt['createdate' ] = $file['date'];
+ $objektinhalt['lastchangedate'] = $file['date'];
+
+ $objektinhalt['size' ] = $file['size'];
+ $objektinhalt['type' ] = 'file';
+
+ break;
+
+ case 'link':
+
+ $link = $this->client->link( $objectid );
+
+ $objektinhalt = array();
+ $objektinhalt['name'] = $this->fullSkriptName.'/'.$link['filename'].'/';
+ $objektinhalt['displayname'] = $link['filename'];
+ $objektinhalt['createdate' ] = $link['date'];
+ $objektinhalt['lastchangedate'] = $link['date'];
+
+ $objektinhalt['size' ] = 0;
+ $objektinhalt['type' ] = 'file';
+
+
+ $this->multiStatus( array($objektinhalt) );
+
+ break;
+
+ default:
+ Logger::warn('Internal Error, unknown request type: '. $this->requestType);
+ $this->httpStatus('500 Internal Server Error');
+ }
+ }
+
+
+ /**
+ * Webdav-Methode PROPPATCH ist nicht implementiert.
+ */
+ public function davPROPPATCH()
+ {
+ // TODO: Multistatus erzeugen.
+ // Evtl. ist '409 Conflict' besser?
+ $this->httpStatus('405 Not Allowed');
+ }
+
+
+ /**
+ * Erzeugt einen Multi-Status.
+ * @access private
+ */
+ private function multiStatus( $files )
+ {
+ $this->httpStatus('207 Multi-Status');
+ header('Content-Type: text/xml; charset=utf-8');
+
+ $response = '';
+ $response .= '<?xml version="1.0" encoding="utf-8" ?>';
+ $response .= '<d:multistatus xmlns:d="DAV:">';
+
+ foreach( $files as $file )
+ $response .= $this->getResponse( $file['name'],$file );
+
+ $response .= '</d:multistatus>';
+
+ $response = utf8_encode($response);
+
+ header('Content-Length: '.strlen($response));
+ Logger::debug('Multistatus: '.$response);
+ echo $response;
+ }
+
+
+ /**
+ * Erzeugt ein "response"-Element, welches in ein "multistatus"-element verwendet werden kann.
+ */
+ private function getResponse( $file,$options )
+ {
+ // TODO: Nur angeforderte Elemente erzeugen.
+ $response = '';
+ $response .= '<d:response>';
+ $response .= '<d:href>'.$file.'</d:href>';
+ $response .= '<d:propstat>';
+ $response .= '<d:prop>';
+ // $response .= '<d:source></d:source>';
+ $response .= '<d:creationdate>'.date('r',$options['createdate']).'</d:creationdate>';
+ $response .= '<d:displayname>'.$options['displayname'].'</d:displayname>';
+ $response .= '<d:getcontentlength>'.$options['size'].'</d:getcontentlength>';
+ $response .= '<d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">'.date('r',$options['lastchangedate']).'</d:getlastmodified>';
+
+ if ( $options['type'] == 'folder')
+ $response .= '<d:resourcetype><d:collection/></d:resourcetype>';
+ else
+ $response .= '<d:resourcetype />';
+
+ $response .= '<d:categories />';
+ $response .= '<d:fields></d:fields>';
+
+
+
+// $response .= '<d:getcontenttype>text/html</d:getcontenttype>';
+// $response .= '<d:getcontentlength />';
+// $response .= '<d:getcontentlanguage />';
+// $response .= '<d:executable />';
+// $response .= '<d:resourcetype>';
+// $response .= '<d:collection />';
+// $response .= '</d:resourcetype>';
+// $response .= '<d:getetag />';
+
+ $response .= '</d:prop>';
+ $response .= '<d:status>HTTP/1.1 200 OK</d:status>';
+ $response .= '</d:propstat>';
+ $response .= '</d:response>';
+
+ return $response;
+ }
+
+
+
+ /**
+ * URI parsen.
+ */
+ private function parseURI( $uri )
+ {
+ // Ergebnis initialisieren (damit alle Schl�ssel vorhanden sind)
+ $ergebnis = array('type' => null,
+ 'projectid' => null,
+ 'objectid' => null );
+
+
+// Logger::trace( 'WEBDAV: Parsen der URI '.$uri);
+ $uriParts = explode('/',$uri);
+
+ $projectName = array_shift($uriParts);
+
+ if ( empty($projectName) )
+ {
+ $ergebnis['type'] = 'root';
+ return $ergebnis; // Root-Verzeichnis
+ }
+
+ $result = $this->client->projectlist();
+ $projects = $result['projects'];
+
+ $projectid = array_search($projectName,$projects);
+
+ if ( $projectid === FALSE )
+ {
+ $this->httpStatus("404 Project not found");
+ echo 'project not found';
+ exit;
+ }
+
+ $project = $this->client->project($projectid);
+
+ $ergebnis['projectid'] = $projectid;
+
+ $objectid = $project['rootobjectid'];
+ $type = 'folder';
+
+ while( length($uriParts) > 0 )
+ {
+ $name = array_shift($uriParts);
+
+ $folder = $this->client->folder($objectid);
+
+ $found = false;
+ foreach( $folder['object'] as $oid => $object)
+ {
+ if ( $object['filename'] == $name )
+ {
+ $found = true;
+
+ $type = $object['type'];
+ $objectid = $object['objectid'];
+
+ break;
+ }
+
+ }
+
+ if ( ! $found )
+ {
+ httpStatus('404 Not Found');
+ exit;
+ }
+ }
+
+ $ergebnis['type' ] = $type;
+ $ergebnis['objectid'] = $objectid;
+
+
+ return $ergebnis;
+ }
+
+
+
+ /**
+ * Setzt einen HTTP-Status.<br>
+ * <br>
+ * Es wird ein HTTP-Status gesetzt, zus�tzlich wird der Status in den Header "X-WebDAV-Status" geschrieben.<br>
+ * Ist der Status nicht 200 oder 207 (hier folgt ein BODY), wird das Skript beendet.
+ */
+ protected function httpStatus( $status = true )
+ {
+ if ( $status === true )
+ $status = '200 OK';
+
+ // Logger::debug('WEBDAV: HTTP-Status: '.$status);
+
+ header('HTTP/1.1 '.$status);
+ header('X-WebDAV-Status: '.$status,true);
+
+ // RFC 2616 (HTTP/1.1), Section 10.4.6 "405 Method Not Allowed" says:
+ // "[...] The response MUST include an
+ // Allow header containing a list of valid methods for the requested
+ // resource."
+ //
+ // RFC 2616 (HTTP/1.1), Section 14.7 "Allow" says:
+ // "[...] An Allow header field MUST be
+ // present in a 405 (Method Not Allowed) response."
+ if ( substr($status,0,3) == '405' )
+ header('Allow: '.implode(', ',$this->allowed_methods()) );
+ }
+
+
+
+
+ private function allowed_methods()
+ {
+
+ if ($this->readonly)
+ return array('OPTIONS','HEAD','GET','PROPFIND'); // Readonly-Modus
+ else
+ // PROPPATCH unterstuetzen wir garnicht, aber lt. Spec sollten wir das.
+ return array('OPTIONS','HEAD','GET','PROPFIND','DELETE','PUT','COPY','MOVE','MKCOL','PROPPATCH');
+ }
+
+
+}
diff --git a/dav.ini b/dav.ini
@@ -0,0 +1,17 @@
+; you may copy this file dav.ini to a custom file dav.custom.ini or dav.<hostname>.ini
+;
+; beware of publishing this file via the webserver because it may contain secret information!
+
+dav.enable=true
+dav.create=true
+dav.readonly = true
+dav.anonymous = false
+
+log.file=dav.log
+log.level=trace
+
+cms.username=dav
+cms.password=davdav
+cms.database=pdo_my_prod
+cms.host=duese
+cms.path="/~dankert/cms/cms09/"
diff --git a/dav.log b/dav.log
@@ -0,0 +1,126 @@
+Jan 9 22:49:58 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:49:58 WARN 127.0.0.1 OPTIONS WEBDAV is disabled by configuration
+Jan 9 22:50:50 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:50:50 WARN 127.0.0.1 OPTIONS WEBDAV is disabled by configuration
+Jan 9 22:55:33 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:55:37 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:55:47 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:55:50 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:57:25 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 22:57:28 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:04:17 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:04:19 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:04:26 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:14:14 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:14:19 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:14:27 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:17:48 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:17:51 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:18:19 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:19:21 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:19:30 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:11 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:16 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:34 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:36 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:38 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:26:41 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:27:46 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:27:46 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Jan 9 23:35:20 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:35:20 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Jan 9 23:35:20 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:35:24 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:35:32 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:35:32 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Jan 9 23:35:32 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:35:35 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:35:35 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Jan 9 23:35:35 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:35:43 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:37:38 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Jan 9 23:37:38 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Jan 9 23:37:38 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Jan 9 23:37:42 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 22 23:11:28 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 22 23:11:28 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 22 23:14:41 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:14:56 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:16:08 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:16:36 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:16:44 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:16:50 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:16:57 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:18:29 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:19:06 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:19:24 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 22 23:19:24 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 22 23:20:14 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 22 23:20:14 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 22 23:58:20 TRACE 127.0.0.1 GET WEBDAV request
+Mar 22 23:59:43 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 22 23:59:47 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 22 23:59:48 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 23 00:01:36 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 23 00:01:39 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 23 00:01:39 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 23 00:16:21 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 23 00:16:24 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 23 00:16:25 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 23 00:16:25 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:16:26 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:16:29 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:16:30 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:16:39 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:16:41 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:00 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:02 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:03 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:05 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:10 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:11 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:24 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:25 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:29 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:31 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:32 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:33 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:17:34 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:17:35 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:19:20 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:19:22 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:19:41 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:19:42 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:19:43 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:19:44 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:20:07 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 23 00:20:08 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 23 00:23:51 TRACE 127.0.0.1 GET WEBDAV request
+Mar 23 00:23:57 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 21:54:33 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 26 21:54:33 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 26 21:54:33 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:37 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:41 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 26 21:54:41 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 26 21:54:41 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:43 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:45 TRACE 127.0.0.1 OPTIONS WEBDAV request
+Mar 26 21:54:45 TRACE 127.0.0.1 OPTIONS OPTIONS: Allow: OPTIONS, HEAD, GET, PROPFIND
+Mar 26 21:54:45 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:47 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:49 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 26 21:54:53 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:54:54 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 26 21:55:09 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 21:55:11 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 21:55:14 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 21:55:36 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:55:38 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 26 21:55:39 TRACE 127.0.0.1 PROPFIND WEBDAV request
+Mar 26 21:55:41 DEBUG 127.0.0.1 PROPFIND Multistatus: <?xml version="1.0" encoding="utf-8" ?><d:multistatus xmlns:d="DAV:"><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 13:00:00 +0100</d:creationdate><d:displayname></d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 13:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/heimkino.jandankert.de/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>heimkino.jandankert.de</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response><d:response><d:href>http://duese/~dankert/cms/cms09/dav/dav.php/Test Forum/</d:href><d:propstat><d:prop><d:creationdate>Sat, 01 Jan 2000 00:00:00 +0100</d:creationdate><d:displayname>Test Forum</d:displayname><d:getcontentlength>1</d:getcontentlength><d:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/" b:dt="dateTime.rfc1123">Sat, 01 Jan 2000 00:00:00 +0100</d:getlastmodified><d:resourcetype><d:collection/></d:resourcetype><d:categories /><d:fields></d:fields></d:prop><d:status>HTTP/1.1 200 OK</d:status></d:propstat></d:response></d:multistatus>
+Mar 26 21:56:32 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 21:56:42 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 22:01:11 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 22:40:45 TRACE 127.0.0.1 GET WEBDAV request
+Mar 26 22:40:57 TRACE 127.0.0.1 GET WEBDAV request
diff --git a/dav.php b/dav.php
@@ -0,0 +1,112 @@
+<?php
+
+/**
+ * WebDAV für OpenRat Content Management System<br>
+ *
+ * Das virtuelle Ordnersystem dieses CMS kann ueber das WebDAV-Protokoll
+ * dargestellt werden.
+ *
+ * Diese Klasse nimmt die Anfragen von WebDAV-Clients entgegen, zerlegt die
+ * Anfrage und erzeugt eine Antwort, die im HTTP-Body zurueck uebertragen
+ * wird.
+ * <br>
+ * WebDAV ist spezifiziert in der RFC 2518.<br>
+ * Siehe <code>http://www.ietf.org/rfc/rfc2518.txt</code><br>
+ *
+ * Implementiert wird DAV-Level 1 (d.h. ohne LOCK).
+ *
+ * Der Zugang über WebDAV beinhaltet einige Nachteile:
+ * - Login ist nur mit Name/Kennwort möglich (kein OpenId)
+ * - Nur die Standard-Datenbank kann verwendet werden
+ * - Der Client muss Cookies unterstützen
+ *
+ * @author Jan Dankert
+ * @package openrat.actions
+ */
+
+
+
+if (!defined('E_STRICT'))
+ define('E_STRICT', 2048);
+
+define('TIME_20000101',946681200); // default time for objects without time information.
+
+// Default-Configuration.
+$config = array('dav.enable' => false,
+ 'dav.create' => true,
+ 'dav.readonly' => false,
+ 'dav.expose_openrat' => true,
+ 'dav.compliant_to_redmond' => true,
+ 'dav.realm' =>'OpenRat CMS WebDAV Login',
+ 'dav.anonymous' => false,
+ 'cms.host' => 'localhost',
+ 'cms.port' => 80,
+ 'cms.username' => null,
+ 'cms.password' => null,
+ 'cms.database' => 'db1',
+ 'cms.path' => '/',
+ 'cms.max_file_size' => 1000,
+ 'log.level' => 'info',
+ 'log.file' => null
+ );
+
+// Configuration-Loader
+foreach( array( 'dav-'.$_SERVER['HTTP_HOST'].'.ini',
+ 'dav-custom.ini',
+ 'dav.ini') as $iniFile )
+ if ( is_file($iniFile))
+ $config = array_merge($config,parse_ini_file( $iniFile) );
+
+
+require('Logger.class.php');
+require('Client.class.php');
+require('CMS.class.php');
+require('WebDAV.class.php');
+
+//Logger::info( print_r($config,true));
+
+
+
+// PHP-Fehler ins Log schreiben, damit die Ausgabe nicht zerstoert wird.
+if (version_compare(PHP_VERSION, '5.0.0', '>'))
+ set_error_handler('webdavErrorHandler',E_ERROR | E_WARNING);
+else
+ set_error_handler('webdavErrorHandler');
+
+
+try {
+
+ $dav = new WebDAV();
+
+ $httpMethod = strtoupper($_SERVER['REQUEST_METHOD']);
+ $davMethodName = 'dav' . $httpMethod;
+
+ $dav->$davMethodName();
+}
+catch( Exception $e )
+{
+ error_log('WEBDAV ERROR: '.$e->getMessage()."\n".$e->getTraceAsString() );
+
+ // Wir teilen dem Client mit, dass auf dem Server was schief gelaufen ist.
+ header('HTTP/1.1 503 Internal WebDAV Server Error');
+ echo 'WebDAV-Request failed'."\n".$e->getTraceAsString();
+}
+
+/**
+ * Fehler-Handler fuer WEBDAV.<br>
+ * Bei einem Laufzeitfehler ist eine Ausgabe des Fehlers auf der Standardausgabe sinnlos,
+ * da der WebDAV-Client dies nicht lesen oder erkennen kann.
+ * Daher wird der Fehler-Handler umgebogen, so dass nur ein Logeintrag sowie ein
+ * Server-Fehler erzeugt wird.
+ */
+function webdavErrorHandler($errno, $errstr, $errfile, $errline)
+{
+ error_log('WEBDAV ERROR: '.$errno.'/'.$errstr.'/file:'.$errfile.'/line:'.$errline);
+
+
+ header('HTTP/1.1 503 Internal WebDAV Server Error');
+
+ // Wir teilen dem Client mit, dass auf dem Server was schief gelaufen ist.
+ echo 'WebDAV-Request failed with "'.$errstr.'"';
+ exit;
+}
diff --git a/index.php b/index.php
@@ -0,0 +1,6 @@
+<html>
+<body>
+<a href="./dav.php/">DAV</a>
+</body>
+</html>
+