2014-05-22 03:41:27 +04:00
< ? php
/**
2016-07-21 17:49:16 +03:00
* @ copyright Copyright ( c ) 2016 , ownCloud , Inc .
*
2016-05-26 20:56:05 +03:00
* @ author Björn Schießle < bjoern @ schiessle . org >
2020-08-24 15:54:25 +03:00
* @ author Daniel Kesselberg < mail @ danielkesselberg . de >
2017-11-06 17:56:42 +03:00
* @ author Frédéric Fortier < frederic . fortier @ oronospolytechnique . com >
2016-07-21 17:49:16 +03:00
* @ author Joas Schilling < coding @ schilljs . com >
2015-03-26 13:44:34 +03:00
* @ author Morris Jobke < hey @ morrisjobke . de >
2016-07-21 19:13:36 +03:00
* @ author Robin Appelman < robin @ icewind . nl >
2016-07-21 17:49:16 +03:00
* @ author Roeland Jago Douma < roeland @ famdouma . nl >
* @ author Vincent Petry < pvince81 @ owncloud . com >
2015-03-26 13:44:34 +03:00
*
* @ license AGPL - 3.0
*
* This code is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License , version 3 ,
2019-12-03 21:57:53 +03:00
* along with this program . If not , see < http :// www . gnu . org / licenses />
2015-03-26 13:44:34 +03:00
*
2014-05-22 03:41:27 +04:00
*/
2015-02-26 13:37:37 +03:00
2014-05-22 03:41:27 +04:00
namespace OCA\Files_Sharing ;
2018-08-16 22:05:01 +03:00
use OC\Cache\CappedMemoryCache ;
2016-04-14 12:50:27 +03:00
use OC\Files\Filesystem ;
2014-11-24 17:54:42 +03:00
use OC\Files\Mount\MountPoint ;
2014-05-22 03:41:27 +04:00
use OC\Files\Mount\MoveableMount ;
2015-04-15 19:18:28 +03:00
use OC\Files\View ;
2020-02-06 19:09:09 +03:00
use OCP\EventDispatcher\IEventDispatcher ;
2018-08-16 22:05:01 +03:00
use OCP\Files\Storage\IStorageFactory ;
2020-02-06 19:09:09 +03:00
use OCP\Share\Events\VerifyMountPointEvent ;
2014-05-22 03:41:27 +04:00
/**
2014-05-28 15:47:50 +04:00
* Shared mount points can be moved by the user
2014-05-22 03:41:27 +04:00
*/
2014-11-24 17:54:42 +03:00
class SharedMount extends MountPoint implements MoveableMount {
2014-05-22 03:41:27 +04:00
/**
2016-06-01 15:29:31 +03:00
* @ var \OCA\Files_Sharing\SharedStorage $storage
2014-05-22 03:41:27 +04:00
*/
protected $storage = null ;
2015-06-29 20:13:39 +03:00
/**
* @ var \OC\Files\View
*/
private $recipientView ;
2015-07-03 16:58:52 +03:00
/**
* @ var string
*/
private $user ;
2016-04-15 15:03:48 +03:00
/** @var \OCP\Share\IShare */
2016-06-15 10:47:33 +03:00
private $superShare ;
/** @var \OCP\Share\IShare[] */
private $groupedShares ;
2016-04-15 15:03:48 +03:00
2015-12-07 23:08:20 +03:00
/**
* @ param string $storage
2016-04-14 12:50:27 +03:00
* @ param SharedMount [] $mountpoints
2018-08-16 21:10:45 +03:00
* @ param array $arguments
2018-08-16 22:05:01 +03:00
* @ param IStorageFactory $loader
2018-08-16 21:10:45 +03:00
* @ param View $recipientView
2015-12-07 23:08:20 +03:00
*/
2018-08-16 22:05:01 +03:00
public function __construct ( $storage , array $mountpoints , $arguments , IStorageFactory $loader , View $recipientView , CappedMemoryCache $folderExistCache ) {
2015-07-03 16:58:52 +03:00
$this -> user = $arguments [ 'user' ];
2018-08-16 21:10:45 +03:00
$this -> recipientView = $recipientView ;
2016-06-15 10:47:33 +03:00
$this -> superShare = $arguments [ 'superShare' ];
$this -> groupedShares = $arguments [ 'groupedShares' ];
2018-08-16 22:05:01 +03:00
$newMountPoint = $this -> verifyMountPoint ( $this -> superShare , $mountpoints , $folderExistCache );
2015-07-03 16:58:52 +03:00
$absMountPoint = '/' . $this -> user . '/files' . $newMountPoint ;
2014-05-28 00:43:20 +04:00
parent :: __construct ( $storage , $absMountPoint , $arguments , $loader );
2014-05-27 22:48:41 +04:00
}
/**
* check if the parent folder exists otherwise move the mount point up
2015-12-08 11:11:50 +03:00
*
2016-04-15 10:01:10 +03:00
* @ param \OCP\Share\IShare $share
2016-04-14 12:50:27 +03:00
* @ param SharedMount [] $mountpoints
2015-12-08 11:11:50 +03:00
* @ return string
2014-05-27 22:48:41 +04:00
*/
2018-08-16 22:05:01 +03:00
private function verifyMountPoint ( \OCP\Share\IShare $share , array $mountpoints , CappedMemoryCache $folderExistCache ) {
2016-04-15 10:01:10 +03:00
$mountPoint = basename ( $share -> getTarget ());
$parent = dirname ( $share -> getTarget ());
2014-05-27 22:48:41 +04:00
2020-02-06 19:09:09 +03:00
$event = new VerifyMountPointEvent ( $share , $this -> recipientView , $parent );
/** @var IEventDispatcher $dispatcher */
$dispatcher = \OC :: $server -> query ( IEventDispatcher :: class );
$dispatcher -> dispatchTyped ( $event );
$parent = $event -> getParent ();
2018-08-16 22:05:01 +03:00
if ( $folderExistCache -> hasKey ( $parent )) {
$parentExists = $folderExistCache -> get ( $parent );
} else {
$parentExists = $this -> recipientView -> is_dir ( $parent );
$folderExistCache -> set ( $parent , $parentExists );
}
if ( ! $parentExists ) {
2016-06-17 12:11:59 +03:00
$parent = Helper :: getShareFolder ( $this -> recipientView );
2014-05-27 22:48:41 +04:00
}
2016-04-14 12:50:27 +03:00
$newMountPoint = $this -> generateUniqueTarget (
2015-06-29 20:13:39 +03:00
\OC\Files\Filesystem :: normalizePath ( $parent . '/' . $mountPoint ),
2016-04-14 12:50:27 +03:00
$this -> recipientView ,
$mountpoints
2015-06-29 20:13:39 +03:00
);
2014-05-27 22:48:41 +04:00
2016-04-15 10:01:10 +03:00
if ( $newMountPoint !== $share -> getTarget ()) {
2015-09-07 15:28:20 +03:00
$this -> updateFileTarget ( $newMountPoint , $share );
2014-05-27 22:48:41 +04:00
}
2014-05-28 00:43:20 +04:00
return $newMountPoint ;
2014-05-27 22:48:41 +04:00
}
2016-04-15 10:01:10 +03:00
/**
* update fileTarget in the database if the mount point changed
*
* @ param string $newPath
* @ param \OCP\Share\IShare $share
* @ return bool
*/
private function updateFileTarget ( $newPath , & $share ) {
$share -> setTarget ( $newPath );
2016-06-15 10:47:33 +03:00
2016-12-14 00:28:09 +03:00
foreach ( $this -> groupedShares as $tmpShare ) {
$tmpShare -> setTarget ( $newPath );
\OC :: $server -> getShareManager () -> moveShare ( $tmpShare , $this -> user );
2016-06-15 10:47:33 +03:00
}
2016-04-15 10:01:10 +03:00
}
2016-04-14 12:50:27 +03:00
/**
* @ param string $path
* @ param View $view
* @ param SharedMount [] $mountpoints
* @ return mixed
*/
private function generateUniqueTarget ( $path , $view , array $mountpoints ) {
$pathinfo = pathinfo ( $path );
2018-01-27 01:46:40 +03:00
$ext = isset ( $pathinfo [ 'extension' ]) ? '.' . $pathinfo [ 'extension' ] : '' ;
2016-04-14 12:50:27 +03:00
$name = $pathinfo [ 'filename' ];
$dir = $pathinfo [ 'dirname' ];
$i = 2 ;
2018-08-16 20:16:24 +03:00
$absolutePath = $this -> recipientView -> getAbsolutePath ( $path ) . '/' ;
while ( $view -> file_exists ( $path ) || isset ( $mountpoints [ $absolutePath ])) {
2016-12-13 14:30:29 +03:00
$path = Filesystem :: normalizePath ( $dir . '/' . $name . ' (' . $i . ')' . $ext );
2018-08-16 20:16:24 +03:00
$absolutePath = $this -> recipientView -> getAbsolutePath ( $path ) . '/' ;
2016-04-14 12:50:27 +03:00
$i ++ ;
}
return $path ;
}
2014-05-22 03:41:27 +04:00
/**
* Format a path to be relative to the / user / files / directory
*
* @ param string $path the absolute path
* @ return string e . g . turns '/admin/files/test.txt' into '/test.txt'
2015-12-08 11:11:50 +03:00
* @ throws \OCA\Files_Sharing\Exceptions\BrokenPath
2014-05-22 03:41:27 +04:00
*/
2014-09-29 13:13:01 +04:00
protected function stripUserFilesPath ( $path ) {
2014-05-22 03:41:27 +04:00
$trimmed = ltrim ( $path , '/' );
$split = explode ( '/' , $trimmed );
// it is not a file relative to data/user/files
if ( count ( $split ) < 3 || $split [ 1 ] !== 'files' ) {
2018-04-20 15:35:37 +03:00
\OC :: $server -> getLogger () -> error ( 'Can not strip userid and "files/" from path: ' . $path , [ 'app' => 'files_sharing' ]);
2014-09-29 13:13:01 +04:00
throw new \OCA\Files_Sharing\Exceptions\BrokenPath ( 'Path does not start with /user/files' , 10 );
2014-05-22 03:41:27 +04:00
}
// skip 'user' and 'files'
$sliced = array_slice ( $split , 2 );
$relPath = implode ( '/' , $sliced );
return '/' . $relPath ;
}
/**
* Move the mount point to $target
*
* @ param string $target the target mount point
* @ return bool
*/
public function moveMount ( $target ) {
$relTargetPath = $this -> stripUserFilesPath ( $target );
$share = $this -> storage -> getShare ();
2014-07-31 13:55:59 +04:00
$result = true ;
2016-04-15 10:01:10 +03:00
try {
$this -> updateFileTarget ( $relTargetPath , $share );
2014-05-22 03:41:27 +04:00
$this -> setMountPoint ( $target );
$this -> storage -> setMountPoint ( $relTargetPath );
2016-04-15 10:01:10 +03:00
} catch ( \Exception $e ) {
2018-04-20 15:35:37 +03:00
\OC :: $server -> getLogger () -> logException ( $e , [ 'app' => 'files_sharing' , 'message' => 'Could not rename mount point for shared folder "' . $this -> getMountPoint () . '" to "' . $target . '"' ]);
2014-05-22 03:41:27 +04:00
}
return $result ;
}
/**
* Remove the mount points
*
* @ return bool
*/
public function removeMount () {
2014-07-02 16:40:22 +04:00
$mountManager = \OC\Files\Filesystem :: getMountManager ();
2020-08-14 16:10:48 +03:00
/** @var \OCA\Files_Sharing\SharedStorage $storage */
2014-05-27 17:07:53 +04:00
$storage = $this -> getStorage ();
2014-07-31 13:55:59 +04:00
$result = $storage -> unshareStorage ();
2014-07-02 16:40:22 +04:00
$mountManager -> removeMount ( $this -> mountPoint );
2014-05-27 17:07:53 +04:00
return $result ;
2014-05-22 03:41:27 +04:00
}
2015-03-09 18:20:18 +03:00
2015-12-08 11:11:50 +03:00
/**
2016-04-15 10:01:10 +03:00
* @ return \OCP\Share\IShare
2015-12-08 11:11:50 +03:00
*/
2015-03-09 18:20:18 +03:00
public function getShare () {
2016-06-15 10:47:33 +03:00
return $this -> superShare ;
2016-04-15 15:03:48 +03:00
}
/**
* Get the file id of the root of the storage
*
* @ return int
*/
public function getStorageRootId () {
2016-06-15 10:47:33 +03:00
return $this -> getShare () -> getNodeId ();
2015-03-09 18:20:18 +03:00
}
2016-08-09 16:52:13 +03:00
/**
* @ return int
*/
public function getNumericStorageId () {
2016-12-13 14:30:29 +03:00
if ( ! is_null ( $this -> getShare () -> getNodeCacheEntry ())) {
return $this -> getShare () -> getNodeCacheEntry () -> getStorageId ();
} else {
$builder = \OC :: $server -> getDatabaseConnection () -> getQueryBuilder ();
$query = $builder -> select ( 'storage' )
-> from ( 'filecache' )
-> where ( $builder -> expr () -> eq ( 'fileid' , $builder -> createNamedParameter ( $this -> getStorageRootId ())));
$result = $query -> execute ();
$row = $result -> fetch ();
$result -> closeCursor ();
if ( $row ) {
2017-02-21 06:07:37 +03:00
return ( int ) $row [ 'storage' ];
2016-12-13 14:30:29 +03:00
}
return - 1 ;
2016-08-25 19:06:13 +03:00
}
2016-08-09 16:52:13 +03:00
}
2017-04-26 15:53:11 +03:00
public function getMountType () {
return 'shared' ;
}
2014-05-22 03:41:27 +04:00
}