예제 #1
0
 /**
  * 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);
 }
예제 #2
0
 /**
  * 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);
 }
예제 #3
0
 /**
  * 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();
 }
예제 #4
0
 /**
  * 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);
     }
 }
예제 #5
0
 /**
  * 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;
 }
예제 #6
0
 /**
  * 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());
 }
예제 #7
0
 /**
  * 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);
         }
     }
 }
예제 #8
0
 /**
  * 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);
 }
예제 #9
0
 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');
 }
예제 #10
0
 /**
  * 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>';
 }
예제 #11
0
 /**
  * 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);
 }
예제 #12
0
 /**
  * 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);
     }
     #>>>>>>>>
 }