openrat-cms

OpenRat Content Management System
git clone http://git.code.weiherhei.de/openrat-cms.git
Log | Files | Refs | README

commit 25984cdd2196405711905db6b5bf4cff38aabe46
parent a53a3a2494261dea2de8e1bb7aa533c22a9fefee
Author: Jan Dankert <develop@jandankert.de>
Date:   Sat, 14 Nov 2020 22:37:35 +0100

Removing WebDAV access. This is now available via the separate project 'openrat-webdav'.

Diffstat:
Dmodules/cms/action/WebdavAction.class.php | 1222-------------------------------------------------------------------------------
Dwebdav.php | 11-----------
2 files changed, 0 insertions(+), 1233 deletions(-)

diff --git a/modules/cms/action/WebdavAction.class.php b/modules/cms/action/WebdavAction.class.php @@ -1,1221 +0,0 @@ -<?php - -namespace cms\action; - -use cms\base\Startup; -use cms\model\User; -use cms\model\Project; -use cms\model\Page; -use cms\model\Folder; -use cms\model\BaseObject; -use cms\model\File; -use cms\model\Link; - - -/** - * Action-Klasse fuer WebDAV.<br> - * - * Das virtuelle Ordnersystem dieses CMS kann �ber 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 zur�ck �bertragen - * 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 - * @deprecated - */ - -class WebdavAction extends BaseAction -{ - public $security = SECURITY_USER; - - // Zahlreiche Instanzvariablen, die im Konstruktor - // beim Zerlegen der Anfrag gef�llt werden. - var $defaultSubAction = 'show'; - var $database; - var $depth; - var $project; - var $folder; - var $obj; - 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; - - - /** - * Im Kontruktor wird der Request analysiert und ggf. eine Authentifzierung - * durchgefuehrt. - */ - function __construct() - { - parent::__construct(); - - if (!defined('E_STRICT')) - define('E_STRICT', 2048); - - // Nicht notwendig, da wir den Error-Handler umbiegen: - error_reporting(0); // PHP-Fehlermeldungen zerstoeren XML-Dokument, daher ausschalten. - - // 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'); - - - //Changed tobias - //$conf = \cms\base\Configuration::rawConfig(); - $prefs = new Preferences(); - $conf = $prefs->load(); - //End changed Tobias - $this->webdav_conf = $conf['webdav']; - - if ( $this->webdav_conf['compliant_to_redmond'] ) - header('MS-Author-Via: DAV' ); // Extrawurst fuer MS-Clients. - - if ( $this->webdav_conf['expose_openrat'] ) - header('X-Dav-powered-by: OpenRat CMS'); // Bandbreite verschwenden :) - - Logger::trace( 'WEBDAV: URI='.$_SERVER['REQUEST_URI']); - - if ( !$conf['webdav']['enable']) - { - Logger::warn( 'WEBDAV is disabled by configuration' ); - $this->httpStatus('403 Forbidden'); - exit; - } - - $this->create = $this->webdav_conf['create']; - $this->readonly = $this->webdav_conf['readonly']; - $this->maxFileSize = $this->webdav_conf['max_file_size']; - - Logger::debug( 'WEBDAV method is '.$_GET['subaction'] ); - - $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'; - - // Pr�fen, ob Benutzer angemeldet ist. - $user = $this->getUserFromSession(); - - // Authentisierung erzwingen (au�er bei Methode OPTIONS). - // For the motivation for not checking OPTIONS requests see - // http://pear.php.net/bugs/bug.php?id=5363 - if ( !is_object($user) && $_GET[RequestParams::PARAM_SUBACTION] != 'options' ) - { - Logger::debug( 'Checking Authentication' ); - - if ( !is_object(Session::getDatabase()) ) - $this->setDefaultDb(); - - $ok = false; - if ( isset($_SERVER['PHP_AUTH_USER']) ) - { - $user = new User(); - $user->name = $_SERVER['PHP_AUTH_USER']; - - $ok = $user->checkPassword( $_SERVER['PHP_AUTH_PW'] ); - - if ( $ok ) - { - $user->load(); - $user->setCurrent(); - $this->redirectWithSessionId(); - } - } - - if ( !$ok ) - { - // Client ist nicht angemeldet, daher wird nun die - // Authentisierung angefordert. - Logger::debug( 'Requesting Client to authenticate' ); - header('WWW-Authenticate: Basic realm="'.Startup::TITLE.'"'); - $this->httpStatus('401 Unauthorized'); - exit; - } - } - elseif ( !is_object($user) && $_GET[RequestParams::PARAM_SUBACTION] == 'options' ) - { - $this->setDefaultDb(); - } - - - $this->fullSkriptName = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'].'/'; - - if ( $this->webdav_conf['session_in_uri'] ) - $sos = 1+strlen(session_id())+strlen($this->webdav_conf['session_in_uri_prefix']); - else - $sos = 0; - - // URL parsen. - $uri = substr($_SERVER['REQUEST_URI'],strlen($_SERVER['SCRIPT_NAME']) + $sos); - - Logger::debug( 'WebDAV: URI="'.$uri.'"' ); - - $uri = $this->parseURI( $uri ); - $this->requestType = $uri['type' ]; - $this->folder = $uri['folder' ]; - $this->obj = $uri['object' ]; - $this->project = $uri['project']; - - $this->fullSkriptName .= implode('/',$uri['path']); - - if ( is_object($this->obj) && $this->obj->isFolder ) - $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 ( is_object($this->obj) && - $this->obj->isFolder && - $_GET['subaction'] == 'get' && - substr($_SERVER['REQUEST_URI'],strlen($_SERVER['REQUEST_URI'])-1 ) != '/' ) - { - Logger::debug( 'WebDAV: 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')); - } - - - - /** - * Falls ein WebDAV-Client keine Cookies setzen kann (was HTTP/1.1 eigentlich - * der Fall sein sollte), kann die Session-Id in die URL eingetragen - * werden. Dies muss in der Konfiguration aktiviert werden. - */ - function redirectWithSessionId() - { - if ( $this->webdav_conf['session_in_uri'] ) - { - header('Location: '.dirname($_SERVER['REQUEST_URI']).'/'. $this->webdav_conf['session_in_uri_prefix'].session_id().'/'.basename($_SERVER['REQUEST_URI'])); - //$this->httpStatus('303 See Other'); - $this->httpStatus('302 Moved'); - } - } - - - - /** - * Da im WebDAV-Request keine Datenbank-Id angegeben werden kann, benutzen - * wir hier die Standard-Datenbank. - */ - function setDefaultDb() - { - $conf = \cms\base\Configuration::rawConfig(); - - if ( !isset($conf['database']['default']) ) - { - Logger::error('No default database in configuration'); - $this->httpStatus('500 Internal Server Error - no default-database in configuration'); - } - - $dbid = $conf['database']['default']; - - $db = new DB( $conf['database'][$dbid] ); - $db->id = $dbid; - Session::setDatabase( $db ); - } - - - - 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'); - } - - - - /** - * HTTP-Methode OPTIONS.<br> - * <br> - * Es werden die verfuegbaren Methoden ermittelt und ausgegeben. - */ - function options() - { - header('DAV: 1'); // Wir haben DAV-Level 1. - header('Allow: '.implode(', ',$this->allowed_methods()) ); - - $this->httpStatus( '200 OK' ); - } - - - - /** - * 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. - */ - 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()) ); - } - - - - /** - * WebDav-HEAD-Methode. - */ - function head() - { - if ( $this->obj == null ) - { - $this->httpStatus( '404 Not Found' ); - } - elseif ( $this->obj->isFolder ) - { - $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. - */ - function get() - { - if ( $this->obj->isFolder ) - $this->getDirectory(); - elseif( $this->obj->isPage ) - { - $this->httpStatus( '200 OK' ); - - header('Content-Type: text/html'); - - $page = new Page( $this->obj->objectid ); - $page->load(); - echo '<html><head><title>OpenRat WEBDAV Access</title></head>'; - echo '<body>'; - echo '<h1>'.$page->full_filename().'</h1>'; - echo '<pre>'; - echo 'No Content available'; - echo '</pre>'; - echo '</body>'; - echo '</html>'; - } - elseif( $this->obj->isLink ) - { - $this->httpStatus( '200 OK' ); - - header('Content-Type: text/plain'); - - $link = new Link( $this->obj->objectid ); - $link->load(); - echo 'url: ' .$link->url ."\n"; - echo 'target-id: '.$link->linkedObjectId."\n"; - } - elseif( $this->obj->isFile ) - { - $this->httpStatus( '200 OK' ); - - $file = new File( $this->obj->objectid ); - $file->load(); - - header('Content-Type: '.$file->mimeType() ); - header('X-File-Id: '.$file->fileid ); - - // 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() ); - header('Content-Transfer-Encoding: binary' ); - header('Content-Description: '.$file->name ); - - $file->write(); // Bild aus Datenbank laden und in tempor�re Datei schreiben - - // Groesse des Bildes in Bytes - // Der Browser hat so die Moeglichkeit, einen Fortschrittsbalken zu zeigen - header('Content-Length: '.filesize($file->tmpfile()) ); - readfile( $file->tmpfile() ); - } - } - - - - /** - * Erzeugt ein Unix-�hnliche Ausgabe des Verzeichnisses als HTML. - */ - function getDirectory() - { - $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"); - - if ( $this->requestType == 'projectlist' ) - { - foreach(Project::getAllProjects() as $projectName ) - { - $objektinhalt = array(); - $z = 30*365.25*24*60*60; - $objektinhalt['createdate' ] = $z; - $objektinhalt['lastchangedate'] = $z; - $objektinhalt['size' ] = 1; - echo '<a href="'.$this->fullSkriptName.'/'.$projectName.'"> </a>'; - } - } - elseif( $this->requestType == 'object' ) // Verzeichnisinhalt - { - $objects = $this->folder->getObjects(); - - foreach( $objects as $object ) - { - printf($format, - number_format(1), - strftime("%Y-%m-%d %H:%M:%S",$object->lastchangeDate ), - '<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 lock() - { - $this->httpStatus('412 Precondition failed'); - $this->options(); - } - - - - /** - * 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) - */ - function unlock() - { - $this->httpStatus('412 Precondition failed'); - $this->options(); - } - - - - /** - * Die Methode POST ist bei WebDav nicht sinnvoll.<br> - * <br> - * Ausgabe von HTTP-Status 405 (Method Not Allowed) - */ - function post() - { - // Die Methode POST ist bei Webdav nicht sinnvoll. - $this->httpStatus('405 Method Not Allowed' ); - } - - - - /** - * Verzeichnis anlegen. - */ - function mkcol() - { - - 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. - */ - function delete() - { - 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. - */ - function copy() - { - if ( $this->readonly || !$this->create ) - { - Logger::error('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. - Logger::error('WEBDAV: COPY request, but Source not found'); - $this->httpStatus('405 Not Allowed' ); - } - elseif ( $this->destination == null ) - { - Logger::error('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> - */ - function move() - { - 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> - */ - function put() - { - // TODO: 409 (Conflict) wenn �bergeordneter Ordner nicht da. - - if ( $this->webdav_conf['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 ( !$this->webdav_conf['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. - */ - function propfind() - { - switch( $this->requestType ) - { - case 'projectlist': // 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; - - foreach(Project::getAllProjects() as $projectid=> $projectName ) - { - $project = new Project( $projectid ); - $rootObjectId = $project->getRootObjectId(); - $folder = new Folder( $rootObjectId ); - $folder->load(); - - $objektinhalt = array(); - $z = 30*365.25*24*60*60; - $objektinhalt['createdate' ] = $z; - $objektinhalt['lastchangedate'] = $folder->lastchangeDate; - $objektinhalt['size' ] = $project->size(); - $objektinhalt['name' ] = $this->fullSkriptName.$projectName.'/'; - $objektinhalt['displayname' ] = $projectName; - $objektinhalt['type'] = 'folder'; - $inhalte[] = $objektinhalt; - } - - $this->multiStatus( $inhalte ); - break; - - case 'object': // Verzeichnisinhalt - - if ( $this->obj == null ) - { - // Objekt existiert nicht. - Logger::trace( 'WEBDAV: PROPFIND of non-existent object'); - $this->httpStatus('404 Not Found'); - return; - } - elseif ( $this->obj->isFolder ) - { - if ( ! $this->obj->hasRight( ACL_READ )) - { - Logger::debug( 'Folder '.$this->obj->objectid.': access denied'); - $this->httpStatus('403 Forbidden'); - } - - $inhalte = array(); - - $objektinhalt = array(); - $objektinhalt['createdate' ] = $this->obj->createDate; - $objektinhalt['lastchangedate'] = $this->obj->lastchangeDate; - $objektinhalt['name' ] = $this->fullSkriptName; - $objektinhalt['displayname' ] = basename($this->fullSkriptName); - $objektinhalt['type' ] = 'folder'; - $objektinhalt['size' ] = 0; - $inhalte[] = $objektinhalt; - - if ( $this->depth > 0 ) - { - $objects = $this->folder->getObjects(); - foreach( $objects as $object ) - { - if ( ! $object->hasRight( ACL_READ )) - continue; - - //$object->loadRaw(); - $objektinhalt = array(); - $objektinhalt['createdate' ] = $object->createDate; - $objektinhalt['lastchangedate'] = $object->lastchangeDate; - $objektinhalt['displayname' ] = $object->filename; - - switch( $object->getType() ) - { - - case OR_TYPE_FOLDER: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename.'/'; - $objektinhalt['type'] = 'folder'; - $objektinhalt['size'] = 0; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_FILE: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $file = new File($object->objectid); - $file->load(); - $objektinhalt['size'] = $file->size; - $objektinhalt['mime'] = 'application/x-non-readable'; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_LINK: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $objektinhalt['size'] = 0; - $objektinhalt['mime'] = 'application/x-non-readable'; - $inhalte[] = $objektinhalt; - break; - case OR_TYPE_PAGE: - $objektinhalt['name'] = $this->fullSkriptName.$object->filename; - $objektinhalt['type'] = 'file'; - $objektinhalt['size'] = 0; - $inhalte[] = $objektinhalt; - break; - default: - } - } - } - Logger::trace( 'WEBDAV: PROPFIND-2'); - -// if ( count($inhalte)==0 ) -// $inhalte[] = array('createdate'=>0,'lastchangedate'=>0,'name'=>'empty','size'=>0,'type'=>'file'); - - Logger::trace('Anzahl Dateien:'.count($inhalte)); - $this->multiStatus( $inhalte ); - } - else - { - $object = $this->obj; - Logger::trace( 'WEBDAV: PROPFIND of file'); - $objektinhalt = array(); - $objektinhalt = array(); - $objektinhalt['name'] = $this->fullSkriptName.'/'.$object->filename.'/'; - $objektinhalt['displayname'] = $object->filename; - $objektinhalt['createdate' ] = $object->createDate; - $objektinhalt['lastchangedate'] = $object->lastchangeDate; - $file = new File( $this->obj->objectid ); - $file->load(); - $objektinhalt['size' ] = $file->size; - $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. - */ - function proppatch() - { - // TODO: Multistatus erzeugen. - // Evtl. ist '409 Conflict' besser? - $this->httpStatus('405 Not Allowed'); - } - - - /** - * Erzeugt einen Multi-Status. - * @access 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>'; - Logger::trace('PROPFIND: '.$response); - - $response = utf8_encode($response); - - header('Content-Length: '.strlen($response)); - echo $response; - } - - - /** - * Erzeugt ein "response"-Element, welches in ein "multistatus"-element verwendet werden kann. - */ - 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. - */ - function parseURI( $uri ) - { - // Ergebnis initialisieren (damit alle Schl�ssel vorhanden sind) - $ergebnis = array('type' => null, - 'project' => null, - 'path' => array(), - 'folder' => null, - 'object' => null ); - - Logger::trace( 'WEBDAV: Parsen der URI '.$uri); - $uriParts = explode('/',$uri); - - $nr = 0; - $f = null; - $o = null; - $ergebnis['type'] = 'projectlist'; - - foreach( $uriParts as $uriPart ) - { - if ( empty( $uriPart)) - continue; - - $ergebnis['path'][] = $uriPart; - - if ( $f == null ) - { - // URI='/project/' - // Name des Projektes in der URL, es wird das Projekt geladen. - $ergebnis['type'] = 'object'; - - $p = new Project(); - $p->name = $uriPart; - Logger::trace("Projektname: ".$p->name); - $p->loadByName(); - $ergebnis['project'] = $p; - // Das Projekt hat weder Sprache noch Variante gesetzt. - //Session::setProjectLanguage( new Language( $this->project->getDefaultLanguageId() ) ); - //Session::setProjectModel ( new Model ( $this->project->getDefaultModelId() ) ); - - $oid = $p->getRootObjectId(); - - $f = new Folder($oid); - $ergebnis['object'] = $f; - $ergebnis['folder'] = $f; - - } - else - { - if ( $ergebnis['object'] == null ) - { - $this->httpStatus('409 Conflict'); - exit; - } - - $oid = $f->getObjectIdByFileName($uriPart); - - if ( $oid == 0 ) - { - Logger::trace( 'WEBDAV: URL-Part does not exist: '.$uriPart); - $ergebnis['object'] = null; - } - else - { - Logger::trace( 'Teil '.$uriPart); - $o = new BaseObject($oid); - $o->load(); - $ergebnis['object'] = $o; - - if ( $o->isFolder ) - { - $f = new Folder($oid); - $ergebnis['folder'] = $f; - } - } - } - } - - return $ergebnis; - } -} - - - -/** - * 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) -{ - Logger::warn('WEBDAV ERROR: '.$errno.'/'.$errstr.'/file:'.$errfile.'/line:'.$errline); - - // Wir teilen dem Client mit, dass auf dem Server was schief gelaufen ist. - WebdavAction::httpStatus('500 Internal Server Error, WebDAV-Request failed with "'.$errstr.'"'); -} - -?>- \ No newline at end of file diff --git a/webdav.php b/webdav.php @@ -1,10 +0,0 @@ -<?php - -// Direkte Umleitung auf die WebDAV-Aktionsklasse. -// Diese Datei ist notwendig, um Parameter in der Webdav-Einstiegs-URL zu vermeiden. -$_GET['action' ] = 'WebDAV.class'; -$_GET['subaction'] = strtolower($_SERVER['REQUEST_METHOD']); - -require( 'index.php' ); - -?>- \ No newline at end of file