Exemple #1
0
 /**
  * Serves PROPPATCH requests.
  * 
  * The method receives a {@link ezcWebdavPropPatchRequest} object
  * containing all relevant information obout the clients request and will
  * return an instance of {@link ezcWebdavErrorResponse} on error or a
  * {@link ezcWebdavPropPatchResponse} response on success. If the
  * referenced resource is a collection or if only some properties produced
  * errors, an instance of {@link ezcWebdavMultistatusResponse} may be
  * returned.
  *
  * @param ezcWebdavPropPatchRequest $request
  * @return ezcWebdavResponse
  */
 public function propPatch(ezcWebdavPropPatchRequest $request)
 {
     $source = $request->requestUri;
     // Check authorization
     // Need to do this before checking of node existence is checked, to
     // avoid leaking information
     if (!ezcWebdavServer::getInstance()->isAuthorized($source, $request->getHeader('Authorization'), ezcWebdavAuthorizer::ACCESS_WRITE)) {
         return $this->createUnauthorizedResponse($source, $request->getHeader('Authorization'));
     }
     // Check if resource is available
     if (!$this->nodeExists($source)) {
         return new ezcWebdavErrorResponse(ezcWebdavResponse::STATUS_404, $source);
     }
     // Store proeprties, to be able to revert all changes later
     $propertyBackup = clone $this->getAllProperties($source);
     $errors = array(ezcWebdavResponse::STATUS_403 => new ezcWebdavBasicPropertyStorage(), ezcWebdavResponse::STATUS_409 => new ezcWebdavBasicPropertyStorage(), ezcWebdavResponse::STATUS_424 => new ezcWebdavBasicPropertyStorage());
     $errnous = false;
     // Update properties, like requested
     foreach ($request->updates as $property) {
         // If there already has been some error, issue failed
         // dependency errors for everything else.
         if ($errnous) {
             $errors[ezcWebdavResponse::STATUS_424]->attach($property);
             continue;
         }
         // Check for property validation errors and add a 409 for this.
         if ($property->hasError) {
             $errors[ezcWebdavResponse::STATUS_409]->attach($property);
             $errnous = true;
             continue;
         }
         switch ($request->updates->getFlag($property->name, $property->namespace)) {
             case ezcWebdavPropPatchRequest::REMOVE:
                 if (!$this->removeProperty($source, $property)) {
                     // If update failed, we assume the access has been denied.
                     $errors[ezcWebdavResponse::STATUS_403]->attach($property);
                     $errnous = true;
                 }
                 break;
             case ezcWebdavPropPatchRequest::SET:
                 if (!$this->setProperty($source, $property)) {
                     // If update failed, we assume the access has been denied.
                     //
                     // @todo: This assumptions is not particular correct.
                     // In case of live properties, which were tried to
                     // update a 409 error would be correct.
                     $errors[ezcWebdavResponse::STATUS_403]->attach($property);
                     $errnous = true;
                 }
                 break;
             default:
                 // This may happen, when a broken flag has been assigned
                 // during request generation. This SHOULD never happen.
                 $this->resetProperties($source, $propertyBackup);
                 return new ezcWebdavErrorResponse(ezcWebdavResponse::STATUS_500);
         }
     }
     // Create node from source for response
     if ($this->isCollection($source)) {
         $node = new ezcWebdavCollection($source);
     } else {
         $node = new ezcWebdavResource($source);
     }
     if ($errnous) {
         // Revert all changes
         $this->resetProperties($source, $propertyBackup);
         // Create response
         return new ezcWebdavMultistatusResponse(new ezcWebdavPropPatchResponse($node, new ezcWebdavPropStatResponse($errors[ezcWebdavResponse::STATUS_403], ezcWebdavResponse::STATUS_403), new ezcWebdavPropStatResponse($errors[ezcWebdavResponse::STATUS_409], ezcWebdavResponse::STATUS_409), new ezcWebdavPropStatResponse($errors[ezcWebdavResponse::STATUS_424], ezcWebdavResponse::STATUS_424)));
     }
     // Verify If-[None-]Match headers.
     // Done in this place to ensure that PROPPATCH would succeed otherwise.
     // Reset of properties to orgiginal state is performed if ETag check
     // fails.
     if (($res = $this->checkIfMatchHeaders($request, $source)) !== null) {
         $this->resetProperties($source, $propertyBackup);
         return $res;
     }
     $successProps = new ezcWebdavBasicPropertyStorage();
     foreach ($request->updates as $updatedProperty) {
         $successProp = clone $updatedProperty;
         $successProp->clear();
         $successProps->attach($successProp);
     }
     // RFC update requires multi-status even if everything worked properly
     return new ezcWebdavPropPatchResponse($node, new ezcWebdavPropStatResponse($successProps));
 }