PageRenderTime 54ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/Webdav/src/plugins/lock/handlers/copy.php

https://github.com/Yannix/zetacomponents
PHP | 291 lines | 142 code | 34 blank | 115 comment | 10 complexity | 7d22c6649fc8081c741963488b3ae0a7 MD5 | raw file
  1. <?php
  2. /**
  3. * File containing the ezcWebdavLockCopyRequestResponseHandler class.
  4. *
  5. * Licensed to the Apache Software Foundation (ASF) under one
  6. * or more contributor license agreements. See the NOTICE file
  7. * distributed with this work for additional information
  8. * regarding copyright ownership. The ASF licenses this file
  9. * to you under the Apache License, Version 2.0 (the
  10. * "License"); you may not use this file except in compliance
  11. * with the License. You may obtain a copy of the License at
  12. *
  13. * http://www.apache.org/licenses/LICENSE-2.0
  14. *
  15. * Unless required by applicable law or agreed to in writing,
  16. * software distributed under the License is distributed on an
  17. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18. * KIND, either express or implied. See the License for the
  19. * specific language governing permissions and limitations
  20. * under the License.
  21. *
  22. * @package Webdav
  23. * @version //autogentag//
  24. * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25. *
  26. * @access private
  27. */
  28. /**
  29. * Handler class for the COPY request.
  30. *
  31. * This class provides plugin callbacks for the COPY request for {@link
  32. * ezcWebdavLockPlugin}.
  33. *
  34. * @package Webdav
  35. * @version //autogen//
  36. *
  37. * @access private
  38. */
  39. class ezcWebdavLockCopyRequestResponseHandler extends ezcWebdavLockRequestResponseHandler
  40. {
  41. /**
  42. * Properties of the destination parent.
  43. *
  44. * These properties need to be set on the successfully moved the source to
  45. * the destination. The properties still need to be manipulated in {@link
  46. * generatedResponse()}
  47. *
  48. * @var ezcWebdavBasicPropertyStorage
  49. */
  50. protected $lockProperties;
  51. /**
  52. * The original request.
  53. *
  54. * @var ezcWebdavCopyRequest
  55. */
  56. protected $request;
  57. /**
  58. * Pathes moved to the destination.
  59. *
  60. * Used to determine all paths that need lock updates.
  61. *
  62. * @var array(string)
  63. */
  64. protected $sourcePaths;
  65. /**
  66. * Handles COPY requests.
  67. *
  68. * Performs all lock related checks necessary for the COPY request. In case
  69. * a violation with locks is detected or any other pre-condition check
  70. * fails, this method returns an instance of {@link ezcWebdavResponse}. If
  71. * everything is correct, null is returned, so that the $request is handled
  72. * by the backend.
  73. *
  74. * @param ezcWebdavRequest $request ezcWebdavCopyRequest
  75. * @return ezcWebdavResponse|null
  76. */
  77. public function receivedRequest( ezcWebdavRequest $request )
  78. {
  79. $backend = ezcWebdavServer::getInstance()->backend;
  80. $this->request = $request;
  81. $destination = $request->getHeader( 'Destination' );
  82. $destParent = dirname( $destination );
  83. $ifHeader = $request->getHeader( 'If' );
  84. $authHeader = $request->getHeader( 'Authorization' );
  85. // Check destination parent and collect the lock properties to
  86. // set after successfully moving
  87. $destinationLockRefresher = new ezcWebdavLockRefreshRequestGenerator(
  88. $request
  89. );
  90. $violation = $this->tools->checkViolations(
  91. // Destination parent dir
  92. // We also get the lock property from here and refresh the
  93. // locks on it
  94. new ezcWebdavLockCheckInfo(
  95. $destParent,
  96. ezcWebdavRequest::DEPTH_ZERO,
  97. $ifHeader,
  98. $authHeader,
  99. ezcWebdavAuthorizer::ACCESS_WRITE,
  100. $destinationLockRefresher
  101. ),
  102. // Return on first violation
  103. true
  104. );
  105. if ( $violation !== null )
  106. {
  107. if ( $violation->status === ezcWebdavResponse::STATUS_404 )
  108. {
  109. // Destination parent not found
  110. return new ezcWebdavErrorResponse(
  111. ezcWebdavResponse::STATUS_409,
  112. $violation->requestUri
  113. );
  114. }
  115. return $violation;
  116. }
  117. // Check destination itself, if it exsists
  118. $violation = $this->tools->checkViolations(
  119. // Destination (maybe overwritten, maybe not, but we must not
  120. // care)
  121. new ezcWebdavLockCheckInfo(
  122. $destination,
  123. ezcWebdavRequest::DEPTH_INFINITY,
  124. $ifHeader,
  125. $authHeader,
  126. ezcWebdavAuthorizer::ACCESS_WRITE,
  127. $destinationLockRefresher
  128. ),
  129. // Return on first violation
  130. true
  131. );
  132. // Destination might be there but not violated, or might not be there
  133. if ( $violation !== null && $violation->status !== ezcWebdavResponse::STATUS_404 )
  134. {
  135. // ezcWebdavErrorResponse
  136. return $violation;
  137. }
  138. // Perform lock refresh (must occur no matter if request succeeds)
  139. $destinationLockRefresher->sendRequests();
  140. // Store infos for use on correct moving
  141. // @TODO: Do we always get the correct property here?
  142. $this->lockDiscoveryProp = $destinationLockRefresher->getLockDiscoveryProperty(
  143. $destParent
  144. );
  145. $sourcePaths = $this->getSourcePaths();
  146. if ( is_object( $sourcePaths ) )
  147. {
  148. // ezcWebdavErrorResponse
  149. return $sourcePaths;
  150. }
  151. $this->sourcePaths = $sourcePaths;
  152. // Backend now handles the request
  153. return null;
  154. }
  155. /**
  156. * Returns all pathes in the copy source.
  157. *
  158. * This method performs the necessary checks on the source to copy. It
  159. * returns all paths that are to be moved. In case of any violation of the
  160. * checks, the method must hold and return an instance of
  161. * ezcWebdavErrorResponse instead of the desired paths.
  162. *
  163. * @return array(string)|ezcWebdavErrorResponse
  164. */
  165. protected function getSourcePaths()
  166. {
  167. $propFindReq = new ezcWebdavPropFindRequest( $this->request->requestUri );
  168. $propFindReq->prop = new ezcWebdavBasicPropertyStorage();
  169. $propFindReq->prop->attach( new ezcWebdavLockDiscoveryProperty() );
  170. ezcWebdavLockTools::cloneRequestHeaders(
  171. $this->request,
  172. $propFindReq,
  173. array( 'If', 'Depth' )
  174. );
  175. $propFindReq->validateHeaders();
  176. $propFindMultiStatusRes = ezcWebdavServer::getInstance()->backend->propFind(
  177. $propFindReq
  178. );
  179. if ( !( $propFindMultiStatusRes instanceof ezcWebdavMultiStatusResponse ) )
  180. {
  181. return $propFindMultiStatusRes;
  182. }
  183. $paths = array();
  184. foreach ( $propFindMultiStatusRes->responses as $propFindRes )
  185. {
  186. $paths[] = $propFindRes->node->path;
  187. }
  188. return $paths;
  189. }
  190. /**
  191. * Handles responses to the COPY request.
  192. *
  193. * This method reacts on the response generated by the backend for a COPY
  194. * request. It takes care to release all locks that existed on the source
  195. * URI from the newly created destination and to add all necessary locks to
  196. * it, indicated by its parent.
  197. *
  198. * Returns null, if no errors occured, an {@link ezcWebdavErrorResponse}
  199. * otherwise.
  200. *
  201. * @param ezcWebdavResponse $response ezcWebdavCopyResponse
  202. * @return ezcWebdavResponse|null
  203. */
  204. public function generatedResponse( ezcWebdavResponse $response )
  205. {
  206. if ( !( $response instanceof ezcWebdavCopyResponse ) )
  207. {
  208. return null;
  209. }
  210. $backend = ezcWebdavServer::getInstance()->backend;
  211. // Backend successfully performed request, update with LOCK from parent
  212. $request = $this->request;
  213. $source = $request->requestUri;
  214. $dest = $request->getHeader( 'Destination' );
  215. $destParent = dirname( $dest );
  216. $paths = $this->sourcePaths;
  217. $lockDiscovery = ( isset( $this->lockDiscoveryProp )
  218. ? clone $this->lockDiscoveryProp
  219. : new ezcWebdavLockDiscoveryProperty()
  220. );
  221. // Update active locks to reflect new resources
  222. foreach ( $lockDiscovery->activeLock as $id => $activeLock )
  223. {
  224. if ( $activeLock->depth !== ezcWebdavRequest::DEPTH_INFINITY )
  225. {
  226. unset( $lockDiscovery->activeLock[$id] );
  227. continue;
  228. }
  229. if ( $activeLock->baseUri === null )
  230. {
  231. $activeLock->baseUri = $destParent;
  232. $activeLock->lastAccess = null;
  233. }
  234. }
  235. // Perform lock updates
  236. foreach ( $paths as $path )
  237. {
  238. $newPath = str_replace( $source, $dest, $path );
  239. $propPatchReq = new ezcWebdavPropPatchRequest( $newPath );
  240. $propPatchReq->updates->attach( $lockDiscovery, ezcWebdavPropPatchRequest::SET );
  241. ezcWebdavLockTools::cloneRequestHeaders(
  242. $request,
  243. $propPatchReq
  244. );
  245. $propPatchReq->validateHeaders();
  246. $propPatchRes = $backend->propPatch( $propPatchReq );
  247. if ( !( $propPatchRes instanceof ezcWebdavPropPatchResponse ) )
  248. {
  249. throw new ezcWebdavInconsistencyException(
  250. "Could not set lock on resource {$newPath}."
  251. );
  252. }
  253. }
  254. return null;
  255. }
  256. }
  257. ?>