|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZWebDAVContentServer class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package kernel 00009 */ 00010 00011 /*! 00012 \class eZWebDAVContentServer ezwebdavcontentserver.php 00013 \ingroup eZWebDAV 00014 \brief Provides access to eZ Publish kernel using WebDAV 00015 00016 */ 00017 00018 class eZWebDAVContentServer extends eZWebDAVServer 00019 { 00020 const WEBDAV_INI_FILE = "webdav.ini"; 00021 const WEBDAV_AUTH_REALM = "eZ Publish WebDAV interface"; 00022 const WEBDAV_AUTH_FAILED = "Invalid username or password!"; 00023 const WEBDAV_INVALID_SITE = "Invalid site name specified!"; 00024 const WEBDAV_DISABLED = "WebDAV functionality is disabled!"; 00025 00026 /*! 00027 Initializes the eZWebDAVServer 00028 */ 00029 function eZWebDAVContentServer() 00030 { 00031 $this->eZWebDAVServer(); 00032 $this->User = eZUser::currentUser(); 00033 $this->FolderClasses = null; 00034 } 00035 00036 /*! 00037 Makes sure $this->User is reinitialized with the current user, 00038 then calls the $super->processClientRequest(). 00039 */ 00040 function processClientRequest() 00041 { 00042 $this->User = eZUser::currentUser(); 00043 eZWebDAVServer::processClientRequest(); 00044 } 00045 00046 /*! 00047 @{ 00048 */ 00049 00050 /*! 00051 Fetch the file from eZCluster if needed before send. 00052 */ 00053 function outputSendDataToClient( $output, $headers_only = false ) 00054 { 00055 if ( $output["file"] ) 00056 { 00057 $realPath = $output["file"]; 00058 $file = eZClusterFileHandler::instance( $realPath ); 00059 $file->fetch(); 00060 } 00061 $result = eZWebDAVServer::outputSendDataToClient($output,$headers_only); 00062 if ( $output["file"] && is_object( $file ) ) 00063 $file->deleteLocal(); 00064 return $result; 00065 } 00066 00067 /*! 00068 Restricts the allowed methods to only the subset that this server supports. 00069 */ 00070 function options( $target ) 00071 { 00072 // Only a few WebDAV operations are allowed for now. 00073 $options = array(); 00074 $options['methods'] = array( 'OPTIONS', 'PROPFIND', 'HEAD', 'GET', 'PUT', 'MKCOL', 'MOVE' ); 00075 // $options['versions'] = array( '1' ); 00076 00077 return $options; 00078 } 00079 00080 /*! 00081 Produces the collection content. Builds either the virtual start folder 00082 with the virtual content folder in it (and additional files). OR: if 00083 we're browsing within the content folder: it gets the content of the 00084 target/given folder. 00085 */ 00086 function getCollectionContent( $collection, $depth = false, $properties = false ) 00087 { 00088 $fullPath = $collection; 00089 $collection = $this->splitFirstPathElement( $collection, $currentSite ); 00090 00091 if ( !$currentSite ) 00092 { 00093 // Display the root which contains a list of sites 00094 $this->appendLogEntry( "Root: Fethcing site list", 'CS:getCollectionContent' ); 00095 $entries = $this->fetchSiteListContent( $depth, $properties ); 00096 return $entries; 00097 } 00098 00099 if ( !$this->userHasSiteAccess( $currentSite ) ) 00100 { 00101 $this->appendLogEntry( "No access to site '$currentSite'", 'CS:getCollectionContent' ); 00102 return eZWebDAVServer::FAILED_FORBIDDEN; 00103 } 00104 00105 return $this->getVirtualFolderCollection( $currentSite, $collection, $fullPath, $depth, $properties ); 00106 } 00107 00108 /*! 00109 \private 00110 Handles collections on the virtual folder level, if no virtual folder 00111 elements are accessed it lists the virtual folders. 00112 */ 00113 function getVirtualFolderCollection( $currentSite, $collection, $fullPath, $depth, $properties ) 00114 { 00115 $this->appendLogEntry( "Check virtual folder: site '$currentSite' in '$collection' ", 'CS:getVirtualFolderCollection' ); 00116 $this->setCurrentSite( $currentSite ); 00117 00118 if ( !$collection ) 00119 { 00120 // We are inside a site so we display the virtual folder for the site 00121 $this->appendLogEntry( "Virtual folder for '$currentSite'", 'CS:getVirtualFolderCollection' ); 00122 $entries = $this->fetchVirtualSiteContent( $currentSite, $depth, $properties ); 00123 return $entries; 00124 } 00125 00126 $collection = $this->splitFirstPathElement( $collection, $virtualFolder ); 00127 00128 if ( !in_array( $virtualFolder, $this->virtualFolderList() ) ) 00129 { 00130 $this->appendLogEntry( "Unknown virtual folder: '$virtualFolder' in site '$currentSite'", 'CS:getVirtualFolderCollection' ); 00131 return eZWebDAVServer::FAILED_NOT_FOUND; 00132 } 00133 00134 if ( !$this->userHasVirtualAccess( $currentSite, $virtualFolder ) ) 00135 { 00136 $this->appendLogEntry( "No access to virtual folder '$virtualFolder' in site '$currentSite'", 'CS:getVirtualFolderCollection' ); 00137 return eZWebDAVServer::FAILED_FORBIDDEN; 00138 } 00139 00140 return $this->getContentTreeCollection( $currentSite, $virtualFolder, $collection, $fullPath, $depth, $properties ); 00141 } 00142 00143 /*! 00144 \private 00145 Handles collections on the content tree level. 00146 Depending on the virtual folder we will generate a node path url and fetch 00147 the nodes for that path. 00148 */ 00149 function getContentTreeCollection( $currentSite, $virtualFolder, $collection, $fullPath, $depth, $properties ) 00150 { 00151 $this->appendLogEntry( "Content collection: from site '$currentSite' in '$virtualFolder' using path '$collection'", 'CS:getContentTreeCollection' ); 00152 $nodePath = $this->internalNodePath( $virtualFolder, $collection ); 00153 $node = $this->fetchNodeByTranslation( $nodePath ); 00154 00155 if ( !$node ) 00156 { 00157 $this->appendLogEntry( "Unknown node: $nodePath", 'CS:getContentTreeCollection' ); 00158 return eZWebDAVServer::FAILED_NOT_FOUND; 00159 } 00160 00161 // Can we list the children of the node? 00162 if ( !$node->canRead() ) 00163 { 00164 $this->appendLogEntry( "No access to content '$nodePath' in site '$currentSite'", 'CS:getContentTreeCollection' ); 00165 return eZWebDAVServer::FAILED_FORBIDDEN; 00166 } 00167 00168 $entries = $this->fetchContentList( $node, $nodePath, $depth, $properties ); 00169 return $entries; 00170 } 00171 00172 /*! 00173 Tries to figure out the filepath of the object being shown, 00174 if not we will pass the virtual url as the filepath. 00175 */ 00176 function get( $target ) 00177 { 00178 $result = array(); 00179 $result["data"] = false; 00180 $result["file"] = false; 00181 00182 $fullPath = $target; 00183 $target = $this->splitFirstPathElement( $target, $currentSite ); 00184 00185 if ( !$currentSite ) 00186 { 00187 // Sites are folders and have no data 00188 return eZWebDAVServer::FAILED_FORBIDDEN; 00189 } 00190 00191 if ( !$this->userHasSiteAccess( $currentSite ) ) 00192 { 00193 $this->appendLogEntry( "No access to site '$currentSite'", 'CS:get' ); 00194 return eZWebDAVServer::FAILED_FORBIDDEN; 00195 } 00196 00197 return $this->getVirtualFolderData( $result, $currentSite, $target, $fullPath ); 00198 } 00199 00200 /*! 00201 \private 00202 Handles data retrival on the virtual folder level. 00203 */ 00204 function getVirtualFolderData( $result, $currentSite, $target, $fullPath ) 00205 { 00206 $this->appendLogEntry( "current site: $currentSite", 'CS:get' ); 00207 $this->setCurrentSite( $currentSite ); 00208 00209 $target = $this->splitFirstPathElement( $target, $virtualFolder ); 00210 00211 if ( !$target ) 00212 { 00213 if ( !in_array( $virtualFolder, $this->virtualFileList() ) ) 00214 { 00215 return eZWebDAVServer::FAILED_NOT_FOUND; 00216 } 00217 00218 // We have reached the end of the path 00219 if ( $virtualFolder == basename( eZWebDAVContentServer::virtualInfoFileName() ) ) 00220 { 00221 $result["file"] = eZWebDAVContentServer::virtualInfoFileName(); 00222 00223 return $result; 00224 } 00225 00226 // The rest in the virtual folder does not have any data 00227 return eZWebDAVServer::FAILED_NOT_FOUND; 00228 } 00229 00230 if ( !$this->userHasVirtualAccess( $currentSite, $virtualFolder ) ) 00231 { 00232 $this->appendLogEntry( "No access to virtual folder '$virtualFolder' in site '$currentSite'", 'CS:get' ); 00233 return eZWebDAVServer::FAILED_FORBIDDEN; 00234 } 00235 00236 if ( !in_array( $virtualFolder, $this->virtualFolderList() ) ) 00237 { 00238 $this->appendLogEntry( "Unknown virtual folder: '$virtualFolder' in site '$currentSite'", 'CS:get' ); 00239 return eZWebDAVServer::FAILED_NOT_FOUND; 00240 } 00241 00242 if ( $virtualFolder == eZWebDAVContentServer::virtualContentFolderName() or 00243 $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 00244 { 00245 return $this->getContentNodeData( $result, $currentSite, $virtualFolder, $target, $fullPath ); 00246 } 00247 return eZWebDAVServer::FAILED_NOT_FOUND; 00248 } 00249 00250 /*! 00251 \private 00252 Handles data retrival on the content tree level. 00253 */ 00254 function getContentNodeData( $result, $currentSite, $virtualFolder, $target, $fullPath ) 00255 { 00256 $this->appendLogEntry( "attempting to fetch node, target is: $target", 'CS:get' ); 00257 00258 // Attempt to fetch the node the client wants to get. 00259 $nodePath = $this->internalNodePath( $virtualFolder, $target ); 00260 $node = $this->fetchNodeByTranslation( $nodePath ); 00261 00262 // Proceed only if the node is valid: 00263 if ( $node == null ) 00264 { 00265 $this->appendLogEntry( "No node for: $nodePath", 'CS:get' ); 00266 return $result; 00267 } 00268 00269 // Can we fetch the contents of the node 00270 if ( !$node->canRead() ) 00271 { 00272 $this->appendLogEntry( "No access to get '$nodePath' in site '$currentSite'", 'CS:get' ); 00273 return eZWebDAVServer::FAILED_FORBIDDEN; 00274 } 00275 00276 $object = $node->attribute( 'object' ); 00277 00278 $upload = new eZContentUpload(); 00279 $info = $upload->objectFileInfo( $object ); 00280 if ( $info ) 00281 { 00282 $result['file'] = $info['filepath']; 00283 } 00284 00285 return $result; 00286 } 00287 00288 /*! 00289 \note Not implemented yet 00290 */ 00291 function head( $target ) 00292 { 00293 return eZWebDAVServer::FAILED_NOT_FOUND; 00294 } 00295 00296 /*! 00297 Tries to create/update an object at location \a $target with the file \a $tempFile. 00298 */ 00299 function put( $target, $tempFile ) 00300 { 00301 $fullPath = $target; 00302 $target = $this->splitFirstPathElement( $target, $currentSite ); 00303 00304 if ( !$currentSite ) 00305 { 00306 return eZWebDAVServer::FAILED_FORBIDDEN; 00307 } 00308 00309 if ( !$this->userHasSiteAccess( $currentSite ) ) 00310 { 00311 $this->appendLogEntry( "No access to site '$currentSite'", 'CS:put' ); 00312 return eZWebDAVServer::FAILED_FORBIDDEN; 00313 } 00314 00315 return $this->putVirtualFolderData( $currentSite, $target, $tempFile, $fullPath ); 00316 } 00317 00318 /*! 00319 \private 00320 Handles data storage on the content tree level. 00321 It will check if the target is below a content folder in which it calls putContentData(). 00322 */ 00323 function putVirtualFolderData( $currentSite, $target, $tempFile, $fullPath ) 00324 { 00325 $this->appendLogEntry( "current site is: $currentSite", 'CS:put' ); 00326 $this->setCurrentSite( $currentSite ); 00327 00328 $target = $this->splitFirstPathElement( $target, $virtualFolder ); 00329 00330 if ( !$target ) 00331 { 00332 // We have reached the end of the path 00333 // We do not allow 'put' operations for the virtual folder. 00334 return eZWebDAVServer::FAILED_FORBIDDEN; 00335 } 00336 00337 if ( !in_array( $virtualFolder, $this->virtualFolderList() ) ) 00338 { 00339 $this->appendLogEntry( "Unknown virtual folder: '$virtualFolder' in site '$currentSite'", 'CS:put' ); 00340 return eZWebDAVServer::FAILED_CONFLICT; 00341 } 00342 00343 if ( !$this->userHasVirtualAccess( $currentSite, $virtualFolder ) ) 00344 { 00345 $this->appendLogEntry( "No access to virtual folder '$virtualFolder' in site '$currentSite'", 'CS:put' ); 00346 return eZWebDAVServer::FAILED_FORBIDDEN; 00347 } 00348 00349 if ( $virtualFolder == eZWebDAVContentServer::virtualContentFolderName() or 00350 $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 00351 { 00352 return $this->putContentData( $currentSite, $virtualFolder, $target, $tempFile, $fullPath ); 00353 } 00354 00355 return eZWebDAVServer::FAILED_FORBIDDEN; 00356 } 00357 00358 /*! 00359 \private 00360 Handles data storage on the content tree level. 00361 It will try to find the parent node of the wanted placement and 00362 create a new object with data from \a $tempFile. 00363 */ 00364 function putContentData( $currentSite, $virtualFolder, $target, $tempFile, $fullPath ) 00365 { 00366 $nodePath = $this->internalNodePath( $virtualFolder, $target ); 00367 00368 $this->appendLogEntry( "Inside virtual content folder", 'CS:put' ); 00369 00370 $parentNode = $this->fetchParentNodeByTranslation( $nodePath ); 00371 if ( $parentNode == null ) 00372 { 00373 // The node does not exist, so we cannot put the file 00374 $this->appendLogEntry( "Cannot put file $nodePath, not parent found", 'CS:put' ); 00375 return eZWebDAVServer::FAILED_CONFLICT; 00376 } 00377 00378 // Can we put content in the parent node 00379 if ( !$parentNode->canRead() ) 00380 { 00381 $this->appendLogEntry( "No access to put '$nodePath' in site '$currentSite'", 'CS:put' ); 00382 return eZWebDAVServer::FAILED_FORBIDDEN; 00383 } 00384 00385 $parentNodeID = $parentNode->attribute( 'node_id' ); 00386 00387 // We need the MIME-Type to figure out which content-class we will use 00388 $mimeInfo = eZMimeType::findByURL( $nodePath ); 00389 $mime = $mimeInfo['name']; 00390 00391 $webdavINI = eZINI::instance( eZWebDAVContentServer::WEBDAV_INI_FILE ); 00392 $defaultObjectType = $webdavINI->variable( 'PutSettings', 'DefaultClass' ); 00393 00394 $existingNode = $this->fetchNodeByTranslation( $nodePath ); 00395 $upload = new eZContentUpload(); 00396 if ( !$upload->handleLocalFile( $result, $tempFile, $parentNodeID, $existingNode ) ) 00397 { 00398 foreach ( $result['errors'] as $error ) 00399 { 00400 $this->appendLogEntry( "Error: " . $error['description'], 'CS: put' ); 00401 } 00402 foreach ( $result['notices'] as $notice ) 00403 { 00404 $this->appendLogEntry( "Notice: " . $notice['description'], 'CS: put' ); 00405 } 00406 if ( $result['status'] == eZContentUpload::STATUS_PERMISSION_DENIED ) 00407 { 00408 return eZWebDAVServer::FAILED_FORBIDDEN; 00409 } 00410 else 00411 return eZWebDAVServer::FAILED_UNSUPPORTED; 00412 } 00413 00414 return eZWebDAVServer::OK_CREATED; 00415 } 00416 00417 /*! 00418 Tries to create a collection at \a $target. In our case this is a content-class 00419 of a given type (most likely a folder). 00420 */ 00421 function mkcol( $target ) 00422 { 00423 $fullPath = $target; 00424 $target = $this->splitFirstPathElement( $target, $currentSite ); 00425 00426 if ( !$currentSite ) 00427 { 00428 // Site list cannot get new entries 00429 return eZWebDAVServer::FAILED_FORBIDDEN; 00430 } 00431 00432 if ( !$this->userHasSiteAccess( $currentSite ) ) 00433 { 00434 $this->appendLogEntry( "No access to site '$currentSite'", 'CS:mkcol' ); 00435 return eZWebDAVServer::FAILED_FORBIDDEN; 00436 } 00437 00438 return $this->mkcolVirtualFolder( $currentSite, $target, $fullPath ); 00439 } 00440 00441 /*! 00442 \private 00443 Handles collection creation on the virtual folder level. 00444 It will check if the target is below a content folder in which it calls mkcolContent(). 00445 */ 00446 function mkcolVirtualFolder( $currentSite, $target, $fullPath ) 00447 { 00448 $this->setCurrentSite( $currentSite ); 00449 00450 $target = $this->splitFirstPathElement( $target, $virtualFolder ); 00451 00452 if ( !in_array( $virtualFolder, $this->virtualList() ) ) 00453 { 00454 $this->appendLogEntry( "Unknown virtual element: '$virtualFolder' in site '$currentSite'", 'CS:mkcol' ); 00455 return eZWebDAVServer::FAILED_NOT_FOUND; 00456 } 00457 00458 if ( !$target ) 00459 { 00460 // We have reached the end of the path 00461 // We do not allow 'mkcol' operations for the virtual folder. 00462 return eZWebDAVServer::FAILED_FORBIDDEN; 00463 } 00464 00465 if ( !$this->userHasVirtualAccess( $currentSite, $virtualFolder ) ) 00466 { 00467 $this->appendLogEntry( "No access to virtual folder '$virtualFolder' in site '$currentSite'", 'CS:mkcol' ); 00468 return eZWebDAVServer::FAILED_FORBIDDEN; 00469 } 00470 00471 if ( $virtualFolder == eZWebDAVContentServer::virtualContentFolderName() or 00472 $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 00473 { 00474 return $this->mkcolContent( $currentSite, $virtualFolder, $target, $fullPath ); 00475 } 00476 00477 return eZWebDAVServer::FAILED_FORBIDDEN; 00478 } 00479 00480 /*! 00481 \private 00482 Handles collection creation on the content tree level. 00483 It will try to find the parent node of the wanted placement and 00484 create a new collection (folder etc.) as a child. 00485 */ 00486 function mkcolContent( $currentSite, $virtualFolder, $target, $fullPath ) 00487 { 00488 $nodePath = $this->internalNodePath( $virtualFolder, $target ); 00489 $node = $this->fetchNodeByTranslation( $nodePath ); 00490 if ( $node ) 00491 { 00492 return eZWebDAVServer::FAILED_EXISTS; 00493 } 00494 00495 $parentNode = $this->fetchParentNodeByTranslation( $nodePath ); 00496 $this->appendLogEntry( "Target is: $target", 'CS:mkcolContent' ); 00497 00498 if ( !$parentNode ) 00499 { 00500 return eZWebDAVServer::FAILED_NOT_FOUND; 00501 } 00502 00503 // Can we create a collection in the parent node 00504 if ( !$parentNode->canRead() ) 00505 { 00506 $this->appendLogEntry( "No access to mkcol '$nodePath' in site '$currentSite'", 'CS:mkcolContent' ); 00507 return eZWebDAVServer::FAILED_FORBIDDEN; 00508 } 00509 00510 return $this->createFolder( $parentNode, $nodePath ); 00511 } 00512 00513 /*! 00514 Removes the object from the node tree and leaves it in the trash. 00515 */ 00516 function delete( $target ) 00517 { 00518 $fullPath = $target; 00519 $target = $this->splitFirstPathElement( $target, $currentSite ); 00520 00521 if ( !$currentSite ) 00522 { 00523 // Cannot delete entries in site list 00524 return eZWebDAVServer::FAILED_FORBIDDEN; 00525 } 00526 00527 if ( !$this->userHasSiteAccess( $currentSite ) ) 00528 { 00529 $this->appendLogEntry( "No access to site '$currentSite'", 'CS:delete' ); 00530 return eZWebDAVServer::FAILED_FORBIDDEN; 00531 } 00532 00533 return $this->deleteVirtualFolder( $currentSite, $target, $fullPath ); 00534 } 00535 00536 /*! 00537 \private 00538 Handles deletion on the virtual folder level. 00539 It will check if the target is below a content folder in which it calls deleteContent(). 00540 */ 00541 function deleteVirtualFolder( $currentSite, $target, $fullPath ) 00542 { 00543 $this->appendLogEntry( "Target is: $target", 'CS:delete' ); 00544 $this->setCurrentSite( $currentSite ); 00545 00546 $target = $this->splitFirstPathElement( $target, $virtualFolder ); 00547 00548 if ( !in_array( $virtualFolder, $this->virtualList() ) ) 00549 { 00550 $this->appendLogEntry( "Unknown virtual element: '$virtualFolder' in site '$currentSite'", 'CS:deleteVirtualFolder' ); 00551 return eZWebDAVServer::FAILED_NOT_FOUND; 00552 } 00553 00554 if ( !$target ) 00555 { 00556 // We have reached the end of the path 00557 // We do not allow 'delete' operations for the virtual folder. 00558 return eZWebDAVServer::FAILED_FORBIDDEN; 00559 } 00560 00561 if ( !$this->userHasVirtualAccess( $currentSite, $virtualFolder ) ) 00562 { 00563 $this->appendLogEntry( "No access to virtual folder '$virtualFolder' in site '$currentSite'", 'CS:deleteVirtualFolder' ); 00564 return eZWebDAVServer::FAILED_FORBIDDEN; 00565 } 00566 00567 if ( $virtualFolder == eZWebDAVContentServer::virtualContentFolderName() or 00568 $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 00569 { 00570 return $this->deleteContent( $currentSite, $virtualFolder, $target, $fullPath ); 00571 } 00572 00573 return eZWebDAVServer::FAILED_FORBIDDEN; 00574 } 00575 00576 /*! 00577 \private 00578 Handles deletion on the content tree level. 00579 It will try to find the node of the target \a $target 00580 and then try to remove it (ie. move to trash) if the user is allowed. 00581 */ 00582 function deleteContent( $currentSite, $virtualFolder, $target, $fullPath ) 00583 { 00584 $nodePath = $this->internalNodePath( $virtualFolder, $target ); 00585 $node = $this->fetchNodeByTranslation( $nodePath ); 00586 00587 if ( $node == null ) 00588 { 00589 $this->appendLogEntry( "Cannot delete node/object $nodePath, it does not exist", 'CS:deleteContent' ); 00590 return eZWebDAVServer::FAILED_NOT_FOUND; 00591 } 00592 00593 // Can we delete the node? 00594 if ( !$node->canRead() or 00595 !$node->canRemove() ) 00596 { 00597 $this->appendLogEntry( "No access to delete '$nodePath' in site '$currentSite'", 'CS:deleteContent' ); 00598 return eZWebDAVServer::FAILED_FORBIDDEN; 00599 } 00600 00601 $this->appendLogEntry( "Removing node: $nodePath", 'CS:deleteContent' ); 00602 $node->removeNodeFromTree( true ); 00603 return eZWebDAVServer::OK; 00604 } 00605 00606 /*! 00607 Moves the object \a $source to destination \a $destination. 00608 */ 00609 function move( $source, $destination ) 00610 { 00611 $fullSource = $source; 00612 $fullDestination = $destination; 00613 $source = $this->splitFirstPathElement( $source, $sourceSite ); 00614 $destination = $this->splitFirstPathElement( $destination, $destinationSite ); 00615 if ( $sourceSite != $destinationSite ) 00616 { 00617 // We do not support moving from one site to another yet 00618 // TODO: Check if the sites are using the same db, 00619 // if so allow the move as a simple object move 00620 // If not we will have to do an object export from 00621 // $sourceSite and import it in $destinationSite 00622 return eZWebDAVServer::FAILED_FORBIDDEN; 00623 } 00624 00625 if ( !$sourceSite or 00626 !$destinationSite ) 00627 { 00628 // Cannot move entries in site list 00629 return eZWebDAVServer::FAILED_FORBIDDEN; 00630 } 00631 00632 if ( !$this->userHasSiteAccess( $sourceSite ) ) 00633 { 00634 $this->appendLogEntry( "No access to site '$sourceSite'", 'CS:move' ); 00635 return eZWebDAVServer::FAILED_FORBIDDEN; 00636 } 00637 if ( !$this->userHasSiteAccess( $destinationSite ) ) 00638 { 00639 $this->appendLogEntry( "No access to site '$destinationSite'", 'CS:move' ); 00640 return eZWebDAVServer::FAILED_FORBIDDEN; 00641 } 00642 00643 return $this->moveVirtualFolder( $sourceSite, $destinationSite, 00644 $source, $destination, 00645 $fullSource, $fullDestination ); 00646 } 00647 00648 /*! 00649 \private 00650 Handles moving on the virtual folder level. 00651 It will check if the target is below a content folder in which it calls moveContent(). 00652 */ 00653 function moveVirtualFolder( $sourceSite, $destinationSite, 00654 $source, $destination, 00655 $fullSource, $fullDestination ) 00656 { 00657 $this->setCurrentSite( $sourceSite ); 00658 00659 $source = $this->splitFirstPathElement( $source, $sourceVFolder ); 00660 $destination = $this->splitFirstPathElement( $destination, $destinationVFolder ); 00661 00662 if ( !in_array( $sourceVFolder, $this->virtualList() ) ) 00663 { 00664 $this->appendLogEntry( "Unknown virtual element: '$sourceVFolder' in site '$sourceSite'", 'CS:moveVirtualFolder' ); 00665 return eZWebDAVServer::FAILED_NOT_FOUND; 00666 } 00667 00668 if ( !in_array( $destinationVFolder, $this->virtualList() ) ) 00669 { 00670 $this->appendLogEntry( "Unknown virtual element: '$destinationVFolder' in site '$destinationSite'", 'CS:moveVirtualFolder' ); 00671 return eZWebDAVServer::FAILED_NOT_FOUND; 00672 } 00673 00674 if ( !$source or 00675 !$destination ) 00676 { 00677 // We have reached the end of the path for source or destination 00678 // We do not allow 'move' operations for the virtual folder (from or to) 00679 return eZWebDAVServer::FAILED_FORBIDDEN; 00680 } 00681 00682 if ( !$this->userHasVirtualAccess( $sourceSite, $sourceVFolder ) ) 00683 { 00684 $this->appendLogEntry( "No access to virtual folder '$sourceVFolder' in site '$sourceSite'", 'CS:moveVirtualFolder' ); 00685 return eZWebDAVServer::FAILED_FORBIDDEN; 00686 } 00687 if ( !$this->userHasVirtualAccess( $destinationSite, $destinationVFolder ) ) 00688 { 00689 $this->appendLogEntry( "No access to virtual folder '$destinationVFolder' in site '$destinationSite'", 'CS:moveVirtualFolder' ); 00690 return eZWebDAVServer::FAILED_FORBIDDEN; 00691 } 00692 00693 if ( ( $sourceVFolder == eZWebDAVContentServer::virtualContentFolderName() or 00694 $sourceVFolder == eZWebDAVContentServer::virtualMediaFolderName() ) and 00695 ( $destinationVFolder == eZWebDAVContentServer::virtualContentFolderName() or 00696 $destinationVFolder == eZWebDAVContentServer::virtualMediaFolderName() ) ) 00697 { 00698 return $this->moveContent( $sourceSite, $destinationSite, 00699 $sourceVFolder, $destinationVFolder, 00700 $source, $destination, 00701 $fullSource, $fullDestination ); 00702 } 00703 00704 return eZWebDAVServer::FAILED_FORBIDDEN; 00705 } 00706 00707 /*! 00708 \private 00709 Handles moving on the content tree level. 00710 It will try to find the node of the target \a $source 00711 and then try to move it to \a $destination. 00712 */ 00713 function moveContent( $sourceSite, $destinationSite, 00714 $sourceVFolder, $destinationVFolder, 00715 $source, $destination, 00716 $fullSource, $fullDestination ) 00717 { 00718 $nodePath = $this->internalNodePath( $sourceVFolder, $source ); 00719 $destinationNodePath = $this->internalNodePath( $destinationVFolder, $destination ); 00720 00721 // Get rid of possible extensions, remove .jpeg .txt .html etc.. 00722 $source = $this->fileBasename( $source ); 00723 00724 $sourceNode = $this->fetchNodeByTranslation( $nodePath ); 00725 00726 if ( !$sourceNode ) 00727 { 00728 return eZWebDAVServer::FAILED_NOT_FOUND; 00729 } 00730 00731 // Can we move the node from $sourceNode 00732 if ( !$sourceNode->canMoveFrom() ) 00733 { 00734 $this->appendLogEntry( "No access to move the node '$sourceSite':'$nodePath'", 'CS:moveContent' ); 00735 return eZWebDAVServer::FAILED_FORBIDDEN; 00736 } 00737 00738 $object = $sourceNode->attribute( 'object' ); 00739 $classID = $object->attribute( 'contentclass_id' ); 00740 00741 // Get rid of possible extensions, remove .jpeg .txt .html etc.. 00742 $destination = $this->fileBasename( $destination ); 00743 00744 $destinationNode = $this->fetchNodeByTranslation( $destinationNodePath ); 00745 $this->appendLogEntry( "Destination: $destinationNodePath", 'CS:moveContent' ); 00746 00747 if ( $destinationNode ) 00748 { 00749 return eZWebDAVServer::FAILED_EXISTS; 00750 } 00751 00752 $destinationNode = $this->fetchParentNodeByTranslation( $destinationNodePath ); 00753 00754 if ( !$destinationNode ) 00755 { 00756 return eZWebDAVServer::FAILED_NOT_FOUND; 00757 } 00758 00759 // Can we move the node to $destinationNode 00760 if ( !$destinationNode->canMoveTo( $classID ) ) 00761 { 00762 $this->appendLogEntry( "No access to move the node '$sourceSite':'$nodePath' to '$destinationSite':'$destinationNodePath'", 'CS:moveContent' ); 00763 return eZWebDAVServer::FAILED_FORBIDDEN; 00764 } 00765 00766 $srcParentPath = $this->splitLastPathElement( $nodePath, $srcNodeName ); 00767 $dstParentPath = $this->splitLastPathElement( $destinationNodePath, $dstNodeName ); 00768 if ( $srcParentPath == $dstParentPath ) 00769 { 00770 if( !$object->rename( $dstNodeName ) ) 00771 { 00772 $this->appendLogEntry( "Unable to rename the node '$sourceSite':'$nodePath' to '$destinationSite':'$destinationNodePath'", 'CS:moveContent' ); 00773 return eZWebDAVServer::FAILED_FORBIDDEN; 00774 } 00775 } 00776 else 00777 { 00778 if( !eZContentObjectTreeNodeOperations::move( $sourceNode->attribute( 'node_id' ), $destinationNode->attribute( 'node_id' ) ) ) 00779 { 00780 $this->appendLogEntry( "Unable to move the node '$sourceSite':'$nodePath' to '$destinationSite':'$destinationNodePath'", 'CS:moveContent' ); 00781 return eZWebDAVServer::FAILED_FORBIDDEN; 00782 } 00783 } 00784 00785 /* 00786 00787 // Todo: add lookup of the name setting for the current object 00788 $contentObjectID = $object->attribute( 'id' ); 00789 $contentObjectAttributes =& $object->contentObjectAttributes(); 00790 $contentObjectAttributes[0]->setAttribute( 'data_text', basename( $destination ) ); 00791 $contentObjectAttributes[0]->store(); 00792 00793 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 'version' => 1 ) ); 00794 $object->store(); 00795 */ 00796 00797 return eZWebDAVServer::OK_CREATED; 00798 } 00799 00800 /*! 00801 @} 00802 */ 00803 00804 /*! 00805 Sets/changes the current site(access) to a \a $site. 00806 */ 00807 function setCurrentSite( $site ) 00808 { 00809 $access = array( 'name' => $site, 00810 'type' => eZSiteAccess::TYPE_STATIC ); 00811 00812 $access = eZSiteAccess::change( $access ); 00813 eZDebugSetting::writeDebug( 'kernel-siteaccess', $access, 'current siteaccess' ); 00814 00815 // Clear/flush global database instance. 00816 $nullVar = null; 00817 eZDB::setInstance( $nullVar ); 00818 } 00819 00820 /*! 00821 Checks if the current user has access rights to site \a $site. 00822 \return \c true if the user proper access. 00823 */ 00824 function userHasSiteAccess( $site ) 00825 { 00826 $result = $this->User->hasAccessTo( 'user', 'login' ); 00827 $accessWord = $result['accessWord']; 00828 00829 if ( $accessWord == 'limited' ) 00830 { 00831 $hasAccess = false; 00832 $policyChecked = false; 00833 foreach ( array_keys( $result['policies'] ) as $key ) 00834 { 00835 $policy =& $result['policies'][$key]; 00836 if ( isset( $policy['SiteAccess'] ) ) 00837 { 00838 $policyChecked = true; 00839 if ( in_array( eZSys::ezcrc32( $site ), $policy['SiteAccess'] ) ) 00840 { 00841 $hasAccess = true; 00842 break; 00843 } 00844 } 00845 if ( $hasAccess ) 00846 break; 00847 } 00848 if ( !$policyChecked ) 00849 $hasAccess = true; 00850 } 00851 else if ( $accessWord == 'yes' ) 00852 { 00853 $hasAccess = true; 00854 } 00855 else if ( $accessWord == 'no' ) 00856 { 00857 $hasAccess = false; 00858 } 00859 return $hasAccess; 00860 } 00861 00862 /*! 00863 Checks if the current user has access rights to virtual element \a virtual 00864 on site \a $site. 00865 \return \c true if the user proper access. 00866 */ 00867 function userHasVirtualAccess( $site, $virtual ) 00868 { 00869 $this->appendLogEntry( "Can access '$site' and '$virtual'", 'CS:userHasVirtualAccess' ); 00870 return true; 00871 } 00872 00873 /*! 00874 Detects a possible/valid site-name in start of a path. 00875 \return The name of the site that was detected or \c false if not site could be detected 00876 */ 00877 function currentSiteFromPath( $path ) 00878 { 00879 $this->appendLogEntry( "start path: $path", 'CS:currentSiteFromPath' ); 00880 00881 $indexDir = eZSys::indexDir(); 00882 00883 // Remove indexDir if used in non-virtualhost mode. 00884 if ( preg_match( "#^" . preg_quote( $indexDir ) . "(.+)$#", $path, $matches ) ) 00885 { 00886 $path = $matches[1]; 00887 } 00888 00889 $this->appendLogEntry( "indexdir: $path", 'CS:currentSiteFromPath' ); 00890 00891 // Get the list of available sites. 00892 $sites = $this->availableSites(); 00893 00894 foreach ( $sites as $site ) 00895 { 00896 // Check if given path starts with this site-name, if so: return it. 00897 if ( preg_match( "#^/" . preg_quote( $site ) . "(.*)$#", $path, $matches ) ) 00898 { 00899 $this->appendLogEntry( "site $site: $path", 'CS:currentSiteFromPath' ); 00900 return $site ; 00901 } 00902 } 00903 00904 $this->appendLogEntry( "no valid site was found..", 'CS:currentSiteFromPath' ); 00905 return false ; 00906 } 00907 00908 /*! 00909 Removes the www-dir and indexfile from the URL. 00910 */ 00911 function processURL( $url ) 00912 { 00913 $this->appendLogEntry( "start url: $url", 'CS:processURL' ); 00914 $indexDir = eZSys::indexDir(); 00915 $len = strlen( $indexDir ); 00916 00917 if ( $indexDir == substr( $url, 0, $len ) ) 00918 { 00919 $url = substr( $url, $len ); 00920 } 00921 00922 // Remove the starting / if there is one 00923 // the rest of the operation code expects this to not be present 00924 if ( strlen( $url ) > 0 and $url[0] == '/' ) 00925 $url = substr( $url, 1 ); 00926 00927 $this->appendLogEntry( "indexdir url: $url", 'CS:processURL' ); 00928 return $url; 00929 } 00930 00931 function headers() 00932 { 00933 header( "WebDAV-Powered-By: eZ Publish" ); 00934 } 00935 00936 /*! 00937 Takes the first path element from \a $path and removes it from 00938 the path, the extracted part will be placed in \a $name. 00939 \return A string containing the rest of the path, 00940 the path will not contain a starting slash. 00941 \param $path A string defining a path of elements delimited by a slash, 00942 if the path starts with a slash it will be removed. 00943 \param[out] $element The name of the first path element without any slashes. 00944 00945 \code 00946 $path = '/path/to/item/'; 00947 $newPath = eZWebDAVContentServer::splitFirstPathElement( $path, $root ); 00948 print( $root ); // prints 'path', $newPath is now 'to/item/' 00949 $newPath = eZWebDAVContentServer::splitFirstPathElement( $newPath, $second ); 00950 print( $second ); // prints 'to', $newPath is now 'item/' 00951 $newPath = eZWebDAVContentServer::splitFirstPathElement( $newPath, $third ); 00952 print( $third ); // prints 'item', $newPath is now '' 00953 \endcode 00954 */ 00955 function splitFirstPathElement( $path, &$element ) 00956 { 00957 if ( $path[0] == '/' ) 00958 $path = substr( $path, 1 ); 00959 $pos = strpos( $path, '/' ); 00960 if ( $pos === false ) 00961 { 00962 $element = $path; 00963 $path = ''; 00964 } 00965 else 00966 { 00967 $element = substr( $path, 0, $pos ); 00968 $path = substr( $path, $pos + 1 ); 00969 } 00970 return $path; 00971 } 00972 00973 /*! 00974 Takes the last path element from \a $path and removes it from 00975 the path, the extracted part will be placed in \a $name. 00976 \return A string containing the rest of the path, 00977 the path will not contain the ending slash. 00978 \param $path A string defining a path of elements delimited by a slash, 00979 if the path ends with a slash it will be removed. 00980 \param[out] $element The name of the first path element without any slashes. 00981 00982 \code 00983 $path = '/path/to/item/'; 00984 $newPath = eZWebDAVContentServer::splitLastPathElement( $path, $root ); 00985 print( $root ); // prints 'item', $newPath is now '/path/to' 00986 $newPath = eZWebDAVContentServer::splitLastPathElement( $newPath, $second ); 00987 print( $second ); // prints 'to', $newPath is now '/path' 00988 $newPath = eZWebDAVContentServer::splitLastPathElement( $newPath, $third ); 00989 print( $third ); // prints 'path', $newPath is now '' 00990 \endcode 00991 */ 00992 function splitLastPathElement( $path, &$element ) 00993 { 00994 $len = strlen( $path ); 00995 if ( $len > 0 and $path[$len - 1] == '/' ) 00996 $path = substr( $path, 0, $len - 1 ); 00997 $pos = strrpos( $path, '/' ); 00998 if ( $pos === false ) 00999 { 01000 $element = $path; 01001 $path = ''; 01002 } 01003 else 01004 { 01005 $element = substr( $path, $pos + 1 ); 01006 $path = substr( $path, 0, $pos ); 01007 } 01008 return $path; 01009 } 01010 01011 /*! 01012 \private 01013 \return A path that corresponds to the internal path of nodes. 01014 */ 01015 function internalNodePath( $virtualFolder, $collection ) 01016 { 01017 // All root nodes needs to prepend their name to get the correct path 01018 // except for the content root which uses the path directly. 01019 if ( $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 01020 { 01021 $nodePath = 'media'; 01022 if ( strlen( $collection ) > 0 ) 01023 $nodePath .= '/' . $collection; 01024 } 01025 else 01026 { 01027 $nodePath = $collection; 01028 } 01029 return $nodePath; 01030 } 01031 01032 /*! 01033 Attempts to fetch a possible/existing node by translating 01034 the inputted string/path to a node-number. 01035 */ 01036 function fetchNodeByTranslation( $nodePathString ) 01037 { 01038 // Get rid of possible extensions, remove .jpeg .txt .html etc.. 01039 $nodePathString = $this->fileBasename( $nodePathString ); 01040 01041 // Strip away last slash 01042 if ( strlen( $nodePathString ) > 0 and 01043 $nodePathString[strlen( $nodePathString ) - 1] == '/' ) 01044 { 01045 $nodePathString = substr( $nodePathString, 0, strlen( $nodePathString ) - 1 ); 01046 } 01047 01048 if ( strlen( $nodePathString ) > 0 ) 01049 { 01050 $nodePathString = eZURLAliasML::convertPathToAlias( $nodePathString ); 01051 } 01052 01053 // Attempt to get nodeID from the URL. 01054 $nodeID = eZURLAliasML::fetchNodeIDByPath( $nodePathString ); 01055 if ( $nodeID ) 01056 { 01057 $this->appendLogEntry( "NodeID: $nodeID", 'CS:fetchNodeByTranslation' ); 01058 } 01059 else 01060 { 01061 $this->appendLogEntry( "No nodeID", 'CS:fetchNodeByTranslation' ); 01062 return false; 01063 } 01064 01065 // Attempt to fetch the node. 01066 $node = eZContentObjectTreeNode::fetch( $nodeID ); 01067 01068 // Return the node. 01069 return $node; 01070 } 01071 01072 /*! 01073 \return The string \a $name without the final suffix (.jpg, .gif etc.) 01074 */ 01075 function fileBasename( $name ) 01076 { 01077 $pos = strrpos( $name, '.' ); 01078 if ( $pos !== false ) 01079 { 01080 $name = substr( $name, 0, $pos ); 01081 } 01082 return $name; 01083 } 01084 01085 /*! 01086 Attempts to fetch a possible node by translating 01087 the inputted string/path to a node-number. The last 01088 section of the path is removed before the actual 01089 translation: hence, the PARENT node is returned. 01090 */ 01091 function fetchParentNodeByTranslation( $nodePathString ) 01092 { 01093 // Strip extensions. E.g. .jpg 01094 $nodePathString = $this->fileBasename( $nodePathString ); 01095 01096 // Strip away last slash 01097 if ( strlen( $nodePathString ) > 0 and 01098 $nodePathString[strlen( $nodePathString ) - 1] == '/' ) 01099 { 01100 $nodePathString = substr( $nodePathString, 0, strlen( $nodePathString ) - 1 ); 01101 } 01102 01103 $nodePathString = $this->splitLastPathElement( $nodePathString, $element ); 01104 01105 if ( strlen( $nodePathString ) == 0 ) 01106 $nodePathString = '/'; 01107 01108 $nodePathString = eZURLAliasML::convertPathToAlias( $nodePathString ); 01109 01110 // Attempt to translate the URL to something like "/content/view/full/84". 01111 $translateResult = eZURLAliasML::translate( $nodePathString ); 01112 01113 // handle redirects 01114 while ( $nodePathString == 'error/301' ) 01115 { 01116 $nodePathString = $translateResult; 01117 01118 $translateResult = eZURLAliasML::translate( $nodePathString ); 01119 } 01120 01121 // Get the ID of the node (which is the last part of the translated path). 01122 if ( preg_match( "#^content/view/full/([0-9]+)$#", $nodePathString, $matches ) ) 01123 { 01124 $nodeID = $matches[1]; 01125 $this->appendLogEntry( "NodeID: $nodeID", 'CS:fetchParentNodeByTranslation' ); 01126 } 01127 else 01128 { 01129 $this->appendLogEntry( "Root node", 'CS:fetchParentNodeByTranslation' ); 01130 $nodeID = 2; 01131 } 01132 01133 // Attempt to fetch the node. 01134 $node = eZContentObjectTreeNode::fetch( $nodeID ); 01135 01136 // Return the node. 01137 return $node; 01138 } 01139 01140 /*! 01141 \return An array containing the names of all folders in the virtual root. 01142 */ 01143 function virtualFolderList() 01144 { 01145 return array( eZWebDAVContentServer::virtualContentFolderName(), eZWebDAVContentServer::virtualMediaFolderName() ); 01146 } 01147 01148 /*! 01149 \return An array containing the names of all folders in the virtual root. 01150 */ 01151 function virtualFolderInfoList() 01152 { 01153 return array( array( 'name' => eZWebDAVContentServer::virtualContentFolderName() ), 01154 array( 'name' => eZWebDAVContentServer::virtualMediaFolderName() ) ); 01155 } 01156 01157 /*! 01158 \return An array containing the names of all files in the virtual root. 01159 */ 01160 function virtualFileList() 01161 { 01162 return array( basename( eZWebDAVContentServer::virtualInfoFileName() ) ); 01163 } 01164 01165 /*! 01166 \return An array containing the names of all files in the virtual root. 01167 */ 01168 function virtualFileInfoList() 01169 { 01170 return array( array( 'name' => basename( eZWebDAVContentServer::virtualInfoFileName() ), 01171 'filepath' => eZWebDAVContentServer::virtualInfoFileName() ) ); 01172 } 01173 01174 /*! 01175 \return An array containing the names of all elements in the virtual root. 01176 */ 01177 function virtualList() 01178 { 01179 return array_merge( eZWebDAVContentServer::virtualFolderList(), 01180 eZWebDAVContentServer::virtualFileList() ); 01181 } 01182 01183 /*! 01184 \return An array containing the names of all elements in the virtual root. 01185 */ 01186 function virtualInfoList() 01187 { 01188 return array_merge( eZWebDAVContentServer::virtualFolderInfoList(), 01189 eZWebDAVContentServer::virtualFileInfoList() ); 01190 } 01191 01192 /*! 01193 Functions related to creation collections 01194 @{ 01195 */ 01196 01197 /*! 01198 Builds and returns the content of the virtual start fodler 01199 for a site. The virtual startfolder is an intermediate step 01200 between the site-list and actual content. This directory 01201 contains the "content" folder which leads to the site's 01202 actual content. 01203 */ 01204 function fetchVirtualSiteContent( $site, $depth, $properties ) 01205 { 01206 $this->appendLogEntry( "Script URL.." . eZSys::instance()->RequestURI, 'CS:fetchVirtualSiteContent' ); 01207 // Location of the info file. 01208 $infoFile = $_SERVER['DOCUMENT_ROOT'] . '/' . eZWebDAVContentServer::virtualInfoFileName(); 01209 01210 // Always add the current collection 01211 $contentEntry = array(); 01212 $contentEntry["name"] = eZSys::instance()->RequestURI; 01213 $contentEntry["size"] = 0; 01214 $contentEntry["mimetype"] = 'httpd/unix-directory'; 01215 $contentEntry["ctime"] = filectime( 'settings/siteaccess/' . $site ); 01216 $contentEntry["mtime"] = filemtime( 'settings/siteaccess/' . $site ); 01217 $contentEntry["href"] = eZSys::instance()->RequestURI; 01218 $entries[] = $contentEntry; 01219 01220 $defctime = $contentEntry['ctime']; 01221 $defmtime = $contentEntry['mtime']; 01222 01223 if ( $depth > 0 ) 01224 { 01225 $scriptURL = eZSys::instance()->RequestURI; 01226 if ( $scriptURL{strlen($scriptURL) - 1} != "/" ) 01227 $scriptURL .= "/"; 01228 01229 // Set up attributes for the virtual content folder: 01230 foreach ( $this->virtualInfoList() as $info ) 01231 { 01232 $name = $info['name']; 01233 $filepath = false; 01234 if ( isset( $info['filepath'] ) ) 01235 $filepath = $info['filepath']; 01236 $size = 0; 01237 if ( $filepath === false or file_exists( $filepath ) ) 01238 { 01239 $mimeType = 'httpd/unix-directory'; 01240 if ( $filepath !== false ) 01241 { 01242 $mimeInfo = eZMimeType::findByFileContents( $filepath ); 01243 $mimeType = $mimeInfo['name']; 01244 $ctime = filectime( $filepath ); 01245 $mtime = filemtime( $filepath ); 01246 $size = filesize( $filepath ); 01247 } 01248 else 01249 { 01250 $ctime = $defctime; 01251 $mtime = $defmtime; 01252 } 01253 01254 $entry = array(); 01255 $entry["name"] = $name; 01256 $entry["size"] = $size; 01257 $entry["mimetype"] = $mimeType; 01258 $entry["ctime"] = $ctime; 01259 $entry["mtime"] = $mtime; 01260 $entry["href"] = $scriptURL . $name; 01261 $entries[] = $entry; 01262 } 01263 } 01264 } 01265 01266 return $entries; 01267 } 01268 01269 /*! 01270 Builds a content-list of available sites and returns it. 01271 */ 01272 function fetchSiteListContent( $depth, $properties ) 01273 { 01274 // At the end: we'll return an array of entry-arrays. 01275 $entries = array(); 01276 01277 // An entry consists of several attributes (name, size, etc). 01278 $contentEntry = array(); 01279 $entries = array(); 01280 01281 // Set up attributes for the virtual site-list folder: 01282 $contentEntry["name"] = '/'; 01283 $contentEntry["href"] = eZSys::instance()->RequestURI; 01284 $contentEntry["size"] = 0; 01285 $contentEntry["mimetype"] = 'httpd/unix-directory'; 01286 $contentEntry["ctime"] = filectime( 'var' ); 01287 $contentEntry["mtime"] = filemtime( 'var' ); 01288 01289 $entries[] = $contentEntry; 01290 01291 if ( $depth > 0 ) 01292 { 01293 // Get list of available sites. 01294 $sites = $this->availableSites(); 01295 01296 // For all available sites: 01297 foreach ( $sites as $site ) 01298 { 01299 // Set up attributes for the virtual site-list folder: 01300 $contentEntry["name"] = eZSys::instance()->RequestURI . $site; 01301 $contentEntry["size"] = 0; 01302 $contentEntry["mimetype"] = 'httpd/unix-directory'; 01303 $contentEntry["ctime"] = filectime( 'settings/siteaccess/' . $site ); 01304 $contentEntry["mtime"] = filemtime( 'settings/siteaccess/' . $site ); 01305 01306 if ( eZSys::instance()->RequestURI == '/' ) 01307 { 01308 $contentEntry["href"] = $contentEntry["name"]; 01309 } 01310 else 01311 { 01312 $contentEntry["href"] = eZSys::instance()->RequestURI . $contentEntry["name"]; 01313 } 01314 01315 $entries[] = $contentEntry; 01316 } 01317 } 01318 01319 return $entries; 01320 } 01321 01322 /*! 01323 Gets and returns the content of an actual node. 01324 List of other nodes belonging to the target node 01325 (one level below it) will be returned. 01326 */ 01327 function fetchContentList( &$node, $target, $depth, $properties ) 01328 { 01329 // We'll return an array of entries (which is an array of attributes). 01330 $entries = array(); 01331 01332 if ( $depth == 1 ) 01333 { 01334 // Get all the children of the target node. 01335 $subTree = $node->subTree( array ( 'Depth' => 1 ) ); 01336 01337 // Build the entries array by going through all the 01338 // nodes in the subtree and getting their attributes: 01339 foreach ( $subTree as $someNode ) 01340 { 01341 $entries[] = $this->fetchNodeInfo( $someNode ); 01342 } 01343 } 01344 01345 // Always include the information about the current level node 01346 $thisNodeInfo = array(); 01347 $thisNodeInfo = $this->fetchNodeInfo( $node ); 01348 $thisNodeInfo["href"] = eZSys::instance()->RequestURI; 01349 $entries[] = $thisNodeInfo; 01350 01351 // Return the content of the target. 01352 return $entries; 01353 } 01354 01355 /*! 01356 \return \c true if the object \a $object should always be considered a folder. 01357 */ 01358 function isObjectFolder( $object, &$class ) 01359 { 01360 $classIdentifier = $class->attribute( 'identifier' ); 01361 if ( $this->FolderClasses === null ) 01362 { 01363 $webdavINI = eZINI::instance( eZWebDAVContentServer::WEBDAV_INI_FILE ); 01364 $folderClasses = array(); 01365 if ( $webdavINI->hasGroup( 'GeneralSettings' ) and 01366 $webdavINI->hasVariable( 'GeneralSettings', 'FolderClasses' ) ) 01367 { 01368 $folderClasses = $webdavINI->variable( 'GeneralSettings', 'FolderClasses' ); 01369 } 01370 $this->FolderClasses = $folderClasses; 01371 } 01372 return in_array( $classIdentifier, $this->FolderClasses ); 01373 } 01374 01375 /*! 01376 Gathers information about a given node (specified as parameter). 01377 */ 01378 function fetchNodeInfo( &$node ) 01379 { 01380 // When finished, we'll return an array of attributes/properties. 01381 $entry = array(); 01382 01383 // Grab settings from the ini file: 01384 $webdavINI = eZINI::instance( eZWebDAVContentServer::WEBDAV_INI_FILE ); 01385 $iniSettings = $webdavINI->variable( 'DisplaySettings', 'FileAttribute' ); 01386 01387 $classIdentifier = $node->attribute( 'class_identifier' ); 01388 01389 $object = $node->attribute( 'object' ); 01390 01391 // By default, everything is displayed as a folder: 01392 // Trim the name of the node, it is in some cases whitespace in eZ Publish 01393 $entry["name"] = trim( $node->attribute( 'name' ) ); 01394 $entry["size"] = 0; 01395 $entry["mimetype"] = 'httpd/unix-directory'; 01396 $entry["ctime"] = $object->attribute( 'published' ); 01397 $entry["mtime"] = $object->attribute( 'modified' ); 01398 01399 $upload = new eZContentUpload(); 01400 $info = $upload->objectFileInfo( $object ); 01401 $suffix = ''; 01402 $class = $object->contentClass(); 01403 $isObjectFolder = $this->isObjectFolder( $object, $class ); 01404 01405 if ( $isObjectFolder ) 01406 { 01407 // We do nothing, the default is to see it as a folder 01408 } 01409 else if ( $info ) 01410 { 01411 $filePath = $info['filepath']; 01412 $entry["mimetype"] = false; 01413 $entry["size"] = false; 01414 if ( isset( $info['filesize'] ) ) 01415 $entry['size'] = $info['filesize']; 01416 if ( isset( $info['mime_type'] ) ) 01417 $entry['mimetype'] = $info['mime_type']; 01418 01419 // Fill in information from the actual file if they are missing. 01420 $file = eZClusterFileHandler::instance( $filePath ); 01421 if ( !$entry['size'] and $file->exists() ) 01422 { 01423 $entry["size"] = $file->size(); 01424 } 01425 if ( !$entry['mimetype'] ) 01426 { 01427 $mimeInfo = eZMimeType::findByURL( $filePath ); 01428 $entry["mimetype"] = $mimeInfo['name']; 01429 $suffix = $mimeInfo['suffix']; 01430 if ( strlen( $suffix ) > 0 ) 01431 $entry["name"] .= '.' . $suffix; 01432 } 01433 else 01434 { 01435 // eZMimeType returns first suffix in its list 01436 // this could be another one than the original file extension 01437 // so let's try to get the suffix from the file path first 01438 $suffix = eZFile::suffix( $filePath ); 01439 if ( !$suffix ) 01440 { 01441 $mimeInfo = eZMimeType::findByName( $entry['mimetype'] ); 01442 $suffix = $mimeInfo['suffix']; 01443 } 01444 if ( strlen( $suffix ) > 0 ) 01445 $entry["name"] .= '.' . $suffix; 01446 } 01447 01448 if ( $file->exists() ) 01449 { 01450 $entry["ctime"] = $file->mtime(); 01451 $entry["mtime"] = $file->mtime(); 01452 } 01453 } 01454 else 01455 { 01456 // Here we only show items as folders if they have 01457 // is_container set to true, otherwise it's an unknown binary file 01458 if ( !$class->attribute( 'is_container' ) ) 01459 { 01460 $entry['mimetype'] = 'application/octet-stream'; 01461 } 01462 } 01463 01464 $scriptURL = eZSys::instance()->RequestURI; 01465 if ( strlen( $scriptURL ) > 0 and $scriptURL[ strlen( $scriptURL ) - 1 ] != "/" ) 01466 $scriptURL .= "/"; 01467 01468 $trimmedScriptURL = trim( $scriptURL, '/' ); 01469 $scriptURLParts = explode( '/', $trimmedScriptURL ); 01470 01471 $siteAccess = $scriptURLParts[0]; 01472 $virtualFolder = $scriptURLParts[1]; 01473 01474 $startURL = '/' . $siteAccess . '/' . $virtualFolder . '/'; 01475 01476 // Set the href attribute (note that it doesn't just equal the name). 01477 if ( !isset( $entry['href'] ) ) 01478 { 01479 if ( strlen( $suffix ) > 0 ) 01480 $suffix = '.' . $suffix; 01481 01482 $alias = $node->urlAlias(); 01483 if ( $virtualFolder == eZWebDAVContentServer::virtualMediaFolderName() ) 01484 { 01485 // remove the real media node url alias, the virtual media folder is already in $startURL 01486 $aliasParts = explode( '/', $alias ); 01487 array_shift( $aliasParts ); 01488 $alias = implode( '/', $aliasParts ); 01489 } 01490 $entry["href"] = $startURL . $alias . $suffix; 01491 } 01492 // Return array of attributes/properties (name, size, mime, times, etc.). 01493 return $entry; 01494 } 01495 01496 /*! 01497 @} 01498 */ 01499 01500 /*! 01501 Creates a new folder under the given target node. 01502 */ 01503 function createFolder( $parentNode, $target ) 01504 { 01505 // Grab settings from the ini file: 01506 $webdavINI = eZINI::instance( eZWebDAVContentServer::WEBDAV_INI_FILE ); 01507 $folderClassID = $webdavINI->variable( 'FolderSettings', 'FolderClass' ); 01508 $languageCode = eZContentObject::defaultLanguage(); 01509 01510 $contentObject = eZContentObject::createWithNodeAssignment( $parentNode, $folderClassID, $languageCode ); 01511 if ( $contentObject ) 01512 { 01513 $db = eZDB::instance(); 01514 $db->begin(); 01515 $version = $contentObject->version( 1 ); 01516 $version->setAttribute( 'status', eZContentObjectVersion::STATUS_DRAFT ); 01517 $version->store(); 01518 01519 $contentObjectID = $contentObject->attribute( 'id' ); 01520 $contentObjectAttributes = $version->contentObjectAttributes(); 01521 01522 $contentObjectAttributes[0]->setAttribute( 'data_text', basename( $target ) ); 01523 $contentObjectAttributes[0]->store(); 01524 $db->commit(); 01525 01526 $operationResult = eZOperationHandler::execute( 'content', 'publish', array( 'object_id' => $contentObjectID, 01527 'version' => 1 ) ); 01528 return eZWebDAVServer::OK_CREATED; 01529 } 01530 else 01531 { 01532 $this->appendLogEntry( "Not allowed", 'CS:createFolder' ); 01533 return eZWebDAVServer::FAILED_FORBIDDEN; 01534 } 01535 } 01536 01537 /*! 01538 Gets and returns a list of the available sites (from site.ini). 01539 */ 01540 function availableSites() 01541 { 01542 // The site list is an array of strings. 01543 $siteList = array(); 01544 01545 // Grab the sitelist from the ini file. 01546 $webdavINI = eZINI::instance(); 01547 $siteList = $webdavINI->variable( 'SiteSettings', 'SiteList' ); 01548 01549 // Return the site list. 01550 return $siteList ; 01551 } 01552 01553 static function virtualContentFolderName() 01554 { 01555 return ezpI18n::tr( 'kernel/content', "Content" ); 01556 } 01557 01558 static function virtualMediaFolderName() 01559 { 01560 return ezpI18n::tr( 'kernel/content', "Media" ); 01561 } 01562 01563 static function virtualInfoFileName() 01564 { 01565 $infoFile = eZSys::varDirectory() . '/webdav/root/info.txt'; 01566 return $infoFile; 01567 } 01568 01569 /// \privatesection 01570 /// Contains an array with classes that are considered folder 01571 public $FolderClasses; 01572 } 01573 ?>