@@ -527,6 +527,50 @@ protected function httpPropPatch() {
527527 */
528528 protected function httpPut () {
529529
530+ $ body = $ this ->httpRequest ->getBody ();
531+
532+ // Intercepting the Finder problem
533+ if (($ expected = $ this ->httpRequest ->getHeader ('X-Expected-Entity-Length ' )) && $ expected > 0 ) {
534+
535+ /**
536+ Many webservers will not cooperate well with Finder PUT requests,
537+ because it uses 'Chunked' transfer encoding for the request body.
538+
539+ The symptom of this problem is that Finder sends files to the
540+ server, but they arrive as 0-lenght files in PHP.
541+
542+ If we don't do anything, the user might think they are uploading
543+ files successfully, but they end up empty on the server. Instead,
544+ we throw back an error if we detect this.
545+
546+ The reason Finder uses Chunked, is because it thinks the files
547+ might change as it's being uploaded, and therefore the
548+ Content-Length can vary.
549+
550+ Instead it sends the X-Expected-Entity-Length header with the size
551+ of the file at the very start of the request. If this header is set,
552+ but we don't get a request body we will fail the request to
553+ protect the end-user.
554+ */
555+
556+ // Only reading first byte
557+ $ firstByte = fread ($ body ,1 );
558+ if (strlen ($ firstByte )!==1 ) {
559+ throw new Sabre_DAV_Exception_Forbidden ('This server is not compatible with OS/X finder. Consider using a different WebDAV client or webserver. ' );
560+ }
561+
562+ // The body needs to stay intact, so we copy everything to a
563+ // temporary stream.
564+
565+ $ newBody = fopen ('php://temp ' ,'r+ ' );
566+ fwrite ($ newBody ,$ firstByte );
567+ stream_copy_to_stream ($ body , $ newBody );
568+ rewind ($ newBody );
569+
570+ $ body = $ newBody ;
571+
572+ }
573+
530574 // First we'll do a check to see if the resource already exists
531575 try {
532576
@@ -544,14 +588,14 @@ protected function httpPut() {
544588 if (!($ node instanceof Sabre_DAV_IFile)) throw new Sabre_DAV_Exception_Conflict ('PUT is not allowed on non-files. ' );
545589 if (!$ this ->broadcastEvent ('beforeWriteContent ' ,array ($ this ->getRequestUri ()))) return false ;
546590
547- $ node ->put ($ this -> httpRequest -> getBody () );
591+ $ node ->put ($ body );
548592 $ this ->httpResponse ->setHeader ('Content-Length ' ,'0 ' );
549593 $ this ->httpResponse ->sendStatus (200 );
550594
551595 } catch (Sabre_DAV_Exception_FileNotFound $ e ) {
552596
553597 // If we got here, the resource didn't exist yet.
554- $ this ->createFile ($ this ->getRequestUri (),$ this -> httpRequest -> getBody () );
598+ $ this ->createFile ($ this ->getRequestUri (),$ body );
555599 $ this ->httpResponse ->setHeader ('Content-Length ' ,'0 ' );
556600 $ this ->httpResponse ->sendStatus (201 );
557601
0 commit comments