/** * Handles a POST request * @param DAV_Resource $resource * @return void * @throws DAV_Status */ public function handle($resource) { $resource->assertLock(); $headers = array(); try { ob_start(); $entity = $resource->method_POST($headers); } catch (DAV_Status $e) { ob_end_clean(); throw $e; } if ($length = ob_get_length()) { $headers['Content-Length'] = $length; DAV::header($headers); ob_end_flush(); return; } else { ob_end_clean(); } if (is_string($entity)) { $headers['Content-Length'] = strlen($entity); DAV::header($headers); echo $entity; return; } DAV::header($headers); }
/** * Deletes $resource. * Callers must check DAV_Multistatus::active() afterwards. * @param DAV_Resource $resource * @throws DAV_Status */ public static function delete($resource) { $resource->assertLock(); $resource->assertMemberLocks(); $parent = $resource->collection(); if (!$parent) { throw new DAV_Status(DAV::HTTP_FORBIDDEN); } $parent->assertLock(); self::delete_member($parent, $resource); }
/** * Handle the PROPPATCH request * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { $resource->assertLock(); if (empty($this->props)) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'No properties found in request body.'); } $priv_write = $resource->property_priv_write(array_keys($this->props)); $errors = array(); foreach ($this->props as $name => $value) { try { if (@DAV::$PROTECTED_PROPERTIES[$name]) { throw new DAV_Status(DAV::HTTP_FORBIDDEN, DAV::COND_CANNOT_MODIFY_PROTECTED_PROPERTY); } if (!@$priv_write[$name]) { throw DAV::forbidden(); } $resource->method_PROPPATCH($name, $value); } catch (DAV_Status $e) { $errors[$name] = $e; } } $response = new DAV_Element_response(DAV::getPath()); if (empty($errors)) { try { $resource->storeProperties(); } catch (DAV_Status $e) { foreach (array_keys($this->props) as $propname) { $errors[$propname] = $e; } } } if (empty($errors)) { foreach (array_keys($this->props) as $propname) { $response->setStatus($propname, DAV_Status::$OK); } } else { $failed_dependency = new DAV_Status(DAV::HTTP_FAILED_DEPENDENCY); foreach (array_keys($this->props) as $propname) { if (!isset($errors[$propname])) { $errors[$propname] = $failed_dependency; } } foreach ($errors as $propname => $status) { $response->setStatus($propname, $status); } } DAV_Multistatus::inst()->addResponse($response); DAV_Multistatus::inst()->close(); }
/** * Handles the OPTIONS request * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { $headers = array('DAV' => array('1' . (DAV::$LOCKPROVIDER ? ', 2' : '') . ', 3', 'access-control', '<http://apache.org/dav/propset/fs/1>'), 'MS-Author-Via' => 'DAV', 'Allow' => implode(', ', self::$ALLOWED_METHODS), 'Content-Length' => 0); if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { $headers['Access-Control-Allow-Methods'] = $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']; } if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { $headers['Access-Control-Allow-Headers'] = $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']; } if ($resource instanceof DAV_Resource) { DAV::header($resource->method_OPTIONS($headers)); } else { DAV::header($headers); } }
/** * Handle the common (resource independent) headers * * @param DAV_Resource $resource * @return array HTTP headers */ protected static function common($resource) { $headers = $resource->method_HEAD(); if (!isset($headers['Content-Length']) && !is_null($tmp = $resource->prop_getcontentlength())) { $headers['Content-Length'] = htmlspecialchars_decode($tmp); } if (!isset($headers['Content-Type'])) { if (!is_null($tmp = $resource->prop_getcontenttype())) { $headers['Content-Type'] = htmlspecialchars_decode($tmp); } else { $headers['Content-Type'] = 'application/octet-stream'; } } if (!isset($headers['ETag']) && !is_null($tmp = $resource->prop_getetag())) { $headers['ETag'] = htmlspecialchars_decode($tmp); } if (!isset($headers['Last-Modified']) && !is_null($tmp = $resource->prop_getlastmodified())) { $headers['Last-Modified'] = htmlspecialchars_decode($tmp); } if (!isset($headers['Content-Language']) && !is_null($tmp = $resource->prop_getcontentlanguage())) { $headers['Content-Language'] = htmlspecialchars_decode($tmp); } $headers['Accept-Ranges'] = 'bytes'; return $headers; }
/** * Checks and handles MKCOL request * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { if ($resource) { if ($resource->isVisible()) { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED); } throw DAV::forbidden(); } $resource = DAV::$REGISTRY->resource(dirname(DAV::getPath())); if (!$resource or !$resource->isVisible()) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to MKCOL in unknown resource'); } if (!$resource instanceof DAV_Collection) { throw new DAV_Status(DAV::HTTP_METHOD_NOT_ALLOWED); } if (0 < (int) @$_SERVER['CONTENT_LENGTH']) { throw new DAV_Status(DAV::HTTP_UNSUPPORTED_MEDIA_TYPE); } $resource->assertLock(); $resource->method_MKCOL(basename(DAV::getPath())); DAV::redirect(DAV::HTTP_CREATED, DAV::getPath()); }
/** * Handles a DAV:acl-principal-prop-set REPORT request * * @param DAV_Resource $resource The resource to perform the request on * @return void */ private function handle_acl_principal_prop_set($resource) { $ppr = $resource->property_priv_read(array(DAV::PROP_ACL)); if (!$ppr[DAV::PROP_ACL]) { throw DAV::forbidden(); } $principals = array(); foreach ($resource->user_prop_acl() as $ace) { if ('/' === $ace->principal[0]) { $principals[$ace->principal] = true; } elseif (isset(DAVACL::$PRINCIPALS[$ace->principal])) { continue; } else { $href = $resource->prop($ace->principal); if ($href instanceof DAV_Element_href) { $principals[$href->URIs[0]] = true; } } } $multistatus = DAV_Multistatus::inst(); foreach (array_keys($principals) as $href) { if ($href && ($principal = DAV::$REGISTRY->resource($href))) { $response = new DAV_Element_response($href); foreach ($this->entity as $property) { try { $response->setProperty($property, $principal->prop($property)); } catch (DAV_Status $e) { $response->setStatus($property, $e); } } $multistatus->addResponse($response); } } }
/** * Set or delete a property when a PROPPATCH request was made * * @param string $propname the name of the property to be set. * @param string $value an XML fragment, or null to unset the property. * @see DAV_Resource::method_PROPPATCH() */ public function method_PROPPATCH($propname, $value = null) { if ($method = @DAV::$ACL_PROPERTIES[$propname] or $this instanceof DAVACL_Principal && ($method = @DAV::$PRINCIPAL_PROPERTIES[$propname])) { return call_user_func(array($this, "set_{$method}"), $value); } return parent::method_PROPPATCH($propname, $value); }
public function testCollection() { $root = new DAV_Resource('/'); $this->assertNull($root->collection(), 'DAV_Resource::collection() should return null for the root resource'); $this->assertSame($this->obj->collection()->path, '/collection', 'DAV_Resource::collection() should return the correct collection for the non-root resource'); }
/** * Refreshes an already existing lock * * @param DAV_Resource $resource * @return void * @throws DAV_Statuss */ private function handleRefreshLock($resource) { $if_header = $this->if_header; if (!isset($if_header[DAV::getPath()]) || !$if_header[DAV::getPath()]['lock']) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, array(DAV::COND_LOCK_TOKEN_SUBMITTED => new DAV_Element_href(DAV::getPath()))); } // I think this can never evaluate to true, because DAV_Request already checks // whether the 'If' header matches the lock token of the resource. So if the // resource doesn't have a lock, this is already detected before this method // is called! (However, I don't dare to delete this yet and it doesn't hurt to // keep it) if (!($lock = DAV::$LOCKPROVIDER->getlock(DAV::getPath()))) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED, array(DAV::COND_LOCK_TOKEN_MATCHES_REQUEST_URI)); } DAV::$LOCKPROVIDER->refresh($lock->lockroot, $lock->locktoken, $this->timeout); if (!($lockdiscovery = $resource->prop_lockdiscovery())) { throw new DAV_Status(DAV::HTTP_INTERNAL_SERVER_ERROR); } // Generate output: DAV::header('application/xml; charset="utf-8"'); echo DAV::xml_header() . '<D:prop xmlns:D="DAV:"><D:lockdiscovery>' . $lockdiscovery . '</D:lockdiscovery></D:prop>'; }
/** * Called by {@link method_PROPFIND()} * @param string $path * @param DAV_Resource $resource * @param array $props */ private function handle3($resource, $props) { $propprivs = $resource->property_priv_read($props); $response = new DAV_Element_response($resource->path); foreach ($props as $prop) { if (array_key_exists($prop, $propprivs) && !$propprivs[$prop]) { $response->setStatus($prop, DAV::forbidden()); } else { try { $value = $resource->prop($prop); if (!is_null($value)) { $response->setProperty($prop, $value); } else { $response->setStatus($prop, DAV_Status::$NOT_FOUND); } } catch (DAV_Status $e) { $response->setStatus($prop, $e); } } } DAV_Multistatus::inst()->addResponse($response); }
/** * Determines whether the copy request is valid and if so, copies the resources * * @param DAV_Resource $resource * @return void * @throws DAV_Status */ protected function handle($resource) { $destination = $this->destination(); if ($resource instanceof DAV_Collection) { $destination = DAV::slashify($destination); } else { // The next line is here to make the litmus test succeed. The author of // litmus had eir own doubts wether this is actually desirable behaviour, // but chose to require this behaviour anyway: $destination = DAV::unslashify($destination); } // Can't move the root collection: if ($this instanceof DAV_Request_MOVE && '/' === DAV::getPath()) { throw new DAV_Status(DAV::HTTP_FORBIDDEN); } // Assert proper Depth: header value: if (DAV::DEPTH_1 === $this->depth() or $this instanceof DAV_Request_MOVE && DAV::DEPTH_INF !== $this->depth()) { throw new DAV_Status(DAV::HTTP_BAD_REQUEST, 'Illegal value for Depth: header.'); } // Check: Can't move a collection to one of its members. if ($this instanceof DAV_Request_MOVE && '/' === substr(DAV::getPath(), -1) && 0 === strpos($destination, DAV::getPath())) { throw new DAV_Status(DAV::HTTP_FORBIDDEN, "Can't move a collection to itself or one of its members."); } $resourceCollection = $resource->collection(); if ($this instanceof DAV_Request_MOVE) { $resourceCollection->assertLock(); $resource->assertLock(); $resource->assertMemberLocks(); } if ('/' !== $destination[0]) { // Copy to an external URI? $isCreated = $resource->method_COPY_external($destination, $this->overwrite()); if ($this instanceof DAV_Request_MOVE && !DAV_Multistatus::active()) { DAV_Request_DELETE::delete($resource); } if (DAV_Multistatus::active()) { DAV_Multistatus::inst()->close(); } elseif ($isCreated) { DAV::redirect(DAV::HTTP_CREATED, $destination); } else { DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); } return; } // Check: Won't move a resource to one of its parents. if (0 === strpos(DAV::slashify(DAV::getPath()), DAV::slashify($destination))) { throw new DAV_Status(DAV::HTTP_NOT_IMPLEMENTED, "Won't move or copy a resource to one of its parents."); } $destinationResource = DAV::$REGISTRY->resource($destination); $destinationCollection = DAV::$REGISTRY->resource(dirname($destination)); if (!$destinationCollection) { throw new DAV_Status(DAV::HTTP_CONFLICT, 'Unable to COPY to unexisting destination collection'); } if ($destinationResource) { if (!$this->overwrite()) { throw new DAV_Status(DAV::HTTP_PRECONDITION_FAILED); } else { $destinationResource->assertLock(); } } else { $destinationCollection->assertLock(); } if ($this instanceof DAV_Request_MOVE) { if (DAV::$LOCKPROVIDER) { foreach (DAV::$LOCKPROVIDER->memberLocks(DAV::getPath()) as $lock) { DAV::$LOCKPROVIDER->unlock($lock->lockroot); } if ($lock = DAV::$LOCKPROVIDER->getlock(DAV::getPath())) { DAV::$LOCKPROVIDER->unlock($lock->lockroot); } } $resourceCollection->method_MOVE(basename($resource->path), $destination); } else { $this->copy_recursively($resource, $destination); } #<<<<<<<< #// This version always returns a 207 Multistatus wrapper: #if (!DAV_Multistatus::active()) # if ( $destinationResource ) # DAV_Multistatus::inst()->addStatus( # $resource->path, # new DAV_Status( DAV::HTTP_NO_CONTENT ) # ); # else # DAV_Multistatus::inst()->addStatus( # $resource->path, # new DAV_Status( # DAV::HTTP_CREATED, DAV::path2uri($destination) # ) # ); #DAV_Multistatus::inst()->close(); #======== if (DAV_Multistatus::active()) { DAV_Multistatus::inst()->close(); } elseif ($destinationResource) { DAV::header(array('status' => DAV::HTTP_NO_CONTENT)); } else { DAV::redirect(DAV::HTTP_CREATED, $destination); } #>>>>>>>> }