1010namespace OCA \FilesLock \Service ;
1111
1212use Exception ;
13+ use OC \Files \Storage \DAV ;
14+ use OC \Files \Storage \Wrapper \Wrapper ;
15+ use OCA \FilesLock \AppInfo \Application ;
1316use OCA \FilesLock \Db \LocksRequest ;
1417use OCA \FilesLock \Exceptions \LockNotFoundException ;
1518use OCA \FilesLock \Exceptions \UnauthorizedUnlockException ;
1922use OCP \Constants ;
2023use OCP \EventDispatcher \IEventDispatcher ;
2124use OCP \Files \InvalidPathException ;
25+ use OCP \Files \IRootFolder ;
2226use OCP \Files \Lock \ILock ;
2327use OCP \Files \Lock \LockContext ;
2428use OCP \Files \Lock \OwnerLockedException ;
@@ -65,6 +69,7 @@ public function __construct(
6569 IUserSession $ userSession ,
6670 IRequest $ request ,
6771 LoggerInterface $ logger ,
72+ private IRootFolder $ rootFolder ,
6873 ) {
6974 $ this ->l10n = $ l10n ;
7075 $ this ->userManager = $ userManager ;
@@ -90,8 +95,9 @@ public function getLockForNodeId(int $nodeId) {
9095
9196 try {
9297 $ this ->lockCache [$ nodeId ] = $ this ->getLockFromFileId ($ nodeId );
93- } catch (LockNotFoundException $ e ) {
94- $ this ->lockCache [$ nodeId ] = false ;
98+ } catch (LockNotFoundException ) {
99+ $ remoteLock = $ this ->getRemoteLockFromDav ($ nodeId );
100+ $ this ->lockCache [$ nodeId ] = $ remoteLock ?: false ;
95101 }
96102
97103 return $ this ->lockCache [$ nodeId ];
@@ -110,7 +116,6 @@ public function getLockForNodeIds(array $nodeIds): array {
110116 $ locks [$ nodeId ] = $ this ->lockCache [$ nodeId ];
111117 } else {
112118 $ locksToRequest [] = $ nodeId ;
113- $ this ->lockCache [$ nodeId ] = false ;
114119 }
115120 }
116121 if (count ($ locksToRequest ) === 0 ) {
@@ -394,6 +399,61 @@ function (FileLock $lock) {
394399 $ this ->locksRequest ->removeIds ($ ids );
395400 }
396401
402+ public function getRemoteLockFromDav (int $ nodeId ): ?FileLock {
403+ try {
404+ $ user = $ this ->userSession ->getUser ();
405+ if (!$ user ) {
406+ return null ;
407+ }
408+
409+ $ userFolder = $ this ->rootFolder ->getUserFolder ($ user ->getUID ());
410+ $ node = $ userFolder ->getFirstNodeById ($ nodeId );
411+ if (empty ($ node )) {
412+ return null ;
413+ }
414+
415+ $ storage = $ node ->getStorage ();
416+
417+ while ($ storage ->instanceOfStorage (Wrapper::class)) {
418+ $ storage = $ storage ->getWrapperStorage ();
419+ }
420+
421+ if (!$ storage ->instanceOfStorage (DAV ::class)) {
422+ return null ;
423+ }
424+
425+ $ path = $ node ->getInternalPath ();
426+ $ storage ->getMetaData ($ path );
427+
428+ if (!method_exists ($ storage , 'getPropfindPropertyValue ' )) {
429+ return null ;
430+ }
431+
432+ $ isLocked = $ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK );
433+ if (!$ isLocked ) {
434+ return null ;
435+ }
436+
437+ $ fileLock = new FileLock ();
438+ $ fileLock ->import ([
439+ 'fileId ' => $ nodeId ,
440+ 'owner ' => (string )($ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK_OWNER_DISPLAYNAME ) ?? '' ),
441+ 'type ' => (int )($ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK_OWNER_TYPE ) ?? 0 ),
442+ 'creation ' => (int )($ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK_TIME ) ?? 0 ),
443+ 'ttl ' => (int )($ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK_TIMEOUT ) ?? 0 ),
444+ 'token ' => (string )($ storage ->getPropfindPropertyValue ($ path , Application::DAV_PROPERTY_LOCK_TOKEN ) ?? '' ),
445+ ]);
446+
447+ $ remoteHost = parse_url ($ storage ->getRemote (), PHP_URL_HOST );
448+ $ fileLock ->setDisplayName ($ fileLock ->getDisplayName () . '@ ' . $ remoteHost );
449+
450+ return $ fileLock ;
451+ } catch (\Exception $ e ) {
452+ $ this ->logger ->error ('Failed to get remote lock from DAV: ' . $ e ->getMessage (), ['exception ' => $ e ]);
453+ return null ;
454+ }
455+ }
456+
397457 private function propagateEtag (LockContext $ lockContext ): void {
398458 $ node = $ lockContext ->getNode ();
399459 $ node ->getStorage ()->getCache ()->update ($ node ->getId (), [
0 commit comments