getHeader( 'Lock-Token' ); $authHeader = $request->getHeader( 'Authorization' ); if ( $token === null ) { // UNLOCK must have a lock token return new ezcWebdavErrorResponse( ezcWebdavResponse::STATUS_412 ); } // Check permission if ( !$srv->isAuthorized( $request->requestUri, $authHeader, ezcWebdavAuthorizer::ACCESS_WRITE ) || !$srv->auth->ownsLock( $authHeader->username, $token ) ) { return $srv->createUnauthorizedResponse( $request->requestUri, 'Authorization failed.' ); } // Find properties to determine lock base $propFindReq = new ezcWebdavPropFindRequest( $request->requestUri ); $propFindReq->prop = new ezcWebdavBasicPropertyStorage(); $propFindReq->prop->attach( new ezcWebdavLockDiscoveryProperty() ); ezcWebdavLockTools::cloneRequestHeaders( $request, $propFindReq ); $propFindReq->setHeader( 'Depth', ezcWebdavRequest::DEPTH_ZERO ); $propFindReq->validateHeaders(); $propFindMultistatusRes = $srv->backend->propFind( $propFindReq ); if ( !( $propFindMultistatusRes instanceof ezcWebdavMultistatusResponse ) ) { return $propFindMultistatusRes; } $lockDiscoveryProp = null; foreach ( $propFindMultistatusRes->responses as $propFindRes ) { foreach( $propFindRes->responses as $propStatRes ) { if ( $propStatRes->storage->contains( 'lockdiscovery' ) ) { $lockDiscoveryProp = clone $propStatRes->storage->get( 'lockdiscovery' ); } } } if ( $lockDiscoveryProp === null ) { // Lock was not found (purged?)! Finish successfully. return new ezcWebdavResponse( ezcWebdavResponse::STATUS_204 ); } $affectedActiveLock = null; foreach ( $lockDiscoveryProp->activeLock as $id => $activeLock ) { // Note the ==, sinde $activeLock->token is an instance of // ezcWebdavPotentialUriContent if ( $activeLock->token == $token ) { $affectedActiveLock = $activeLock; break; } } if ( $affectedActiveLock === null ) { // Lock not present (purged)! Finish successfully. return new ezcWebdavUnlockResponse( ezcWebdavResponse::STATUS_204 ); } if ( $affectedActiveLock->baseUri !== null ) { // Requested resource is not the lock base, recurse $newRequest = new ezcWebdavUnlockRequest( $affectedActiveLock->baseUri ); ezcWebdavLockTools::cloneRequestHeaders( $request, $newRequest, array( 'If', 'Lock-Token' ) ); $newRequest->validateHeaders(); // @TODO Should be protected against infinite recursion return $this->receivedRequest( $newRequest ); } // If lock depth is 0, we issue 1 propfind too much here // @TODO: Analyse if clients usually lock 0 or infinity $res = $this->performUnlock( $request, $token, $affectedActiveLock->depth ); if ( $res instanceof ezcWebdavUnlockResponse ) { $srv->auth->releaseLock( $authHeader->username, $token ); } return $res; } /** * Performs unlocking. * * Performs a PROPFIND request with the $depth of the lock with $token on * the given $path (which must be the lock base). All affected resources * get the neccessary properties updated to reflect the change. Lock null * resources in the lock are removed. * * @param ezcWebdavUnlockRequest $request * @param string $token * @param int $depth * @return ezcWebdavResponse */ protected function performUnlock( ezcWebdavUnlockRequest $request, $token, $depth ) { $path = $request->requestUri; $backend = ezcWebdavServer::getInstance()->backend; // Find alle resources affected by the unlock, including affected properties $propFindReq = new ezcWebdavPropFindRequest( $path ); $propFindReq->prop = new ezcWebdavBasicPropertyStorage(); $propFindReq->prop->attach( new ezcWebdavLockDiscoveryProperty() ); ezcWebdavLockTools::cloneRequestHeaders( $request, $propFindReq ); $propFindReq->setHeader( 'Depth', $depth ); $propFindReq->validateHeaders(); $propFindMultistatusRes = $backend->propFind( $propFindReq ); // Remove lock information for the lock identified by $token from each affected resource foreach ( $propFindMultistatusRes->responses as $propFindRes ) { // Takes properties to be updated $changeProps = new ezcWebdavFlaggedPropertyStorage(); foreach ( $propFindRes->responses as $propStatRes ) { if ( $propStatRes->status === ezcWebdavResponse::STATUS_200 ) { // Remove affected active lock part from lockdiscovery property if ( $propStatRes->storage->contains( 'lockdiscovery' ) ) { $lockDiscoveryProp = clone $propStatRes->storage->get( 'lockdiscovery' ); foreach ( $lockDiscoveryProp->activeLock as $id => $activeLock ) { if ( $activeLock->token == $token ) { $lockDiscoveryProp->activeLock->offsetUnset( $id ); $changeProps->attach( $lockDiscoveryProp, ezcWebdavPropPatchRequest::SET ); break; } } } } } // Perform the PROPPATCH if ( count( $changeProps ) > 0 ) { $propPatchReq = new ezcWebdavPropPatchRequest( $propFindRes->node->path ); $propPatchReq->updates = $changeProps; ezcWebdavLockTools::cloneRequestHeaders( $request, $propPatchReq ); $propPatchReq->validateHeaders(); $propPatchRes = $backend->propPatch( $propPatchReq ); if ( !( $propPatchRes instanceof ezcWebdavPropPatchResponse ) ) { throw new ezcWebdavInconsistencyException( "Lock token $token could not be unlocked on resource {$propFindRes->node->path}." ); } } } return new ezcWebdavUnlockResponse( ezcWebdavResponse::STATUS_204 ); } } ?>