[ Index ] |
|
Code source de eZ Publish 3.9.0 |
1 <?php 2 // 3 // Definition of eZWebDAVServer class 4 // 5 // Created on: <01-Aug-2003 13:13:13 bh> 6 // 7 // SOFTWARE NAME: eZ publish 8 // SOFTWARE RELEASE: 3.9.0 9 // BUILD VERSION: 17785 10 // COPYRIGHT NOTICE: Copyright (C) 1999-2006 eZ systems AS 11 // SOFTWARE LICENSE: GNU General Public License v2.0 12 // NOTICE: > 13 // This program is free software; you can redistribute it and/or 14 // modify it under the terms of version 2.0 of the GNU General 15 // Public License as published by the Free Software Foundation. 16 // 17 // This program is distributed in the hope that it will be useful, 18 // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 // GNU General Public License for more details. 21 // 22 // You should have received a copy of version 2.0 of the GNU General 23 // Public License along with this program; if not, write to the Free 24 // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 25 // MA 02110-1301, USA. 26 // 27 // 28 29 /*! \file ezwebdavserver.php 30 WebDAV server base class. 31 */ 32 33 /*! \defgroup eZWebDAV WebDAV system */ 34 35 /*! 36 \class eZWebDAVServer ezwebdavserver.php 37 \ingroup eZWebDAV 38 \brief Virtual base class for implementing WebDAV servers. 39 40 \todo Add support for propall and propname 41 */ 42 43 include_once ( 'lib/ezxml/classes/ezxml.php' ); 44 include_once ( "lib/ezutils/classes/ezmimetype.php" ); 45 include_once ( 'lib/ezfile/classes/ezdir.php' ); 46 47 // General status OK return codes: 48 define( "EZ_WEBDAV_OK", 10 ); 49 define( "EZ_WEBDAV_OK_SILENT", 11 ); 50 define( "EZ_WEBDAV_OK_CREATED", 12 ); 51 define( "EZ_WEBDAV_OK_OVERWRITE", 13 ); 52 53 // General status FAILED return codes: 54 define( "EZ_WEBDAV_FAILED_FORBIDDEN", 30 ); 55 define( "EZ_WEBDAV_FAILED_NOT_FOUND", 31 ); 56 define( "EZ_WEBDAV_FAILED_EXISTS", 32 ); 57 define( "EZ_WEBDAV_FAILED_CONFLICT", 33 ); 58 define( "EZ_WEBDAV_FAILED_PRECONDITION", 34 ); 59 define( "EZ_WEBDAV_FAILED_LOCKED", 35 ); 60 define( "EZ_WEBDAV_FAILED_BAD_GATEWAY", 36 ); 61 define( "EZ_WEBDAV_FAILED_STORAGE_FULL", 37 ); 62 define( "EZ_WEBDAV_FAILED_UNSUPPORTED", 38 ); 63 64 65 // File timestamp formats (MUST be correct, or else: Won't work in MSIE...). 66 // Yes, the two timestamps are actually in different formats. Don't touch! 67 define( "EZ_WEBDAV_CTIME_FORMAT", "Y-m-d\\TH:i:s\\Z" ); 68 define( "EZ_WEBDAV_MTIME_FORMAT", "D, d M Y H:i:s" ); 69 70 71 // Get the location of the correct var directory. 72 $varDir = eZSys::varDirectory(); 73 74 75 // Temporary (uploaded) file stuff: 76 define( "EZ_WEBDAV_TEMP_DIRECTORY", $varDir . "/webdav/tmp" ); 77 define( "EZ_WEBDAV_ROOT_DIRECTORY", $varDir . "/webdav/root" ); 78 define( "EZ_WEBDAV_TEMP_FILE_PREFIX", "eZWebDAVUpload_" ); 79 80 81 // Check if necessary temp. dir. actually exists, if not: create it! 82 if ( !file_exists( EZ_WEBDAV_TEMP_DIRECTORY ) ) 83 { 84 eZDir::mkdir( EZ_WEBDAV_TEMP_DIRECTORY, eZDir::directoryPermission(), true); 85 } 86 87 // Check if necessary root dir. actually exists, if not: create it! 88 if ( !file_exists( EZ_WEBDAV_ROOT_DIRECTORY ) ) 89 { 90 eZDir::mkdir( EZ_WEBDAV_ROOT_DIRECTORY, eZDir::directoryPermission(), true); 91 } 92 93 94 /*! 95 \return \c true if logging is enabled. 96 \deprecated Use eZWebDAVServer::isLoggingEnabled() instead. 97 */ 98 function eZWebDavCheckLogSetting() 99 { 100 return eZWebDAVServer::isLoggingEnabled(); 101 } 102 103 /*! 104 Logs the string \a $logString to the logfile /tmp/webdavlog.txt 105 if logging is enabled. 106 \deprecated Appending to log file is now done through appendLogEntry in the webdav server class. 107 */ 108 function append_to_log( $logString ) 109 { 110 return eZWebDAVServer::appendLogEntry( $logString ); 111 } 112 113 /*! 114 Logs the string \a $logString to the logfile /tmp/webdavlog.txt 115 if logging is enabled. 116 \deprecated Appending to log file is now done through appendLogEntry in the webdav server class. 117 */ 118 function eZWebDavAppendToLog( $logString ) 119 { 120 return eZWebDAVServer::appendLogEntry( $logString ); 121 } 122 123 class eZWebDAVServer 124 { 125 /*! Constructor of eZWebDAVServer; 126 disables PHP error messages. 127 */ 128 function eZWebDAVServer() 129 { 130 $this->setupXMLOutputCharset(); 131 } 132 133 function setServerRoot( $rootDir ) 134 { 135 if ( file_exists ( $rootDir ) ) 136 { 137 $this->ServerRootDir = $rootDir; 138 139 return true; 140 } 141 else 142 { 143 return false; 144 } 145 } 146 147 /*! Server process function. 148 Dumps a custom header, sets the path and finally 149 checks what the clients wants. Calls the appropriate 150 virtual function (based on the client request). 151 */ 152 function processClientRequest() 153 { 154 $this->appendLogEntry( "WebDAV server started...", 'processClientRequest' ); 155 $this->XMLBodyRead = false; 156 157 // Dump some custom header/info. 158 $this->headers(); 159 160 // Clear file status cache (just in case). 161 clearstatcache(); 162 163 // Convert the requested URI string to non-bogus format. 164 $target = urldecode( $_SERVER["REQUEST_URI"] ); 165 $target = $this->processURL( $target ); 166 167 $this->appendLogEntry( "----------------------------------------" ); 168 $this->appendLogEntry( "Client says: " . $_SERVER["REQUEST_METHOD"], 'processClientRequest' ); 169 $this->appendLogEntry( "Target: " . $_SERVER["REQUEST_URI"], 'processClientRequest' ); 170 $this->appendLogEntry( "----------------------------------------" ); 171 172 $status = EZ_WEBDAV_FAILED_NOT_FOUND; 173 174 switch ( $_SERVER["REQUEST_METHOD"] ) 175 { 176 // OPTIONS (Server ID reply.) 177 case "OPTIONS": 178 { 179 $this->appendLogEntry( "OPTIONS was issued from client.", 'processClientRequest' ); 180 $options = $this->options( $target ); 181 $status = $this->outputOptions( $options ); 182 } break; 183 184 // PROPFIND (Show dir/collection content.) 185 case "PROPFIND": 186 { 187 $this->appendLogEntry( "PROPFIND was issued from client.", 'processClientRequest' ); 188 189 $depth = $_SERVER['HTTP_DEPTH']; 190 if ( $depth != 0 and $depth != 1 and $depth != "infinity" ) 191 $depth = "infinity"; 192 $this->appendLogEntry( "Depth: $depth.", 'processClientRequest' ); 193 194 // Find which properties were requested 195 // $this->appendLogEntry( $xmlBody, 'xmlbody' ); 196 $xml = new eZXML(); 197 $bodyTree = $xml->domTree( $this->xmlBody() ); 198 $requestedProperties = array(); 199 if ( $bodyTree ) 200 { 201 $propfindNode =& $bodyTree->root(); 202 $propNode =& $propfindNode->elementByName( 'prop' ); 203 if ( $propNode ) 204 { 205 $propList = $propNode->children(); 206 foreach ( $propList as $node ) 207 { 208 $name = $node->name(); 209 $requestedProperties[] = $name; 210 } 211 } 212 else 213 { 214 $allpropNode =& $propfindNode->elementByName( 'allprop' ); 215 if ( $allpropNode ) 216 { 217 // The server must return all possible properties 218 $requestedProperties = true; 219 } 220 else 221 { 222 $propnameNode =& $propfindNode->elementByName( 'propname' ); 223 if ( $propnameNode ) 224 { 225 // The server must return only the names of all properties 226 $requestedProperties = false; 227 } 228 } 229 } 230 } 231 232 $collection = $this->getCollectionContent( $target, $depth, $requestedProperties ); 233 if ( is_array( $collection ) ) 234 { 235 $status = $this->outputCollectionContent( $collection, $requestedProperties ); 236 } 237 else 238 { 239 $status = $collection; 240 } 241 } break; 242 243 // HEAD (Check if file/resource exists.) 244 case "HEAD": 245 { 246 $this->appendLogEntry( "HEAD was issued from client.", 'processClientRequest' ); 247 $data = $this->get( $target ); 248 $status = $this->outputSendDataToClient( $data, true ); 249 } break; 250 251 // GET (Download a file/resource from server to client.) 252 case "GET": 253 { 254 $this->appendLogEntry( "GET was issued from client.", 'processClientRequest' ); 255 $data = $this->get( $target ); 256 $status = $this->outputSendDataToClient( $data ); 257 } break; 258 259 // PUT (Upload a file/resource from client to server.) 260 case "PUT": 261 { 262 $this->appendLogEntry( "PUT was issued from client.", 'processClientRequest' ); 263 $status = EZ_WEBDAV_OK_CREATED; 264 265 // Attempt to get file/resource sent from client/browser. 266 $tempFile = $this->storeUploadedFile( $target ); 267 268 // If there was an actual file: 269 if ( $tempFile ) 270 { 271 // Attempt to do something with it (copy/whatever). 272 $status = $this->put( $target, $tempFile ); 273 274 unlink( $tempFile ); 275 include_once ( 'lib/ezfile/classes/ezdir.php' ); 276 eZDir::cleanupEmptyDirectories( dirname( $tempFile ) ); 277 } 278 // Else: something went wrong... 279 else 280 { 281 $status = EZ_WEBDAV_FAILED_FORBIDDEN; 282 } 283 284 } break; 285 286 // MKCOL (Create a directory/collection.) 287 case "MKCOL": 288 { 289 $this->appendLogEntry( "MKCOL was issued from client.", 'processClientRequest' ); 290 if ( strlen( $this->xmlBody() ) > 0 ) 291 { 292 $this->appendLogEntry( "MKCOL body error.", 'processClientRequest' ); 293 $status = EZ_WEBDAV_FAILED_FORBIDDEN; 294 } 295 else 296 { 297 $status = $this->mkcol( $target ); 298 } 299 } break; 300 301 // COPY (Copy a resource/collection from one location to another.) 302 case "COPY": 303 { 304 $this->appendLogEntry( "COPY was issued from client.", 'processClientRequest' ); 305 306 $source = $target; 307 $url = parse_url( $_SERVER["HTTP_DESTINATION"] ); 308 $destination = urldecode( $url["path"] ); 309 $destination = $this->processURL( $destination ); 310 $status = $this->copy( $source, $destination ); 311 } break; 312 313 // MOVE (Move a resource/collection from one location to another.) 314 case "MOVE": 315 { 316 $this->appendLogEntry( "MOVE was issued from client.", 'processClientRequest' ); 317 $source = $target; 318 $url = parse_url( $_SERVER["HTTP_DESTINATION"] ); 319 $destination = urldecode( $url["path"] ); 320 $destination = $this->processURL( $destination ); 321 $status = $this->move( $source, $destination ); 322 } break; 323 324 // DELETE (Remove a resource/collection.) 325 case "DELETE": 326 { 327 $this->appendLogEntry( "DELETE was issued from client.", 'processClientRequest' ); 328 $status = $this->delete( $target ); 329 } break; 330 331 // Default case: unknown command from client. 332 default: 333 { 334 // __FIX_ME__ 335 } break; 336 } 337 // Read the XML body if it is not used yet, 338 // PHP should discard it but it's a bug in some PHP versions 339 if ( !$this->XMLBodyRead ) 340 $this->flushXMLBody(); 341 342 // Handle the returned status code (post necessary/matching headers, etc.). 343 $this->handle( $status ); 344 } 345 346 /*! 347 \protected 348 Generates HTTP headers with information on what the server supports. 349 \param $options An array with the various options the server supports 350 - methods - An array with methods it can handle, 351 if not supplied it will report all possible methods. 352 - versions - An array with versions this server supports, 353 if not supplied it will return 1,2,<http://apache.org/dav/propset/fs/1>. 354 \return The WebDAV status code 355 */ 356 function outputOptions( $options ) 357 { 358 // Default options 359 $methods = array( 'OPTIONS', 'GET', 'HEAD', 'POST', 'DELETE', 'TRACE', 'PROPFIND', 'PROPPATCH', 'COPY', 'MOVE', 'LOCK', 'UNLOCK' ); 360 $versions = array( '1', '2', '<http://apache.org/dav/propset/fs/1>' ); 361 362 if ( isset( $options['methods'] ) ) 363 $methods = $options['methods']; 364 if ( isset( $options['versions'] ) ) 365 $versions = $options['versions']; 366 367 header( 'Content-Length: 0' ); 368 header( 'MS-Author-Via: DAV' ); 369 header( 'Allow: ' . implode( ', ', $methods ) ); 370 header( 'DAV: ' . implode( ',', $versions ) ); 371 header( 'Content-Type: text/plain; charset=iso-8859-1' ); 372 373 return EZ_WEBDAV_OK_SILENT; 374 } 375 376 /*! 377 \protected 378 Generates the WebDAV XML from \a $collection and outputs using print(). 379 \param $collection An array with elements (e.g dirs/files). 380 Each element consists of: 381 - ctime - The timestamp when the element was created 382 - mtime - The timestamp when the element was last modified 383 - mimetype - The type of element, use httpd/unix-directory for folder like entries 384 - href - URL which points to the element 385 - name - The name of the element 386 - size - The size of the element in bytes, not needed for folders 387 \return The WebDAV status code 388 */ 389 function outputCollectionContent( $collection, $requestedProperties ) 390 { 391 // Sanity check & action: if client forgot to ask, we'll still 392 // play along revealing some basic/default properties. This is 393 // necessary to make it work with Windows XP + SP2. 394 if( count( $requestedProperties ) == 0 ) 395 { 396 $requestedProperties = array( 'displayname', 397 'creationdate', 398 'getlastmodified', 399 'getcontenttype', 400 'getconentlength', 401 'resourcetype' ); 402 } 403 404 // Fix for CaDAVer (text based linux client) -> error if not revealed. 405 // Apparently it does not mess up for other clients so I'll just leave 406 // it without wrapping it inside a client-specific check. 407 if( !in_array( 'getcontenttype', $requestedProperties ) ) 408 { 409 $requestedProperties[] = 'getcontenttype'; 410 } 411 412 $this->appendLogEntry( 'Client requesed ' . 413 count( $requestedProperties ) . 414 ' properties.', 'outputCollectionContent' ); 415 416 $dataCharset = eZWebDAVServer::dataCharset(); 417 $xmlCharset = $this->XMLOutputCharset(); 418 419 $xmlText = "<?xml version=\"1.0\" encoding=\"$xmlCharset\"?>\n" . 420 "<D:multistatus xmlns:D=\"DAV:\">\n"; 421 422 // Maps from WebDAV property names to internal names 423 $nameMap = array( 'displayname' => 'name', 424 'creationdate' => 'ctime', 425 'getlastmodified' => 'mtime', 426 'getcontenttype' => 'mimetype', 427 'getcontentlength' => 'size' ); 428 429 foreach ( $requestedProperties as $requestedProperty ) 430 { 431 if ( !isset( $nameMap[$requestedProperty] ) ) 432 $nameMap[$requestedProperty] = $requestedProperty; 433 } 434 435 // Misc helpful debug info (use when things go wrong..) 436 //$this->appendLogEntry( var_dump( $requestedProperties ), 'outputCollectionContent' ); 437 //$this->appendLogEntry( var_dump( $nameMap ), 'outputCollectionContent' ); 438 //$this->appendLogEntry( var_dump( $collection ), 'outputCollectionContent' ); 439 440 // For all the entries in this dir/collection-array: 441 foreach ( $collection as $entry ) 442 { 443 // Translate the various UNIX timestamps to WebDAV format: 444 $creationTime = date( EZ_WEBDAV_CTIME_FORMAT, $entry['ctime'] ); 445 $modificationTime = date( EZ_WEBDAV_MTIME_FORMAT, $entry['mtime'] ); 446 447 // The following lines take care of URL encoding special characters 448 // for each element (stuff between slashes) in the path. 449 $href = $entry['href']; 450 $pathArray = split( '/', eZWebDAVServer::recode( "$href", $dataCharset, $xmlCharset ) ); 451 452 $encodedPath = '/'; 453 454 foreach( $pathArray as $pathElement ) 455 { 456 if( $pathElement != '' ) 457 { 458 $encodedPath .= rawurlencode( $pathElement ); 459 $encodedPath .= '/'; 460 } 461 } 462 463 $isCollection = $entry['mimetype'] == 'httpd/unix-directory'; 464 465 // If this is not a collection, don't leave a trailing '/' 466 // on the href. If you do, Goliath gets confused. 467 if ( !$isCollection ) 468 $encodedPath = rtrim($encodedPath, '/'); 469 470 $xmlText .= "<D:response>\n" . 471 " <D:href>" . $encodedPath ."</D:href>\n" . 472 " <D:propstat>\n" . 473 " <D:prop>\n"; 474 475 $unknownProperties = array(); 476 477 foreach ( $requestedProperties as $requestedProperty ) 478 { 479 $name = $nameMap[$requestedProperty]; 480 if ( isset( $entry[$name] ) ) 481 { 482 if ( $requestedProperty == 'creationdate' ) 483 { 484 $creationTime = date( EZ_WEBDAV_CTIME_FORMAT, $entry['ctime'] ); 485 $xmlText .= " <D:" . $requestedProperty . ">" . $creationTime . "</D:" . $requestedProperty . ">\n"; 486 } 487 else if ( $requestedProperty == 'getlastmodified' ) 488 { 489 $modificationTime = date( EZ_WEBDAV_MTIME_FORMAT, $entry['mtime'] ); 490 $xmlText .= " <D:" . $requestedProperty . ">" . $modificationTime . "</D:" . $requestedProperty . ">\n"; 491 } 492 else if ( $isCollection and $requestedProperty == 'getcontenttype' ) 493 { 494 495 $xmlText .= ( " <D:resourcetype>\n" . 496 " <D:collection />\n" . 497 " </D:resourcetype>\n" ); 498 499 $unknownProperties[] = $requestedProperty; 500 } 501 else 502 { 503 $xmlText .= " <D:" . $requestedProperty . ">" . htmlspecialchars( eZWebDAVServer::recode( "$entry[$name]", $dataCharset, $xmlCharset ) ) . "</D:" . $requestedProperty . ">\n"; 504 } 505 } 506 else if ( $requestedProperty != 'resourcetype' or !$isCollection ) 507 { 508 $unknownProperties[] = $requestedProperty; 509 } 510 } 511 512 $xmlText .= ( " <D:lockdiscovery/>\n" ); 513 514 $xmlText .= ( " </D:prop>\n" . 515 " <D:status>HTTP/1.1 200 OK</D:status>\n" . 516 " </D:propstat>\n" ); 517 518 519 // List the non supported properties and mark with 404 520 // This behavior (although recommended/standard) might 521 // confuse some clients. Try commenting out if necessary... 522 523 $xmlText .= " <D:propstat>\n"; 524 $xmlText .= " <D:prop>\n"; 525 foreach ( $unknownProperties as $unknownProperty ) 526 { 527 $xmlText .= " <D:" . $unknownProperty . " />\n"; 528 } 529 $xmlText .= " </D:prop>\n"; 530 $xmlText .= " <D:status>HTTP/1.1 404 Not Found</D:status>\n"; 531 $xmlText .= " </D:propstat>\n"; 532 533 $xmlText .= "</D:response>\n"; 534 } 535 536 $xmlText .= "</D:multistatus>\n"; 537 // Send the necessary headers... 538 header( 'HTTP/1.1 207 Multi-Status' ); 539 header( 'Content-Type: text/xml' ); 540 541 // Comment out the next line if you don't 542 // want to use chunked transfer encoding. 543 //header( 'Content-Length: '.strlen( $xmlText ) ); 544 545 $text = @ob_get_contents(); 546 if ( strlen( $text ) != 0 ) 547 $this->appendLogEntry( $text, "DAV: PHP Output" ); 548 while ( @ob_end_clean() ); 549 550 // Dump XML response (from server to client to logfile. 551 //$this->appendLogEntry( $xmlText, 'xmlText' ); 552 553 // Dump the actual XML data containing collection list. 554 print( $xmlText ); 555 556 $xml = new eZXML(); 557 $domTree = $xml->domTree( $xmlText ); 558 if ( $domTree ) 559 $this->appendLogEntry( "XML was parsed", 'outputCollectionContent' ); 560 else 561 $this->appendLogEntry( "XML was NOT parsed $xmlText", 'outputCollectionContent' ); 562 563 // If we got this far: everything is OK. 564 return EZ_WEBDAV_OK_SILENT; 565 } 566 567 /*! 568 \protected 569 Outputs the data \a $output using print(). 570 \param $output Is an array which can contain: 571 - data - String or byte data 572 - file - The path to the file, the contents of the file will be output 573 \return The WebDAV status code 574 */ 575 function outputSendDataToClient( $output, $headers_only = false ) 576 { 577 if ( !$output ) 578 { 579 $this->appendLogEntry( "outputData: no data available", 'outputSendDataToClient' ); 580 return EZ_WEBDAV_FAILED_NOT_FOUND; 581 } 582 583 // Check if we are dealing with custom data. 584 if ( $output["data"] ) 585 { 586 $this->appendLogEntry( "outputData: DATA is a string...", 'outputSendDataToClient' ); 587 } 588 // Else: we need to output a file. 589 elseif ( $output["file"] ) 590 { 591 $this->appendLogEntry( "outputData: DATA is a file...", 'outputSendDataToClient' ); 592 $realPath = $output["file"]; 593 594 // Check if the file/dir actually exists and is readable (permission): 595 if ( ( file_exists( $realPath ) ) && ( is_readable( $realPath ) ) ) 596 { 597 $this->appendLogEntry( "outputData: file exists on server...", 'outputSendDataToClient' ); 598 599 // Get misc. file info. 600 $eTag = md5_file( $realPath ); 601 $size = filesize( $realPath ); 602 603 $dir = dirname( $realPath ); 604 $file = basename( $realPath ); 605 606 $mimeInfo = eZMimeType::findByURL( $dir . '/' . $file ); 607 $mimeType = $mimeInfo['name']; 608 609 // Send necessary headers to client. 610 header( 'HTTP/1.1 200 OK' ); 611 header( 'Accept-Ranges: bytes' ); 612 header( 'Content-Length: '.$size ); 613 header( 'Content-Type: '.$mimeType ); 614 header( 'ETag: '.$eTag ); 615 616 $text = @ob_get_contents(); 617 if ( strlen( $text ) != 0 ) 618 $this->appendLogEntry( $text, "DAV: PHP Output" ); 619 while ( @ob_end_clean() ); 620 621 if ( !$headers_only ) 622 { 623 // Attempt to open the file. 624 $fp = fopen( $realPath, "rb" ); 625 626 // Output the actual contents of the file. 627 $status = fpassthru( $fp ); 628 629 // Check if the last command succeded.. 630 if ( $status == $size) 631 { 632 return EZ_WEBDAV_OK_SILENT; 633 } 634 else 635 { 636 return EZ_WEBDAV_FAILED_FORBIDDEN; 637 } 638 } 639 else 640 { 641 return EZ_WEBDAV_OK_SILENT; 642 } 643 } 644 // Else: file/dir doesn't exist! 645 else 646 { 647 $this->appendLogEntry( "outputData: file DOES NOT exists on server...", 'outputSendDataToClient' ); 648 return EZ_WEBDAV_FAILED_NOT_FOUND; 649 } 650 } 651 else 652 { 653 $this->appendLogEntry( "outputData: No file specified", 'outputSendDataToClient' ); 654 655 $text = @ob_get_contents(); 656 if ( strlen( $text ) != 0 ) 657 $this->appendLogEntry( $text, "DAV: PHP Output" ); 658 while ( @ob_end_clean() ); 659 660 return EZ_WEBDAV_FAILED_NOT_FOUND; 661 } 662 } 663 664 /*! 665 \protected 666 Will try to store the uploaded to a temporary location using \a $target 667 for name. 668 \return The name of the temp file or \c false if it failed. 669 */ 670 function storeUploadedFile( $target ) 671 { 672 $dir = EZ_WEBDAV_TEMP_DIRECTORY . '/' . md5( microtime() . '-' . $target ); 673 $filePath = $dir . '/' . basename( $target ); 674 675 if ( !file_exists( $dir ) ) 676 { 677 include_once ( 'lib/ezfile/classes/ezdir.php' ); 678 eZDir::mkdir( $dir, false, true ); 679 } 680 681 $result = copy( "php://input", $filePath ); 682 if ( !$result ) 683 { 684 $result = file_exists( $filePath ); 685 } 686 687 if ( $result ) 688 { 689 header( "HTTP/1.1 201 Created" ); 690 return $filePath; 691 } 692 return false; 693 } 694 695 /*! 696 \return The XML body text for the current request. 697 */ 698 function xmlBody() 699 { 700 $xmlBody = file_get_contents( "php://input" ); 701 // $this->appendLogEntry( $xmlBody, 'xmlBody' ); 702 $this->XMLBodyRead = true; 703 return $xmlBody; 704 } 705 706 /*! 707 \return The XML body text for the current request. 708 */ 709 function flushXMLBody() 710 { 711 // Flush the XML body by reading it, 712 // PHP should discard it but it's a bug in some PHP versions 713 $xmlBody = file_get_contents( "php://input" ); 714 } 715 716 /*! 717 \protected 718 This method will be called on all intercepted URLs and can be reimplemented 719 to clean up the URL for further processing. 720 A typical usage is when the server is running without rewrite rules and will 721 have the .php file in the path. 722 \return The new URL which can safely be passed to the operation methods. 723 */ 724 function processURL( $url ) 725 { 726 return $url; 727 } 728 729 /*! 730 \protected 731 This is called before each each request is processed and can be used to output 732 some common headers. 733 */ 734 function headers() 735 { 736 } 737 738 /*! 739 \virtual 740 Reports WebDAV options which information on what the server supports. 741 \return An associative array with options, can contain: 742 - methods - An array with methods it can handle, 743 if not supplied it will use all possible methods. 744 - versions - An array with versions this server supports, 745 if not supplied it will use 1,2,<http://apache.org/dav/propset/fs/1>. 746 */ 747 function options( $target ) 748 { 749 } 750 751 /*! 752 \virtual 753 \return An array with elements that belongs to the collection \a $collection 754 \param $depth The current depth, \c 0 for only current object, \c 1 for it's children 755 \param $properties Which properties the client asked for, either an array with DAV 756 property names, \c true for all properties or \c false for only property names. 757 */ 758 function getCollectionContent( $collection, $depth, $properties ) 759 { 760 } 761 762 /*! 763 \virtual 764 \return Information on a given element 765 */ 766 function head( $target ) 767 { 768 } 769 770 /*! 771 \virtual 772 Fetches the data for the element \a $target 773 \return The contents of a given element, e.g. contents of a file. 774 */ 775 function get( $target ) 776 { 777 } 778 779 /*! 780 \virtual 781 Tries to create/overwrite an element named \a $target with contents taken from \a $tempFile. 782 \return The WebDAV status code 783 */ 784 function put( $target, $tempFile ) 785 { 786 } 787 788 /*! 789 \virtual 790 Create a new collection (folder) named \a $target. 791 \return The WebDAV status code 792 */ 793 function mkcol( $target ) 794 { 795 } 796 797 /*! 798 \virtual 799 Copies the element \a $source to destination \a $destination 800 \return The WebDAV status code 801 */ 802 function copy( $source, $destination ) 803 { 804 } 805 806 /*! 807 \virtual 808 Moves the element \a $source to destination \a $destination 809 \return The WebDAV status code 810 */ 811 function move( $source, $destination ) 812 { 813 } 814 815 /*! 816 \virtual 817 Removes the element \a $target. 818 \return The WebDAV status code 819 */ 820 function delete( $target ) 821 { 822 } 823 824 /*! 825 \protected 826 Handles return values and sends necessary/corresponding headers. 827 */ 828 function handle( $status ) 829 { 830 $this->appendLogEntry( "handle function was called with status: $status", 'handle' ); 831 832 // Check and translate status to HTTP:WebDAV reply. 833 switch ( $status ) 834 { 835 // OK. 836 case EZ_WEBDAV_OK: 837 { 838 header( "HTTP/1.1 200 OK" ); 839 } break; 840 841 // OK, SILENT. 842 case EZ_WEBDAV_OK_SILENT: 843 { 844 // Do nothing... 845 } break; 846 847 // OK, CREATED. 848 case EZ_WEBDAV_OK_CREATED: 849 { 850 header( "HTTP/1.1 201 Created" ); 851 } break; 852 853 // OK, OVERWRITE. 854 case EZ_WEBDAV_OK_OVERWRITE: 855 { 856 header( "HTTP/1.1 204 No Content"); 857 } break; 858 859 // FAILED, FORBIDDEN! 860 case EZ_WEBDAV_FAILED_FORBIDDEN: 861 { 862 header( "HTTP/1.1 403 Forbidden"); 863 } break; 864 865 // FAILED, NOT FOUND! 866 case EZ_WEBDAV_FAILED_NOT_FOUND: 867 { 868 header( "HTTP/1.1 404 Not Found" ); 869 } break; 870 871 // FAILED, ALREADY EXISTS! 872 case EZ_WEBDAV_FAILED_EXISTS: 873 { 874 header( "HTTP/1.1 405 Method not allowed" ); 875 } break; 876 877 // FAILED, CONFLICT! 878 case EZ_WEBDAV_FAILED_CONFLICT: 879 { 880 header( "HTTP/1.1 409 Conflict" ); 881 }break; 882 883 // FAILED, PRECONDITION. 884 case EZ_WEBDAV_FAILED_PRECONDITION: 885 { 886 header( "HTTP/1.1 412 Precondition Failed" ); 887 } break; 888 889 // FAILED, RESOURCE IS LOCKED! 890 case EZ_WEBDAV_FAILED_LOCKED: 891 { 892 header( "HTTP/1.1 423 Locked" ); 893 } break; 894 895 // FAILED, BAD GATEWAY! 896 case EZ_WEBDAV_FAILED_BAD_GATEWAY: 897 { 898 header( "HTTP/1.1 502 Bad Gateway" ); 899 } break; 900 901 // FAILED, NO SPACE LEFT ON DEVICE! 902 case EZ_WEBDAV_FAILED_STORAGE_FULL: 903 { 904 header( "HTTP/1.1 507 Insufficient Storage" ); 905 } break; 906 907 // FAILED, UNSUPPORTED REQUEST! 908 case EZ_WEBDAV_FAILED_UNSUPPORTED: 909 { 910 header( "HTTP/1.1 415 Unsupported Media Type" ); 911 } break; 912 913 // Default case: something went wrong... 914 default: 915 { 916 $this->appendLogEntry( "HTTP 500, THIS SHOULD NOT HAPPEN!", 'handle' ); 917 header( "HTTP/1.1 500 Internal Server Error" ); 918 } break; 919 } 920 921 $text = @ob_get_contents(); 922 if ( strlen( $text ) != 0 ) 923 $this->appendLogEntry( $text, "DAV: PHP Output" ); 924 while ( @ob_end_clean() ); 925 } 926 927 /*! 928 Logs the string \a $logString to the logfile webdav.log 929 in the current log directory (usually var/log). 930 If logging is disabled, nothing is done. 931 */ 932 function appendLogEntry( $logString, $label = false ) 933 { 934 if ( !eZWebDAVServer::isLoggingEnabled() ) 935 return false; 936 937 $varDir = eZSys::varDirectory(); 938 939 $logDir = 'log'; 940 $logName = 'webdav.log'; 941 $fileName = $varDir . '/' . $logDir . '/' . $logName; 942 if ( !file_exists( $varDir . '/' . $logDir ) ) 943 { 944 include_once ( 'lib/ezfile/classes/ezdir.php' ); 945 eZDir::mkdir( $varDir . '/' . $logDir, 0775, true ); 946 } 947 948 $logFile = fopen( $fileName, 'a' ); 949 $nowTime = date( "Y-m-d H:i:s : " ); 950 $text = $nowTime . $logString; 951 if ( $label ) 952 $text .= ' [' . $label . ']'; 953 fwrite( $logFile, $text . "\n" ); 954 fclose( $logFile ); 955 } 956 957 /*! 958 \static 959 \return \c true if WebDAV logging is enabled. 960 */ 961 function isLoggingEnabled() 962 { 963 $useLogging =& $GLOBALS['eZWebDavLogging']; 964 if ( !isset( $useLogging ) ) 965 { 966 $ini =& eZINI::instance( 'webdav.ini' ); 967 $useLogging = $ini->variable( 'GeneralSettings', 'Logging' ) == 'enabled'; 968 } 969 return $useLogging; 970 } 971 972 /*! 973 Sets charset for outputted xml by 'userAgent' 974 */ 975 function setupXMLOutputCharset() 976 { 977 $charset = eZWebDAVServer::dataCharset(); 978 979 $userAgent = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : false; 980 $pattern = eZWebDAVServer::userAgentPattern(); 981 $userAgentSettings = eZWebDAVServer::userAgentSettings(); 982 983 if ( preg_match( $pattern, $userAgent, $matches ) && isset( $userAgentSettings[$matches[0]] ) ) 984 { 985 $agentSettings = $userAgentSettings[$matches[0]]; 986 if ( isset( $agentSettings['xmlCharset'] ) && $agentSettings['xmlCharset'] != '' ) 987 $charset = $agentSettings['xmlCharset']; 988 } 989 990 $this->setXMLOutputCharset( $charset ); 991 } 992 993 /*! 994 Sets charset for outputted xml. 995 */ 996 function setXMLOutputCharset( $charset ) 997 { 998 if ( $charset == '' ) 999 { 1000 $this->appendLogEntry( "Error: unable to set empty charset for outputted xml.", 'setXMLOutputCharset' ); 1001 return false; 1002 } 1003 1004 $this->XMLOutputCharset = $charset; 1005 return true; 1006 } 1007 1008 /*! 1009 \return charset for outputted xml 1010 */ 1011 function XMLOutputCharset() 1012 { 1013 return $this->XMLOutputCharset; 1014 } 1015 1016 /*! 1017 \static 1018 \return charset of data. It's used as charset for outputted xml if 1019 other charset is not specified in 'userAgentSettings'. 1020 */ 1021 function dataCharset() 1022 { 1023 $ini =& eZINI::instance( 'i18n.ini' ); 1024 $charset = $ini->variable('CharacterSettings', 'Charset' ); 1025 return $charset; 1026 } 1027 1028 /*! 1029 \static 1030 \return pattern for 'preg_match'. The pattern is built from 'userAgentSettings'. 1031 */ 1032 function userAgentPattern() 1033 { 1034 $pattern = '//'; 1035 1036 $userAgentSettings = eZWebDAVServer::userAgentSettings(); 1037 if( count( $userAgentSettings ) > 0 ) 1038 { 1039 $pattern = '/'; 1040 1041 foreach( $userAgentSettings as $agent => $settings ) 1042 $pattern .= $agent . '|'; 1043 1044 $pattern[strlen($pattern)-1] = '/'; 1045 } 1046 1047 return $pattern; 1048 } 1049 1050 /*! 1051 \static 1052 \return a list of different settings for known user-agents. 1053 */ 1054 function userAgentSettings() 1055 { 1056 return array( 'WebDrive' => array( 'xmlCharset' => 'utf-8' ), 1057 'Microsoft Data Access Internet Publishing Provider' => array( 'xmlCharset' => 'utf-8' ) 1058 ); 1059 } 1060 1061 /*! 1062 \static 1063 \return recoded \a $string form \a $fromCharset to \a $toCharset 1064 */ 1065 function recode( $string, $fromCharset, $toCharset, $stop = false ) 1066 { 1067 include_once ( 'lib/ezi18n/classes/eztextcodec.php' ); 1068 $codec =& eZTextCodec::instance( $fromCharset, $toCharset, false ); 1069 if ( $codec ) 1070 $string = $codec->convertString( $string ); 1071 1072 return $string; 1073 } 1074 1075 /// \privatesection 1076 var $ServerRootDir = ""; 1077 var $XMLBodyRead = false; 1078 var $XMLOutputCharset = 'utf-8'; 1079 } 1080 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sat Feb 24 10:30:04 2007 | par Balluche grâce à PHPXref 0.7 |