| <?php |
| /** |
| * File containing the ezcWebdavLockUnlockRequestResponseHandler class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Webdav |
| * @version //autogentag// |
| * @copyright Copyright (C) 2005-2010 eZ Systems AS. All rights reserved. |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| * |
| * @access private |
| */ |
| /** |
| * Handler class for the UNLOCK request. |
| * |
| * This class provides plugin callbacks for the UNLOCK request for {@link |
| * ezcWebdavLockPlugin}. |
| * |
| * @package Webdav |
| * @version //autogen// |
| * |
| * @access private |
| */ |
| class ezcWebdavLockUnlockRequestResponseHandler extends ezcWebdavLockRequestResponseHandler |
| { |
| /** |
| * Handles responses to the UNLOCk request. |
| * |
| * Dummy method to satisfy interface. Does not perform any action, since |
| * the complete request is handled in {@link receivedRequest()}. |
| * |
| * @param ezcWebdavResponse $response |
| * @return ezcWebdavResponse|null |
| */ |
| public function generatedResponse( ezcWebdavResponse $response ) |
| { |
| return null; |
| } |
| |
| /** |
| * Handles UNLOCK requests. |
| * |
| * This method determines the base of the lock determined by the Lock-Token |
| * header of $request and releases the lock from all locked resources. In |
| * case a lock null resource is beyond these, it will be deleted. |
| * |
| * @param ezcWebdavRequest $request ezcWebdavUnlockRequest |
| * @return ezcWebdavResponse |
| */ |
| public function receivedRequest( ezcWebdavRequest $request ) |
| { |
| $srv = ezcWebdavServer::getInstance(); |
| |
| $token = $request->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 ); |
| } |
| } |
| |
| ?> |