[ Index ]
 

Code source de eZ Publish 3.9.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/ezwebdav/classes/ -> ezwebdavserver.php (source)

   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  ?>


Généré le : Sat Feb 24 10:30:04 2007 par Balluche grâce à PHPXref 0.7