/inc/bx/popoon/components/readers/webdav/bx.php
PHP | 414 lines | 216 code | 69 blank | 129 comment | 59 complexity | 01386e5f68819db188875e86d80a0ece MD5 | raw file
Possible License(s): GPL-2.0, BSD-3-Clause, Apache-2.0, LGPL-2.1
- <?php
- // +----------------------------------------------------------------------+
- // | Bx |
- // +----------------------------------------------------------------------+
- // | Copyright (c) 2001-2007 Liip AG |
- // +----------------------------------------------------------------------+
- // | Licensed under the Apache License, Version 2.0 (the "License"); |
- // | you may not use this file except in compliance with the License. |
- // | You may obtain a copy of the License at |
- // | http://www.apache.org/licenses/LICENSE-2.0 |
- // | Unless required by applicable law or agreed to in writing, software |
- // | distributed under the License is distributed on an "AS IS" BASIS, |
- // | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
- // | implied. See the License for the specific language governing |
- // | permissions and limitations under the License. |
- // +----------------------------------------------------------------------+
- // | Author: Liip AG <devel@liip.ch> |
- // +----------------------------------------------------------------------+
- /**
- * Filesystem access using WebDAV
- *
- * @access public
- */
- class HTTP_WebDAV_Server_bx extends HTTP_WebDAV_Server_Filesystem_MDB2
- {
- // request resource
- private $_bxResource=null;
-
- /**
- * Serve a webdav request
- *
- * @access public
- * @param string
- */
- function ServeRequest($base = false)
- {
-
- // set root directory, defaults to webserver document root if not set
- if ($base) {
- $this->base = realpath($base); // TODO throw if not a directory
- } else if(!$this->base) {
- $this->base = $_SERVER['DOCUMENT_ROOT'];
- }
- $this->db = $GLOBALS['POOL']->db;
-
- if (MDB2::isError($this->db)) {
- throw new PopoonDBException( $this->db);
- }
- //mysql_select_db($this->db_name) or die(mysql_error());
- // TODO throw on connection problems
- $old = file_get_contents(BX_DATA_DIR.$this->_urldecode(!empty($_SERVER["PATH_INFO"]) ? $_SERVER["PATH_INFO"] : "/"));
-
- // let the base class do all the work
- parent::ServeRequest();
- // trigger onSave() handler
- $method = strtolower($_SERVER["REQUEST_METHOD"]);
-
- if ($method == 'put' && (int) $this->_http_status >=200 && (int) $this->_http_status <205) {
- if ($this->_bxResource && method_exists($this->_bxResource, 'onSave')) {
- $this->_bxResource->onSave($old);
- }
- }
- }
-
- /**
- * GET method handler
- *
- * @param array parameter passing array
- * @return bool true on success
- */
- function GET(&$options)
- {
- // get absolute fs path to requested resource
- $fulluri = $options["path"];
- $mode = "output";
- // get language and strip it from fulluri
- list($fulluri, $lang) = bx_collections::getLanguage($fulluri);
- $GLOBALS['POOL']->config->setOutputLanguage($lang);
- $parts = bx_collections::getCollectionAndFileParts($fulluri,$mode);
- $collection = $parts['coll'] ;
- $filename = $parts['name'];
- $ext = $parts['ext'];
- $id = $filename.".".$ext;
- if($collection === FALSE) {
- throw new BxPageNotFoundException($fulluri);
- return false;
- } else {
- $fspath = $collection->getContentUriById($id,true);
- }
-
-
-
- // sanity check
-
- if (!file_exists($fspath)) {
- throw new BxPageNotFoundException($fulluri);
- return false;
- }
- // detect resource type
- $options['mimetype'] = $this->_mimetype($fspath);
-
- // detect modification time
- // see rfc2518, section 13.7
- // some clients seem to treat this as a reverse rule
- // requiering a Last-Modified header if the getlastmodified header was set
- $options['mtime'] = filemtime($fspath);
-
- // detect resource size
-
-
- // no need to check result here, it is handled by the base class
- $options['stream'] = fopen($fspath, "r");
- $fstat = fstat( $options['stream'] );
- if ($fstat['size'] > 0) {
- $options['size'] = $fstat['size'];
- }
- return true;
- }
- function _mimetype($fspath) {
- $mimetype= popoon_helpers_mimetypes::getFromFileLocation($fspath);
-
- return $mimetype."; charset=utf-8" ;
-
- }
-
- /**
- * PROPFIND method handler
- *
- * @param array general parameter passing array
- * @param array return array for file properties
- * @return bool true on success
- */
- function PROPFIND(&$options, &$files)
- {
-
- // get absolute fs path to requested resource
- $fspath = $this->base . $options["path"];
- $path = "";
- if (strpos($options['path'],".") === false && substr($options['path'],-1) != "/") {
- $options['path'] .= "/";
- }
- // bx_helpers_debug::dump_errorlog($options);
- $p = bx_collections::getCollectionAndFileParts($options['path'],"output");
- $coll = $p['coll'];
- // prepare property array
- $files["files"] = array();
- // if we have a filename, then it's not a request for a collection, but a sub resource of this collection
- if ($coll && !($coll->mock)) {
- $files["files"][] = $this->fileinfo($path, $coll);
- } else {
- return false;
- }
- // information for contained resources requested?
-
- if (!empty($options["depth"]) && ($coll instanceof bx_collection)) {
-
- // TODO check for is_dir() first?
- // make sure path ends with '/'
- if (substr($options["path"],-1) !== "/") {
- $options["path"] .= "/";
- }
-
- foreach ($coll->getChildren($p['rawname']) as $child) {
- $files["files"][] = $this->fileinfo($options["path"],$child);
- }
-
- }
-
- // ok, all done
-
- //bx_helpers_debug::dump_errorlog($files);
-
- return true;
- }
-
- /**
- * PROPPATCH method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function proppatch(&$options)
- {
- global $prefs, $tab;
- $msg = "";
-
- $path = $options["path"];
-
- $dir = dirname($path)."/";
- $base = basename($path);
- foreach($options["props"] as $key => $prop) {
- if($prop['ns'] == "DAV:") {
- $options["props"][$key][$status] = "403 Forbidden";
- } else {
- //FIXME.. here we should call the res->setProperty
- bx_resourcemanager::setProperty($options['path'],$prop['name'],$prop['val'], $prop['ns']);
- }
- }
-
- return "";
- }
-
- /**
- * MKCOL method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function MKCOL($options)
- {
- $path = $options["path"];
- //$path = "/s";
- $parent = dirname($path);
- if ($parent != "/"){
- $parent .= '/';
- }
- $name = basename($path);
-
- $coll = bx_collections::getCollection($parent);
-
- $coll->makeCollection($name);
-
- /*if(!file_exists($parent)) {
- return "409 Conflict";
- }
- if(!is_dir($parent)) {
- return "403 Forbidden";
- }
- if( file_exists($parent."/".$name) ) {
- return "405 Method not allowed";
- }
- */
- if(!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
- return "415 Unsupported media type";
- }
-
- /*
- if(!$stat) {
- return "403 Forbidden";
- }
- */
- return ("201 Created");
- }
-
- function fileinfo($path, $res = NULL)
- {
- $path = $path.$res->getLocalName();
- $path = str_replace("/./","/",$path);
- // create result array
- $info = array();
- $info["path"] = $path;
- $info["props"] = array();
-
- // no special beautified displayname here ...
- $info["props"][] = $this->mkprop("displayname", $res->getDisplayName());
-
-
- // creation and modification time
- $info["props"][] = $this->mkprop("creationdate", $res->getCreationDate());
- $info["props"][] = $this->mkprop("getlastmodified", $res->getLastModified());
- // type and size (caller already made sure that path exists)
- if ($res->getMimetype() == "httpd/unix-directory") {
- // directory (WebDAV collection)
- $info["props"][] = $this->mkprop("resourcetype", "collection");
- $info["props"][] = $this->mkprop("getcontenttype", "httpd/unix-directory");
- // $info["props"][] = $this->mkprop("getcontentlength", 0);
- } else {
- // plain file (WebDAV resource)
- $info["props"][] = $this->mkprop("resourcetype", "");
- $info["props"][] = $this->mkprop("getcontenttype", $res->getMimetype());
- $info["props"][] = $this->mkprop("getcontentlength",$res->getContentLength()); //filesize($fspath));
- }
- foreach( $res->getAllProperties() as $row) {
- $info["props"][] = $this->mkprop($row["namespace"], $row["name"], $row["value"]);
- }
-
- return $info;
- }
-
- /**
- * PUT method handler
- *
- * @param array parameter passing array
- * @return bool true on success
- */
- function PUT(&$options)
- {
- /* include_once("popoon/streams/bx.php");
- stream_wrapper_register("bx", "bxStream");
- */
- $fspath = $options["path"];
- /*
- if(!@is_dir(dirname($fspath))) {
- return "409 Conflict";
- }
- */
- //$streamtype = $this->getStreamType($options["path"]);
- $p = bx_collections::getCollectionAndFileParts($options["path"],"output");
- $fspath = $p['coll']->getContentUriById($p['rawname']);
- $options["new"] = ! file_exists($fspath);
- //$options["new"] = false;
- if ($p['coll']) {
- $this->_bxResource = $p['coll']->getChildResourceById($p['rawname']);
- if($options['new']) {
- $this->_bxResource->create();
- }
- }
-
- $fp = fopen($fspath, "w");
- if(!$fp) {
- error_log("Could not open $fspath for write");
- }
-
- return $fp;
- }
-
-
- /**
- * COPY method handler
- *
- * @param array general parameter passing array
- * @return bool true on success
- */
- function copy($options, $del=false)
- {
- // TODO Property updates still broken (Litmus should detect this?)
-
- if(!empty($_SERVER["CONTENT_LENGTH"])) { // no body parsing yet
- return "415 Unsupported media type";
- }
- // no copying to different WebDAV Servers yet
- if(isset($options["dest_url"])) {
- return "502 bad gateway";
- }
- $source = $this->base .$options["path"];
- if(!file_exists($source)) return "404 Not found";
- $dest = $this->base . $options["dest"];
- $new = !file_exists($dest);
- $existing_col = false;
- if(!$new) {
- if($del && is_dir($dest)) {
- if(!$options["overwrite"]) {
- return "412 precondition failed";
- }
- $dest .= basename($source);
- if(file_exists($dest.basename($source))) {
- $options["dest"] .= basename($source);
- } else {
- $new = true;
- $existing_col = true;
- }
- }
- }
- if(!$new) {
- if($options["overwrite"]) {
- $stat = $this->delete(array("path" => $options["dest"]));
- if($stat[0] != "2") return $stat;
- } else {
- return "412 precondition failed";
- }
- }
- if (is_dir($source)) {
- // RFC 2518 Section 9.2, last paragraph
- if ($options["depth"] != "infinity") {
- error_log("---- ".$options["depth"]);
- return "400 Bad request";
- }
- system(escapeshellcmd("cp -R ".escapeshellarg($source) ." " . escapeshellarg($dest)));
- if($del) {
- system(escapeshellcmd("rm -rf ".escapeshellarg($source)) );
- }
- } else {
- if($del) {
- @unlink($dest);
- $query = "DELETE FROM properties WHERE path = '$options[dest]'";
- $this->db->query($query);
- rename($source, $dest);
- $query = "UPDATE properties SET path = '$options[dest]' WHERE path = '$options[path]'";
- $this->db->query($query);
- } else {
- if(substr($dest,-1)=="/") $dest = substr($dest,0,-1);
- copy($source, $dest);
- }
- }
- return ($new && !$existing_col) ? "201 Created" : "204 No Content";
- }
-
-
-
- }
-
- ?>