Example #1
0
 /**
  * Performs actual purging of locks.
  *
  * Iterates over {@link $lockProperties} and purges all locks of which the
  * tokens have been collected in {$locksToPurge}.
  * 
  * @return void
  *
  * @throws ezcWebdavLockAdministrationException
  *         in case purging of a lock failed.
  */
 protected function performPurge()
 {
     foreach ($this->lockProperties as $path => $lockDiscoveryProp) {
         $removeIds = array();
         foreach ($lockDiscoveryProp->activeLock as $id => $activeLock) {
             if (isset($this->locksToPurge[(string) $activeLock->token])) {
                 $removeIds[] = $id;
             }
         }
         if ($removeIds !== array()) {
             foreach ($removeIds as $id) {
                 $lockDiscoveryProp->activeLock->offsetUnset($id);
             }
             $propPatchReq = new ezcWebdavPropPatchRequest($path);
             $propPatchReq->updates = new ezcWebdavFlaggedPropertyStorage();
             $propPatchReq->updates->attach($lockDiscoveryProp, ezcWebdavPropPatchRequest::SET);
             $propPatchReq->validateHeaders();
             $propPatchRes = $this->backend->propPatch($propPatchReq);
             if (!$propPatchRes instanceof ezcWebdavPropPatchResponse) {
                 throw new ezcWebdavLockAdministrationException("PROPPATCH to remove timedout lock failed for '{$path}'.", $propPatchRes);
             }
         }
     }
 }
 public function testPropPatchCombinedSetDeleteValidationError()
 {
     $backend = new ezcWebdavMemoryBackend(true);
     $backend->addContents(array('foo' => 'bar', 'bar' => array('blubb' => 'Somme blubb blubbs.')));
     // First add some custom properties.
     $newProperties = new ezcWebdavFlaggedPropertyStorage();
     $newProperties->attach($p_bar = new ezcWebdavDeadProperty('foo:', 'bar', 'some content'), ezcWebdavPropPatchRequest::SET);
     $newProperties->attach($p_blubb = new ezcWebdavDeadProperty('foo:', 'blubb', 'some other content'), ezcWebdavPropPatchRequest::SET);
     $request = new ezcWebdavPropPatchRequest('/foo');
     $request->updates = $newProperties;
     $request->validateHeaders();
     $response = $backend->proppatch($request);
     $resProps = new ezcWebdavBasicPropertyStorage();
     $resProps->attach(new ezcWebdavDeadProperty('foo:', 'bar'));
     $resProps->attach(new ezcWebdavDeadProperty('foo:', 'blubb'));
     $this->assertEquals(new ezcWebdavPropPatchResponse(new ezcWebdavResource('/foo'), new ezcWebdavPropStatResponse($resProps)), $response, 'Expected property adding PROPPATCH response does not match real response.', 0, 20);
     // Then remove them again, with one live property in the middle to
     // check for proper failed dependency response codes.
     $updateProperties = new ezcWebdavFlaggedPropertyStorage();
     $updateProperties->attach($p_blubb, ezcWebdavPropPatchRequest::REMOVE);
     $updateProperties->attach($p_length = new ezcWebdavGetContentLengthProperty(), ezcWebdavPropPatchRequest::REMOVE);
     // Cause validation error
     $p_length->length = 'not a number';
     $updateProperties->attach($p_foo = new ezcWebdavDeadProperty('foo:', 'foo', 'random content'), ezcWebdavPropPatchRequest::SET);
     $updateProperties->attach($p_bar, ezcWebdavPropPatchRequest::REMOVE);
     $request = new ezcWebdavPropPatchRequest('/foo');
     $request->updates = $updateProperties;
     $request->validateHeaders();
     $response = $backend->proppatch($request);
     $failed = new ezcWebdavBasicPropertyStorage();
     $failed->attach($p_length);
     $depError = new ezcWebdavBasicPropertyStorage();
     $depError->attach($p_foo);
     $depError->attach($p_bar);
     $failed->rewind();
     $depError->rewind();
     $this->assertEquals(new ezcWebdavMultistatusResponse(new ezcWebdavPropPatchResponse(new ezcWebdavResource('/foo'), new ezcWebdavPropStatResponse(new ezcWebdavBasicPropertyStorage(), ezcWebdavResponse::STATUS_403), new ezcWebdavPropStatResponse($failed, ezcWebdavResponse::STATUS_409), new ezcWebdavPropStatResponse($depError, ezcWebdavResponse::STATUS_424))), $response, 'Expected property removing PROPPATCH response does not match real response.', 0, 20);
 }
Example #3
0
 public function testDeadPropertyRetrieval()
 {
     $backend = new ezcWebdavFileBackend($this->tempDir . 'backend/');
     $backend->options->useMimeExts = false;
     $newProperties = new ezcWebdavFlaggedPropertyStorage();
     $newProperties->attach($prop = new ezcWebdavDeadProperty('foo:', 'bar', "<?xml version=\"1.0\"?>\n<bar xmlns=\"foo:\">some content</bar>\n"), ezcWebdavPropPatchRequest::SET);
     $request = new ezcWebdavPropPatchRequest('/resource');
     $request->updates = $newProperties;
     $request->validateHeaders();
     $response = $backend->proppatch($request);
     $this->assertTrue(is_file($this->tempDir . 'backend/.ezc/resource.xml'), 'Expected creation of property storage.');
     $request = new ezcWebdavPropFindRequest('/resource');
     $request->prop = $newProperties;
     $request->validateHeaders();
     $response = $backend->propfind($request);
     $responseProperty = new ezcWebdavBasicPropertyStorage();
     $responseProperty->attach($prop);
     $responseProperty->rewind();
     $expectedResponse = new ezcWebdavMultistatusResponse(new ezcWebdavPropFindResponse(new ezcWebdavResource('/resource'), new ezcWebdavPropStatResponse($responseProperty)));
     $this->assertEquals($expectedResponse, $response, 'Expected response does not match real response.', 0, 20);
     $this->assertEquals(new ezcWebdavDeadProperty('foo:', 'bar', "<?xml version=\"1.0\"?>\n<bar xmlns=\"foo:\">some content</bar>\n"), $backend->getProperty('/resource', 'bar', 'foo:'));
 }
Example #4
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));
 }
Example #5
0
 /**
  * Parses the PROPPATCH request and returns a request object.
  *
  * This method is responsible for parsing the PROPPATCH request. It
  * retrieves the current request URI in $path and the request body as
  * $body.  The return value, if no exception is thrown, is a valid {@link
  * ezcWebdavPropPatchRequest} object.
  *
  * This method may be overwritten to adjust it to special client behaviour.
  * 
  * @param string $path 
  * @param string $body 
  * @return ezcWebdavPropPatchRequest
  */
 protected function parsePropPatchRequest($path, $body)
 {
     $request = new ezcWebdavPropPatchRequest($path);
     try {
         $dom = ezcWebdavServer::getInstance()->xmlTool->createDom($body);
     } catch (ezcWebdavInvalidXmlException $e) {
         throw new ezcWebdavInvalidRequestBodyException('PROPPATCH', $e->getMessage());
     }
     if ($dom->documentElement->localName !== 'propertyupdate') {
         throw new ezcWebdavInvalidRequestBodyException('PROPPATCH', "Expected XML element <propertyupdate />, received <{$dom->documentElement->localName} />.");
     }
     $propElements = $dom->documentElement->getElementsByTagNameNS(ezcWebdavXmlTool::XML_DEFAULT_NAMESPACE, 'prop');
     try {
         foreach ($propElements as $propElement) {
             if ($propElement->hasChildNodes()) {
                 ezcWebdavServer::getInstance()->propertyHandler->extractProperties($propElement->childNodes, $request->updates, $propElement->parentNode->localName === 'remove' ? ezcWebdavPropPatchRequest::REMOVE : ezcWebdavPropPatchRequest::SET);
             }
         }
     } catch (ezcBaseValueException $e) {
         throw new ezcWebdavInvalidRequestBodyException('PROPPATCH', "Property extraction produced value exception: '{$e->getMessage()}'.");
     }
     $request->setHeaders(ezcWebdavServer::getInstance()->headerHandler->parseHeaders());
     return $request;
 }
 public function testPropPatchCombinedSetDeleteFail()
 {
     $backend = new ezcWebdavFileBackend($this->tempDir . 'backend/');
     // First add some custom properties.
     $newProperties = new ezcWebdavFlaggedPropertyStorage();
     $newProperties->attach($p_bar = new ezcWebdavDeadProperty('foo:', 'bar', "<?xml version=\"1.0\"?>\n<bar xmlns=\"foo:\">some content</bar>\n"), ezcWebdavPropPatchRequest::SET);
     $newProperties->attach($p_blubb = new ezcWebdavDeadProperty('foo:', 'blubb', "<?xml version=\"1.0\"?>\n<blubb xmlns=\"foo:\">some other content</blubb>\n"), ezcWebdavPropPatchRequest::SET);
     $request = new ezcWebdavPropPatchRequest('/resource');
     $request->updates = $newProperties;
     $request->validateHeaders();
     $response = $backend->proppatch($request);
     $this->assertEquals(new ezcWebdavPropPatchResponse(new ezcWebdavResource('/resource')), $response, 'Expected property adding PROPPATCH response does not match real response.', 0, 20);
     // Then remove them again, with one live property in the middle to
     // check for proper failed dependency response codes.
     $updateProperties = new ezcWebdavFlaggedPropertyStorage();
     $updateProperties->attach($p_blubb, ezcWebdavPropPatchRequest::REMOVE);
     $updateProperties->attach($p_length = new ezcWebdavGetContentLengthProperty(), ezcWebdavPropPatchRequest::REMOVE);
     $updateProperties->attach($p_foo = new ezcWebdavDeadProperty('foo:', 'foo', "<?xml version=\"1.0\"?>\n<foo xmlns=\"foo:\">random content</foo>\n"), ezcWebdavPropPatchRequest::SET);
     $updateProperties->attach($p_bar, ezcWebdavPropPatchRequest::REMOVE);
     $request = new ezcWebdavPropPatchRequest('/resource');
     $request->updates = $updateProperties;
     $request->validateHeaders();
     $response = $backend->proppatch($request);
     $failed = new ezcWebdavBasicPropertyStorage();
     $failed->attach($p_length);
     $depError = new ezcWebdavBasicPropertyStorage();
     $depError->attach($p_foo);
     $depError->attach($p_bar);
     $failed->rewind();
     $depError->rewind();
     $this->assertEquals(new ezcWebdavMultistatusResponse(new ezcWebdavPropPatchResponse(new ezcWebdavResource('/resource'), new ezcWebdavPropStatResponse($failed, ezcWebdavResponse::STATUS_403), new ezcWebdavPropStatResponse(new ezcWebdavBasicPropertyStorage(), ezcWebdavResponse::STATUS_409), new ezcWebdavPropStatResponse($depError, ezcWebdavResponse::STATUS_424))), $response, 'Expected property removing PROPPATCH response does not match real response.', 0, 20);
 }