@@ -597,10 +597,10 @@ public function deleteSettingsFile(
597597 }
598598 }
599599
600-
601600 /**
602- * Given an access token and a fileId, replaces the files with the request body.
603- * Expects a valid token in access_token parameter.
601+ * Implements WOPI File contents operation `PutFile`.
602+ *
603+ * https://learn.microsoft.com/en-us/microsoft-365/cloud-storage-partner-program/rest/files/putfile
604604 */
605605 #[NoAdminRequired]
606606 #[NoCSRFRequired]
@@ -612,7 +612,6 @@ public function putFile(
612612 string $ access_token ,
613613 ): JSONResponse {
614614 [$ fileId , , ] = Helper::parseFileId ($ fileId );
615- $ isPutRelative = ($ this ->request ->getHeader ('X-WOPI-Override ' ) === 'PUT_RELATIVE ' );
616615
617616 try {
618617 $ wopi = $ this ->wopiMapper ->getWopiForToken ($ access_token );
@@ -634,60 +633,24 @@ public function putFile(
634633 if (!$ this ->encryptionManager ->isEnabled () || $ this ->isMasterKeyEnabled ()) {
635634 // Set the user to register the change under his name
636635 $ this ->userScopeService ->setUserScope ($ wopi ->getEditorUid ());
637- $ this ->userScopeService ->setFilesystemScope ($ isPutRelative ? $ wopi -> getEditorUid () : $ wopi ->getUserForFileAccess ());
636+ $ this ->userScopeService ->setFilesystemScope ($ wopi ->getUserForFileAccess ());
638637 } else {
639638 // Per-user encryption is enabled so that collabora isn't able to store the file by using the
640639 // user's private key. Because of that we have to use the incognito mode for writing the file.
641640 \OC_User::setIncognitoMode (true );
642641 }
643642
644643 try {
645- if ($ isPutRelative ) {
646- // the new file needs to be installed in the current user dir
647- $ userFolder = $ this ->rootFolder ->getUserFolder ($ wopi ->getEditorUid ());
648- $ file = $ userFolder ->getFirstNodeById ($ fileId );
649- if ($ file === null ) {
650- return new JSONResponse ([], Http::STATUS_NOT_FOUND );
651- }
652- $ suggested = $ this ->request ->getHeader ('X-WOPI-SuggestedTarget ' );
653- $ suggested = (string )mb_convert_encoding ($ suggested , 'utf-8 ' , 'utf-7 ' );
654-
655- if ($ suggested [0 ] === '. ' ) {
656- $ path = dirname ($ file ->getPath ()) . '/New File ' . $ suggested ;
657- } elseif ($ suggested [0 ] !== '/ ' ) {
658- $ path = dirname ($ file ->getPath ()) . '/ ' . $ suggested ;
659- } else {
660- $ path = $ userFolder ->getPath () . $ suggested ;
661- }
662-
663- if ($ path === '' ) {
664- return new JSONResponse ([
665- 'status ' => 'error ' ,
666- 'message ' => 'Cannot create the file '
667- ]);
668- }
669-
670- // create the folder first
671- if (!$ this ->rootFolder ->nodeExists (dirname ($ path ))) {
672- $ this ->rootFolder ->newFolder (dirname ($ path ));
673- }
674-
675- // create a unique new file
676- $ path = $ this ->rootFolder ->getNonExistingName ($ path );
677- $ this ->rootFolder ->newFile ($ path );
678- $ file = $ this ->rootFolder ->get ($ path );
679- } else {
680- $ file = $ this ->getFileForWopiToken ($ wopi );
681- $ wopiHeaderTime = $ this ->request ->getHeader ('X-COOL-WOPI-Timestamp ' );
644+ $ file = $ this ->getFileForWopiToken ($ wopi );
645+ $ wopiHeaderTime = $ this ->request ->getHeader ('X-COOL-WOPI-Timestamp ' );
682646
683- if (!empty ($ wopiHeaderTime ) && $ wopiHeaderTime !== Helper::toISO8601 ($ file ->getMTime () ?? 0 )) {
684- $ this ->logger ->debug ('Document timestamp mismatch ! WOPI client says mtime {headerTime} but storage says {storageTime} ' , [
685- 'headerTime ' => $ wopiHeaderTime ,
686- 'storageTime ' => Helper::toISO8601 ($ file ->getMTime () ?? 0 )
687- ]);
688- // Tell WOPI client about this conflict.
689- return new JSONResponse (['COOLStatusCode ' => self ::COOL_STATUS_DOC_CHANGED ], Http::STATUS_CONFLICT );
690- }
647+ if (!empty ($ wopiHeaderTime ) && $ wopiHeaderTime !== Helper::toISO8601 ($ file ->getMTime () ?? 0 )) {
648+ $ this ->logger ->debug ('Document timestamp mismatch ! WOPI client says mtime {headerTime} but storage says {storageTime} ' , [
649+ 'headerTime ' => $ wopiHeaderTime ,
650+ 'storageTime ' => Helper::toISO8601 ($ file ->getMTime () ?? 0 )
651+ ]);
652+ // Tell WOPI client about this conflict.
653+ return new JSONResponse (['COOLStatusCode ' => self ::COOL_STATUS_DOC_CHANGED ], Http::STATUS_CONFLICT );
691654 }
692655
693656 $ content = fopen ('php://input ' , 'rb ' );
@@ -705,11 +668,6 @@ public function putFile(
705668 return new JSONResponse (['message ' => 'File locked ' ], Http::STATUS_INTERNAL_SERVER_ERROR );
706669 }
707670
708- if ($ isPutRelative ) {
709- // generate a token for the new file (the user still has to be logged in)
710- $ wopi = $ this ->tokenManager ->generateWopiToken ((string )$ file ->getId (), null , $ wopi ->getEditorUid (), $ wopi ->getDirect ());
711- return new JSONResponse (['Name ' => $ file ->getName (), 'Url ' => $ this ->getWopiUrlForFile ($ wopi , $ file )], Http::STATUS_OK );
712- }
713671 if ($ wopi ->hasTemplateId ()) {
714672 $ wopi ->setTemplateId (null );
715673 $ this ->wopiMapper ->update ($ wopi );
0 commit comments