public function testValidateHeadersFailure()
 {
     $req = new ezcWebdavPropFindRequest('/foo', '/bar');
     $req->setHeader('Depth', null);
     try {
         $req->validateHeaders();
         $this->fail('Exception not thrown on missing Depth header.');
     } catch (ezcWebdavMissingHeaderException $e) {
     }
     $req->setHeader('Depth', 'A');
     try {
         $req->validateHeaders();
         $this->fail('Exception not thrown on invalid Depth header.');
     } catch (ezcWebdavInvalidHeaderException $e) {
     }
 }
Esempio n. 2
0
 /**
  * Purges locks under $path.
  *
  * Checks all active locks on any resource under $path. Purges every lock
  * that has not been accessed for its $timeout value.
  * 
  * @param string $path 
  *
  * @throws ezcWebdavLockAdministrationException
  *         if searching for locks or purging an outdated lock failed.
  */
 public function purgeLocks($path)
 {
     $this->locksToPurge = array();
     $this->lockProperties = array();
     $propFindReq = new ezcWebdavPropFindRequest($path);
     $propFindReq->prop = new ezcWebdavBasicPropertyStorage();
     $propFindReq->prop->attach(new ezcWebdavLockDiscoveryProperty());
     $propFindReq->setHeader('Depth', ezcWebdavRequest::DEPTH_INFINITY);
     $propFindReq->validateHeaders();
     $propFindMultistatusRes = $this->backend->propFind($propFindReq);
     if (!$propFindMultistatusRes instanceof ezcWebdavMultistatusResponse) {
         throw new ezcWebdavLockAdministrationException('Finding locks failed.', $propFindMultistatusRes);
     }
     $this->collectPurgeProperties($propFindMultistatusRes);
     if ($this->locksToPurge !== array()) {
         $this->performPurge();
     }
 }
Esempio n. 3
0
 /**
  * Checks the given $request for If header and general lock violations.
  *
  * This method performs a PROPFIND request on the backend and retrieves the
  * properties <lockdiscovery>, <getetag> and <lockinfo> for all affected
  * resources. It then checks for the following violations:
  *
  * <ul>
  *   <li>Authorization</li>
  *   <li>Restrictions to etags and lock tokens provided by the If header</li>
  *   <li>General violations of other users locks</li>
  * </ul>
  *
  * Since the utilized information from the PROPFIND request must be used in
  * other places around this class, the method may receive a $generator
  * object. This object will be notified of every processed resource and
  * receives the properties listed above. You should use this mechanism to
  * avoid duplicate requesting of these properties and store the information
  * you desire in the background. In case the checkViolations() method
  * returns null, all checks passed and you can savely execute the desired
  * requests. If $returnOnViolation is set, violations are not collected
  * until all resources are checked, but the method returns as soon as the
  * first violation occurs.
  * 
  * @param ezcWebdavLockCheckInfo $checkInfo
  * @param bool $returnOnViolation
  * @return ezcWebdavMultistatusResponse|ezcWebdavErrorResponse|null
  */
 public function checkViolations(ezcWebdavLockCheckInfo $checkInfo, $returnOnViolation = false)
 {
     $srv = ezcWebdavServer::getInstance();
     $propFind = new ezcWebdavPropFindRequest($checkInfo->path);
     $propFind->prop = new ezcWebdavBasicPropertyStorage();
     $propFind->prop->attach(new ezcWebdavLockDiscoveryProperty());
     $propFind->prop->attach(new ezcWebdavGetEtagProperty());
     $propFind->setHeader('Depth', $checkInfo->depth !== null ? $checkInfo->depth : ezcWebdavRequest::DEPTH_ONE);
     $propFind->setHeader('Authorization', $checkInfo->authHeader);
     $propFind->validateHeaders();
     $propFindMultistatusRes = $srv->backend->performRequest($propFind);
     if (!$propFindMultistatusRes instanceof ezcWebdavMultistatusResponse) {
         // Bubble up error from backend
         return $propFindMultistatusRes;
     }
     foreach ($propFindMultistatusRes->responses as $propFindRes) {
         if (($res = $this->checkEtagsAndLocks($propFindRes, $checkInfo)) !== null) {
             return $res;
         }
         // Notify request generator on affected ressource
         if ($checkInfo->requestGenerator !== null) {
             $checkInfo->requestGenerator->notify($propFindRes);
         }
     }
     return null;
 }
 public function testMakeCollectionWithInvalidETag()
 {
     $testDest = "/collection/new_collection";
     $backend = new ezcWebdavFileBackend($this->tempDir . 'backend/');
     // Initialize all property directories
     $req = new ezcWebdavPropFindRequest('');
     $req->allProp = true;
     $req->setHeader('Depth', ezcWebdavRequest::DEPTH_INFINITY);
     $req->validateHeaders();
     $backend->propFind($req);
     $eTag = $backend->getProperty('/collection', 'getetag')->etag;
     $req = new ezcWebdavMakeCollectionRequest($testDest);
     $req->setHeader('If-None-Match', array($eTag));
     $req->validateHeaders();
     $res = $backend->makeCollection($req);
     $this->assertEquals(new ezcWebdavErrorResponse(ezcWebdavResponse::STATUS_412, '/collection', 'If-None-Match header check failed.'), $res, 'Expected response does not match real response.', 0, 20);
 }
 public function testPropPatchCombinedSetDelete()
 {
     $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_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);
     $resProps = new ezcWebdavBasicPropertyStorage();
     $resProps->attach(new ezcWebdavDeadProperty('foo:', 'blubb'));
     $resProps->attach(new ezcWebdavDeadProperty('foo:', 'foo'));
     $resProps->attach(new ezcWebdavDeadProperty('foo:', 'bar'));
     $this->assertEquals(new ezcWebdavPropPatchResponse(new ezcWebdavResource('/foo'), new ezcWebdavPropStatResponse($resProps)), $response, 'Expected property removing PROPPATCH response does not match real response.', 0, 20);
     // Ensure nothing has been removed, and the transactions has been
     // properly reverted.
     $leftProperties = new ezcWebdavBasicPropertyStorage();
     $leftProperties->attach($p_bar);
     $request = new ezcWebdavPropFindRequest('/foo');
     $request->prop = $updateProperties;
     $request->validateHeaders();
     $response = $backend->propfind($request);
     $failed = new ezcWebdavBasicPropertyStorage();
     $failed->attach($p_blubb);
     $failed->attach($p_bar);
     $failed->rewind();
     $success = new ezcWebdavBasicPropertyStorage();
     $success->attach($p_foo);
     $success->rewind();
     $expectedResponse = new ezcWebdavMultistatusResponse(new ezcWebdavPropFindResponse(new ezcWebdavResource('/foo'), new ezcWebdavPropStatResponse($success), new ezcWebdavPropStatResponse($failed, ezcWebdavResponse::STATUS_404)));
     $this->assertEquals($expectedResponse, $response, 'Expected validating PROPFIND response does not match real response.', 0, 20);
 }
Esempio n. 6
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:'));
 }
Esempio n. 7
0
 /**
  * Serves PROPFIND requests.
  * 
  * The method receives a {@link ezcWebdavPropFindRequest} object containing
  * all relevant information obout the clients request and will either
  * return an instance of {@link ezcWebdavErrorResponse} to indicate an error
  * or a {@link ezcWebdavPropFindResponse} on success. If the referenced
  * resource is a collection or if some properties produced errors, an
  * instance of {@link ezcWebdavMultistatusResponse} may be returned.
  *
  * The {@link ezcWebdavPropFindRequest} object contains a definition to
  * find one or more properties of a given collection or non-collection
  * resource.
  *
  * @param ezcWebdavPropFindRequest $request
  * @return ezcWebdavResponse
  */
 public function propFind(ezcWebdavPropFindRequest $request)
 {
     $source = $request->requestUri;
     if (!ezcWebdavServer::getInstance()->isAuthorized($source, $request->getHeader('Authorization'))) {
         // Globally issue a 401, if the user does not have access to the
         // requested resource itself.
         return $this->createUnauthorizedResponse($source, $request->getHeader('Authorization'));
         // Multistatus with 403 will be issued for nested resources in the
         // specific methods.
     }
     // Check if resource is available
     if (!$this->nodeExists($source)) {
         return new ezcWebdavErrorResponse(ezcWebdavResponse::STATUS_404, $source);
     }
     // Verify If-[None-]Match headers
     $res = $this->checkIfMatchHeadersRecursive($request, $source, $request->getHeader('Depth'));
     if ($res !== null) {
         return $res;
     }
     // Check the exact type of propfind request and dispatch to
     // corresponding method.
     switch (true) {
         case $request->prop:
             return $this->fetchProperties($request);
         case $request->propName:
             return $this->fetchPropertyNames($request);
         case $request->allProp:
             return $this->fetchAllProperties($request);
     }
     // This should really never happen, because the request class itself
     // should have ensured, that on of those options is set. Untestable.
     return new ezcWebdavErrorResponse(ezcWebdavResponse::STATUS_500);
 }
Esempio n. 8
0
 /**
  * Parses the PROPFIND request and returns a request object.
  *
  * This method is responsible for parsing the PROPFIND 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
  * ezcWebdavPropFindRequest} object.
  *
  * This method may be overwritten to adjust it to special client behaviour.
  * 
  * @param string $path 
  * @param string $body 
  * @return ezcWebdavPropFindRequest
  */
 protected function parsePropFindRequest($path, $body)
 {
     $request = new ezcWebdavPropFindRequest($path);
     $request->setHeaders(ezcWebdavServer::getInstance()->headerHandler->parseHeaders(array('Depth')));
     if (empty($body)) {
         throw new ezcWebdavInvalidRequestBodyException('PROPFIND', "Could not open XML as DOMDocument: '{$body}'.");
     }
     try {
         $dom = ezcWebdavServer::getInstance()->xmlTool->createDom($body);
     } catch (ezcWebdavInvalidXmlException $e) {
         throw new ezcWebdavInvalidRequestBodyException('PROPFIND', $e->getMessage());
     }
     if ($dom->documentElement->localName !== 'propfind') {
         throw new ezcWebdavInvalidRequestBodyException('PROPFIND', "Expected XML element <propfind />, received <{$dom->documentElement->localName} />.");
     }
     if ($dom->documentElement->firstChild === null) {
         throw new ezcWebdavInvalidRequestBodyException('PROPFIND', "Element <propfind /> does not have a child element.");
     }
     switch ($dom->documentElement->firstChild->localName) {
         case 'allprop':
             $request->allProp = true;
             break;
         case 'propname':
             $request->propName = true;
             break;
         case 'prop':
             $request->prop = new ezcWebdavBasicPropertyStorage();
             try {
                 ezcWebdavServer::getInstance()->propertyHandler->extractProperties($dom->documentElement->firstChild->childNodes, $request->prop);
             } catch (ezcBaseValueException $e) {
                 throw new ezcWebdavInvalidRequestBodyException('PROPFIND', "Property extraction produced value exception: '{$e->getMessage()}'.");
             }
             break;
         default:
             throw new ezcWebdavInvalidRequestBodyException('PROPFIND', "XML element <{$dom->documentElement->firstChild->nodeName} /> is not a valid child element for <propfind />.");
     }
     return $request;
 }