Passed
Push — master ( 30e999...85099f )
by Joas
12:49 queued 11s
created
apps/files_sharing/lib/Migration/SetPasswordColumn.php 1 patch
Indentation   +46 added lines, -46 removed lines patch added patch discarded remove patch
@@ -36,60 +36,60 @@
 block discarded – undo
36 36
  */
37 37
 class SetPasswordColumn implements IRepairStep {
38 38
 
39
-	/** @var IDBConnection */
40
-	private $connection;
39
+    /** @var IDBConnection */
40
+    private $connection;
41 41
 
42
-	/** @var  IConfig */
43
-	private $config;
42
+    /** @var  IConfig */
43
+    private $config;
44 44
 
45 45
 
46
-	public function __construct(IDBConnection $connection, IConfig $config) {
47
-		$this->connection = $connection;
48
-		$this->config = $config;
49
-	}
46
+    public function __construct(IDBConnection $connection, IConfig $config) {
47
+        $this->connection = $connection;
48
+        $this->config = $config;
49
+    }
50 50
 
51
-	/**
52
-	 * Returns the step's name
53
-	 *
54
-	 * @return string
55
-	 * @since 9.1.0
56
-	 */
57
-	public function getName() {
58
-		return 'Copy the share password into the dedicated column';
59
-	}
51
+    /**
52
+     * Returns the step's name
53
+     *
54
+     * @return string
55
+     * @since 9.1.0
56
+     */
57
+    public function getName() {
58
+        return 'Copy the share password into the dedicated column';
59
+    }
60 60
 
61
-	/**
62
-	 * @param IOutput $output
63
-	 */
64
-	public function run(IOutput $output) {
65
-		if (!$this->shouldRun()) {
66
-			return;
67
-		}
61
+    /**
62
+     * @param IOutput $output
63
+     */
64
+    public function run(IOutput $output) {
65
+        if (!$this->shouldRun()) {
66
+            return;
67
+        }
68 68
 
69
-		$query = $this->connection->getQueryBuilder();
70
-		$query
71
-			->update('share')
72
-			->set('password', 'share_with')
73
-			->where($query->expr()->eq('share_type', $query->createNamedParameter(IShare::TYPE_LINK)))
74
-			->andWhere($query->expr()->isNotNull('share_with'));
75
-		$result = $query->execute();
69
+        $query = $this->connection->getQueryBuilder();
70
+        $query
71
+            ->update('share')
72
+            ->set('password', 'share_with')
73
+            ->where($query->expr()->eq('share_type', $query->createNamedParameter(IShare::TYPE_LINK)))
74
+            ->andWhere($query->expr()->isNotNull('share_with'));
75
+        $result = $query->execute();
76 76
 
77
-		if ($result === 0) {
78
-			// No link updated, no need to run the second query
79
-			return;
80
-		}
77
+        if ($result === 0) {
78
+            // No link updated, no need to run the second query
79
+            return;
80
+        }
81 81
 
82
-		$clearQuery = $this->connection->getQueryBuilder();
83
-		$clearQuery
84
-			->update('share')
85
-			->set('share_with', $clearQuery->createNamedParameter(null))
86
-			->where($clearQuery->expr()->eq('share_type', $clearQuery->createNamedParameter(IShare::TYPE_LINK)));
82
+        $clearQuery = $this->connection->getQueryBuilder();
83
+        $clearQuery
84
+            ->update('share')
85
+            ->set('share_with', $clearQuery->createNamedParameter(null))
86
+            ->where($clearQuery->expr()->eq('share_type', $clearQuery->createNamedParameter(IShare::TYPE_LINK)));
87 87
 
88
-		$clearQuery->execute();
89
-	}
88
+        $clearQuery->execute();
89
+    }
90 90
 
91
-	protected function shouldRun() {
92
-		$appVersion = $this->config->getAppValue('files_sharing', 'installed_version', '0.0.0');
93
-		return version_compare($appVersion, '1.4.0', '<');
94
-	}
91
+    protected function shouldRun() {
92
+        $appVersion = $this->config->getAppValue('files_sharing', 'installed_version', '0.0.0');
93
+        return version_compare($appVersion, '1.4.0', '<');
94
+    }
95 95
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Migration/OwncloudGuestShareType.php 2 patches
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -37,46 +37,46 @@
 block discarded – undo
37 37
  */
38 38
 class OwncloudGuestShareType implements IRepairStep {
39 39
 
40
-	/** @var IDBConnection */
41
-	private $connection;
40
+    /** @var IDBConnection */
41
+    private $connection;
42 42
 
43
-	/** @var  IConfig */
44
-	private $config;
43
+    /** @var  IConfig */
44
+    private $config;
45 45
 
46 46
 
47
-	public function __construct(IDBConnection $connection, IConfig $config) {
48
-		$this->connection = $connection;
49
-		$this->config = $config;
50
-	}
47
+    public function __construct(IDBConnection $connection, IConfig $config) {
48
+        $this->connection = $connection;
49
+        $this->config = $config;
50
+    }
51 51
 
52
-	/**
53
-	 * Returns the step's name
54
-	 *
55
-	 * @return string
56
-	 * @since 9.1.0
57
-	 */
58
-	public function getName() {
59
-		return 'Fix the share type of guest shares when migrating from ownCloud';
60
-	}
52
+    /**
53
+     * Returns the step's name
54
+     *
55
+     * @return string
56
+     * @since 9.1.0
57
+     */
58
+    public function getName() {
59
+        return 'Fix the share type of guest shares when migrating from ownCloud';
60
+    }
61 61
 
62
-	/**
63
-	 * @param IOutput $output
64
-	 */
65
-	public function run(IOutput $output) {
66
-		if (!$this->shouldRun()) {
67
-			return;
68
-		}
62
+    /**
63
+     * @param IOutput $output
64
+     */
65
+    public function run(IOutput $output) {
66
+        if (!$this->shouldRun()) {
67
+            return;
68
+        }
69 69
 
70
-		$query = $this->connection->getQueryBuilder();
71
-		$query->update('share')
72
-			->set('share_type',  $query->createNamedParameter(IShare::TYPE_GUEST))
73
-			->where($query->expr()->eq('share_type', $query->createNamedParameter(IShare::TYPE_EMAIL)));
74
-		$query->execute();
75
-	}
70
+        $query = $this->connection->getQueryBuilder();
71
+        $query->update('share')
72
+            ->set('share_type',  $query->createNamedParameter(IShare::TYPE_GUEST))
73
+            ->where($query->expr()->eq('share_type', $query->createNamedParameter(IShare::TYPE_EMAIL)));
74
+        $query->execute();
75
+    }
76 76
 
77
-	protected function shouldRun() {
78
-		$appVersion = $this->config->getAppValue('files_sharing', 'installed_version', '0.0.0');
79
-		return $appVersion === '0.10.0' ||
80
-			$this->config->getAppValue('core', 'vendor', '') === 'owncloud';
81
-	}
77
+    protected function shouldRun() {
78
+        $appVersion = $this->config->getAppValue('files_sharing', 'installed_version', '0.0.0');
79
+        return $appVersion === '0.10.0' ||
80
+            $this->config->getAppValue('core', 'vendor', '') === 'owncloud';
81
+    }
82 82
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -69,7 +69,7 @@
 block discarded – undo
69 69
 
70 70
 		$query = $this->connection->getQueryBuilder();
71 71
 		$query->update('share')
72
-			->set('share_type',  $query->createNamedParameter(IShare::TYPE_GUEST))
72
+			->set('share_type', $query->createNamedParameter(IShare::TYPE_GUEST))
73 73
 			->where($query->expr()->eq('share_type', $query->createNamedParameter(IShare::TYPE_EMAIL)));
74 74
 		$query->execute();
75 75
 	}
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/DeletedShareAPIController.php 1 patch
Indentation   +164 added lines, -164 removed lines patch added patch discarded remove patch
@@ -49,168 +49,168 @@
 block discarded – undo
49 49
 
50 50
 class DeletedShareAPIController extends OCSController {
51 51
 
52
-	/** @var ShareManager */
53
-	private $shareManager;
54
-
55
-	/** @var string */
56
-	private $userId;
57
-
58
-	/** @var IUserManager */
59
-	private $userManager;
60
-
61
-	/** @var IGroupManager */
62
-	private $groupManager;
63
-
64
-	/** @var IRootFolder */
65
-	private $rootFolder;
66
-
67
-	/** @var IAppManager */
68
-	private $appManager;
69
-
70
-	/** @var IServerContainer */
71
-	private $serverContainer;
72
-
73
-	public function __construct(string $appName,
74
-								IRequest $request,
75
-								ShareManager $shareManager,
76
-								string $UserId,
77
-								IUserManager $userManager,
78
-								IGroupManager $groupManager,
79
-								IRootFolder $rootFolder,
80
-								IAppManager $appManager,
81
-								IServerContainer $serverContainer) {
82
-		parent::__construct($appName, $request);
83
-
84
-		$this->shareManager = $shareManager;
85
-		$this->userId = $UserId;
86
-		$this->userManager = $userManager;
87
-		$this->groupManager = $groupManager;
88
-		$this->rootFolder = $rootFolder;
89
-		$this->appManager = $appManager;
90
-		$this->serverContainer = $serverContainer;
91
-	}
92
-
93
-	/**
94
-	 * @suppress PhanUndeclaredClassMethod
95
-	 */
96
-	private function formatShare(IShare $share): array {
97
-		$result = [
98
-			'id' => $share->getFullId(),
99
-			'share_type' => $share->getShareType(),
100
-			'uid_owner' => $share->getSharedBy(),
101
-			'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
102
-			'permissions' => 0,
103
-			'stime' => $share->getShareTime()->getTimestamp(),
104
-			'parent' => null,
105
-			'expiration' => null,
106
-			'token' => null,
107
-			'uid_file_owner' => $share->getShareOwner(),
108
-			'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
109
-			'path' => $share->getTarget(),
110
-		];
111
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
112
-		$nodes = $userFolder->getById($share->getNodeId());
113
-		if (empty($nodes)) {
114
-			// fallback to guessing the path
115
-			$node = $userFolder->get($share->getTarget());
116
-			if ($node === null || $share->getTarget() === '') {
117
-				throw new NotFoundException();
118
-			}
119
-		} else {
120
-			$node = $nodes[0];
121
-		}
122
-
123
-		$result['path'] = $userFolder->getRelativePath($node->getPath());
124
-		if ($node instanceof \OCP\Files\Folder) {
125
-			$result['item_type'] = 'folder';
126
-		} else {
127
-			$result['item_type'] = 'file';
128
-		}
129
-		$result['mimetype'] = $node->getMimetype();
130
-		$result['storage_id'] = $node->getStorage()->getId();
131
-		$result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
132
-		$result['item_source'] = $node->getId();
133
-		$result['file_source'] = $node->getId();
134
-		$result['file_parent'] = $node->getParent()->getId();
135
-		$result['file_target'] = $share->getTarget();
136
-
137
-		$expiration = $share->getExpirationDate();
138
-		if ($expiration !== null) {
139
-			$result['expiration'] = $expiration->format('Y-m-d 00:00:00');
140
-		}
141
-
142
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
143
-			$group = $this->groupManager->get($share->getSharedWith());
144
-			$result['share_with'] = $share->getSharedWith();
145
-			$result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
146
-		} elseif ($share->getShareType() === IShare::TYPE_ROOM) {
147
-			$result['share_with'] = $share->getSharedWith();
148
-			$result['share_with_displayname'] = '';
149
-
150
-			try {
151
-				$result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
152
-			} catch (QueryException $e) {
153
-			}
154
-		}
155
-
156
-		return $result;
157
-	}
158
-
159
-	/**
160
-	 * @NoAdminRequired
161
-	 */
162
-	public function index(): DataResponse {
163
-		$groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
164
-		$roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
165
-
166
-		$shares = array_merge($groupShares, $roomShares);
167
-
168
-		$shares = array_map(function (IShare $share) {
169
-			return $this->formatShare($share);
170
-		}, $shares);
171
-
172
-		return new DataResponse($shares);
173
-	}
174
-
175
-	/**
176
-	 * @NoAdminRequired
177
-	 *
178
-	 * @throws OCSException
179
-	 */
180
-	public function undelete(string $id): DataResponse {
181
-		try {
182
-			$share = $this->shareManager->getShareById($id, $this->userId);
183
-		} catch (ShareNotFound $e) {
184
-			throw new OCSNotFoundException('Share not found');
185
-		}
186
-
187
-		if ($share->getPermissions() !== 0) {
188
-			throw new OCSNotFoundException('No deleted share found');
189
-		}
190
-
191
-		try {
192
-			$this->shareManager->restoreShare($share, $this->userId);
193
-		} catch (GenericShareException $e) {
194
-			throw new OCSException('Something went wrong');
195
-		}
196
-
197
-		return new DataResponse([]);
198
-	}
199
-
200
-	/**
201
-	 * Returns the helper of DeletedShareAPIController for room shares.
202
-	 *
203
-	 * If the Talk application is not enabled or the helper is not available
204
-	 * a QueryException is thrown instead.
205
-	 *
206
-	 * @return \OCA\Talk\Share\Helper\DeletedShareAPIController
207
-	 * @throws QueryException
208
-	 */
209
-	private function getRoomShareHelper() {
210
-		if (!$this->appManager->isEnabledForUser('spreed')) {
211
-			throw new QueryException();
212
-		}
213
-
214
-		return $this->serverContainer->query('\OCA\Talk\Share\Helper\DeletedShareAPIController');
215
-	}
52
+    /** @var ShareManager */
53
+    private $shareManager;
54
+
55
+    /** @var string */
56
+    private $userId;
57
+
58
+    /** @var IUserManager */
59
+    private $userManager;
60
+
61
+    /** @var IGroupManager */
62
+    private $groupManager;
63
+
64
+    /** @var IRootFolder */
65
+    private $rootFolder;
66
+
67
+    /** @var IAppManager */
68
+    private $appManager;
69
+
70
+    /** @var IServerContainer */
71
+    private $serverContainer;
72
+
73
+    public function __construct(string $appName,
74
+                                IRequest $request,
75
+                                ShareManager $shareManager,
76
+                                string $UserId,
77
+                                IUserManager $userManager,
78
+                                IGroupManager $groupManager,
79
+                                IRootFolder $rootFolder,
80
+                                IAppManager $appManager,
81
+                                IServerContainer $serverContainer) {
82
+        parent::__construct($appName, $request);
83
+
84
+        $this->shareManager = $shareManager;
85
+        $this->userId = $UserId;
86
+        $this->userManager = $userManager;
87
+        $this->groupManager = $groupManager;
88
+        $this->rootFolder = $rootFolder;
89
+        $this->appManager = $appManager;
90
+        $this->serverContainer = $serverContainer;
91
+    }
92
+
93
+    /**
94
+     * @suppress PhanUndeclaredClassMethod
95
+     */
96
+    private function formatShare(IShare $share): array {
97
+        $result = [
98
+            'id' => $share->getFullId(),
99
+            'share_type' => $share->getShareType(),
100
+            'uid_owner' => $share->getSharedBy(),
101
+            'displayname_owner' => $this->userManager->get($share->getSharedBy())->getDisplayName(),
102
+            'permissions' => 0,
103
+            'stime' => $share->getShareTime()->getTimestamp(),
104
+            'parent' => null,
105
+            'expiration' => null,
106
+            'token' => null,
107
+            'uid_file_owner' => $share->getShareOwner(),
108
+            'displayname_file_owner' => $this->userManager->get($share->getShareOwner())->getDisplayName(),
109
+            'path' => $share->getTarget(),
110
+        ];
111
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
112
+        $nodes = $userFolder->getById($share->getNodeId());
113
+        if (empty($nodes)) {
114
+            // fallback to guessing the path
115
+            $node = $userFolder->get($share->getTarget());
116
+            if ($node === null || $share->getTarget() === '') {
117
+                throw new NotFoundException();
118
+            }
119
+        } else {
120
+            $node = $nodes[0];
121
+        }
122
+
123
+        $result['path'] = $userFolder->getRelativePath($node->getPath());
124
+        if ($node instanceof \OCP\Files\Folder) {
125
+            $result['item_type'] = 'folder';
126
+        } else {
127
+            $result['item_type'] = 'file';
128
+        }
129
+        $result['mimetype'] = $node->getMimetype();
130
+        $result['storage_id'] = $node->getStorage()->getId();
131
+        $result['storage'] = $node->getStorage()->getCache()->getNumericStorageId();
132
+        $result['item_source'] = $node->getId();
133
+        $result['file_source'] = $node->getId();
134
+        $result['file_parent'] = $node->getParent()->getId();
135
+        $result['file_target'] = $share->getTarget();
136
+
137
+        $expiration = $share->getExpirationDate();
138
+        if ($expiration !== null) {
139
+            $result['expiration'] = $expiration->format('Y-m-d 00:00:00');
140
+        }
141
+
142
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
143
+            $group = $this->groupManager->get($share->getSharedWith());
144
+            $result['share_with'] = $share->getSharedWith();
145
+            $result['share_with_displayname'] = $group !== null ? $group->getDisplayName() : $share->getSharedWith();
146
+        } elseif ($share->getShareType() === IShare::TYPE_ROOM) {
147
+            $result['share_with'] = $share->getSharedWith();
148
+            $result['share_with_displayname'] = '';
149
+
150
+            try {
151
+                $result = array_merge($result, $this->getRoomShareHelper()->formatShare($share));
152
+            } catch (QueryException $e) {
153
+            }
154
+        }
155
+
156
+        return $result;
157
+    }
158
+
159
+    /**
160
+     * @NoAdminRequired
161
+     */
162
+    public function index(): DataResponse {
163
+        $groupShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_GROUP, null, -1, 0);
164
+        $roomShares = $this->shareManager->getDeletedSharedWith($this->userId, IShare::TYPE_ROOM, null, -1, 0);
165
+
166
+        $shares = array_merge($groupShares, $roomShares);
167
+
168
+        $shares = array_map(function (IShare $share) {
169
+            return $this->formatShare($share);
170
+        }, $shares);
171
+
172
+        return new DataResponse($shares);
173
+    }
174
+
175
+    /**
176
+     * @NoAdminRequired
177
+     *
178
+     * @throws OCSException
179
+     */
180
+    public function undelete(string $id): DataResponse {
181
+        try {
182
+            $share = $this->shareManager->getShareById($id, $this->userId);
183
+        } catch (ShareNotFound $e) {
184
+            throw new OCSNotFoundException('Share not found');
185
+        }
186
+
187
+        if ($share->getPermissions() !== 0) {
188
+            throw new OCSNotFoundException('No deleted share found');
189
+        }
190
+
191
+        try {
192
+            $this->shareManager->restoreShare($share, $this->userId);
193
+        } catch (GenericShareException $e) {
194
+            throw new OCSException('Something went wrong');
195
+        }
196
+
197
+        return new DataResponse([]);
198
+    }
199
+
200
+    /**
201
+     * Returns the helper of DeletedShareAPIController for room shares.
202
+     *
203
+     * If the Talk application is not enabled or the helper is not available
204
+     * a QueryException is thrown instead.
205
+     *
206
+     * @return \OCA\Talk\Share\Helper\DeletedShareAPIController
207
+     * @throws QueryException
208
+     */
209
+    private function getRoomShareHelper() {
210
+        if (!$this->appManager->isEnabledForUser('spreed')) {
211
+            throw new QueryException();
212
+        }
213
+
214
+        return $this->serverContainer->query('\OCA\Talk\Share\Helper\DeletedShareAPIController');
215
+    }
216 216
 }
Please login to merge, or discard this patch.
apps/files_sharing/lib/Controller/ShareController.php 1 patch
Indentation   +660 added lines, -660 removed lines patch added patch discarded remove patch
@@ -85,666 +85,666 @@
 block discarded – undo
85 85
  */
86 86
 class ShareController extends AuthPublicShareController {
87 87
 
88
-	/** @var IConfig */
89
-	protected $config;
90
-	/** @var IUserManager */
91
-	protected $userManager;
92
-	/** @var ILogger */
93
-	protected $logger;
94
-	/** @var \OCP\Activity\IManager */
95
-	protected $activityManager;
96
-	/** @var IPreview */
97
-	protected $previewManager;
98
-	/** @var IRootFolder */
99
-	protected $rootFolder;
100
-	/** @var FederatedShareProvider */
101
-	protected $federatedShareProvider;
102
-	/** @var IAccountManager */
103
-	protected $accountManager;
104
-	/** @var EventDispatcherInterface */
105
-	protected $eventDispatcher;
106
-	/** @var IL10N */
107
-	protected $l10n;
108
-	/** @var Defaults */
109
-	protected $defaults;
110
-	/** @var ShareManager */
111
-	protected $shareManager;
112
-
113
-	/** @var Share\IShare */
114
-	protected $share;
115
-
116
-	/**
117
-	 * @param string $appName
118
-	 * @param IRequest $request
119
-	 * @param IConfig $config
120
-	 * @param IURLGenerator $urlGenerator
121
-	 * @param IUserManager $userManager
122
-	 * @param ILogger $logger
123
-	 * @param \OCP\Activity\IManager $activityManager
124
-	 * @param \OCP\Share\IManager $shareManager
125
-	 * @param ISession $session
126
-	 * @param IPreview $previewManager
127
-	 * @param IRootFolder $rootFolder
128
-	 * @param FederatedShareProvider $federatedShareProvider
129
-	 * @param IAccountManager $accountManager
130
-	 * @param EventDispatcherInterface $eventDispatcher
131
-	 * @param IL10N $l10n
132
-	 * @param Defaults $defaults
133
-	 */
134
-	public function __construct(string $appName,
135
-								IRequest $request,
136
-								IConfig $config,
137
-								IURLGenerator $urlGenerator,
138
-								IUserManager $userManager,
139
-								ILogger $logger,
140
-								\OCP\Activity\IManager $activityManager,
141
-								ShareManager $shareManager,
142
-								ISession $session,
143
-								IPreview $previewManager,
144
-								IRootFolder $rootFolder,
145
-								FederatedShareProvider $federatedShareProvider,
146
-								IAccountManager $accountManager,
147
-								EventDispatcherInterface $eventDispatcher,
148
-								IL10N $l10n,
149
-								Defaults $defaults) {
150
-		parent::__construct($appName, $request, $session, $urlGenerator);
151
-
152
-		$this->config = $config;
153
-		$this->userManager = $userManager;
154
-		$this->logger = $logger;
155
-		$this->activityManager = $activityManager;
156
-		$this->previewManager = $previewManager;
157
-		$this->rootFolder = $rootFolder;
158
-		$this->federatedShareProvider = $federatedShareProvider;
159
-		$this->accountManager = $accountManager;
160
-		$this->eventDispatcher = $eventDispatcher;
161
-		$this->l10n = $l10n;
162
-		$this->defaults = $defaults;
163
-		$this->shareManager = $shareManager;
164
-	}
165
-
166
-	/**
167
-	 * @PublicPage
168
-	 * @NoCSRFRequired
169
-	 *
170
-	 * Show the authentication page
171
-	 * The form has to submit to the authenticate method route
172
-	 */
173
-	public function showAuthenticate(): TemplateResponse {
174
-		$templateParameters = ['share' => $this->share];
175
-
176
-		$event = new GenericEvent(null, $templateParameters);
177
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
178
-
179
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
180
-		if ($this->share->getSendPasswordByTalk()) {
181
-			$csp = new ContentSecurityPolicy();
182
-			$csp->addAllowedConnectDomain('*');
183
-			$csp->addAllowedMediaDomain('blob:');
184
-			$response->setContentSecurityPolicy($csp);
185
-		}
186
-
187
-		return $response;
188
-	}
189
-
190
-	/**
191
-	 * The template to show when authentication failed
192
-	 */
193
-	protected function showAuthFailed(): TemplateResponse {
194
-		$templateParameters = ['share' => $this->share, 'wrongpw' => true];
195
-
196
-		$event = new GenericEvent(null, $templateParameters);
197
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
198
-
199
-		$response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
200
-		if ($this->share->getSendPasswordByTalk()) {
201
-			$csp = new ContentSecurityPolicy();
202
-			$csp->addAllowedConnectDomain('*');
203
-			$csp->addAllowedMediaDomain('blob:');
204
-			$response->setContentSecurityPolicy($csp);
205
-		}
206
-
207
-		return $response;
208
-	}
209
-
210
-	protected function verifyPassword(string $password): bool {
211
-		return $this->shareManager->checkPassword($this->share, $password);
212
-	}
213
-
214
-	protected function getPasswordHash(): string {
215
-		return $this->share->getPassword();
216
-	}
217
-
218
-	public function isValidToken(): bool {
219
-		try {
220
-			$this->share = $this->shareManager->getShareByToken($this->getToken());
221
-		} catch (ShareNotFound $e) {
222
-			return false;
223
-		}
224
-
225
-		return true;
226
-	}
227
-
228
-	protected function isPasswordProtected(): bool {
229
-		return $this->share->getPassword() !== null;
230
-	}
231
-
232
-	protected function authSucceeded() {
233
-		// For share this was always set so it is still used in other apps
234
-		$this->session->set('public_link_authenticated', (string)$this->share->getId());
235
-	}
236
-
237
-	protected function authFailed() {
238
-		$this->emitAccessShareHook($this->share, 403, 'Wrong password');
239
-	}
240
-
241
-	/**
242
-	 * throws hooks when a share is attempted to be accessed
243
-	 *
244
-	 * @param \OCP\Share\IShare|string $share the Share instance if available,
245
-	 * otherwise token
246
-	 * @param int $errorCode
247
-	 * @param string $errorMessage
248
-	 * @throws \OC\HintException
249
-	 * @throws \OC\ServerNotAvailableException
250
-	 */
251
-	protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
252
-		$itemType = $itemSource = $uidOwner = '';
253
-		$token = $share;
254
-		$exception = null;
255
-		if ($share instanceof \OCP\Share\IShare) {
256
-			try {
257
-				$token = $share->getToken();
258
-				$uidOwner = $share->getSharedBy();
259
-				$itemType = $share->getNodeType();
260
-				$itemSource = $share->getNodeId();
261
-			} catch (\Exception $e) {
262
-				// we log what we know and pass on the exception afterwards
263
-				$exception = $e;
264
-			}
265
-		}
266
-		\OC_Hook::emit(Share::class, 'share_link_access', [
267
-			'itemType' => $itemType,
268
-			'itemSource' => $itemSource,
269
-			'uidOwner' => $uidOwner,
270
-			'token' => $token,
271
-			'errorCode' => $errorCode,
272
-			'errorMessage' => $errorMessage,
273
-		]);
274
-		if (!is_null($exception)) {
275
-			throw $exception;
276
-		}
277
-	}
278
-
279
-	/**
280
-	 * Validate the permissions of the share
281
-	 *
282
-	 * @param Share\IShare $share
283
-	 * @return bool
284
-	 */
285
-	private function validateShare(\OCP\Share\IShare $share) {
286
-		// If the owner is disabled no access to the linke is granted
287
-		$owner = $this->userManager->get($share->getShareOwner());
288
-		if ($owner === null || !$owner->isEnabled()) {
289
-			return false;
290
-		}
291
-
292
-		// If the initiator of the share is disabled no access is granted
293
-		$initiator = $this->userManager->get($share->getSharedBy());
294
-		if ($initiator === null || !$initiator->isEnabled()) {
295
-			return false;
296
-		}
297
-
298
-		return $share->getNode()->isReadable() && $share->getNode()->isShareable();
299
-	}
300
-
301
-	/**
302
-	 * @PublicPage
303
-	 * @NoCSRFRequired
304
-	 *
305
-	 *
306
-	 * @param string $path
307
-	 * @return TemplateResponse
308
-	 * @throws NotFoundException
309
-	 * @throws \Exception
310
-	 */
311
-	public function showShare($path = ''): TemplateResponse {
312
-		\OC_User::setIncognitoMode(true);
313
-
314
-		// Check whether share exists
315
-		try {
316
-			$share = $this->shareManager->getShareByToken($this->getToken());
317
-		} catch (ShareNotFound $e) {
318
-			$this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
319
-			throw new NotFoundException();
320
-		}
321
-
322
-		if (!$this->validateShare($share)) {
323
-			throw new NotFoundException();
324
-		}
325
-
326
-		$shareNode = $share->getNode();
327
-
328
-		// We can't get the path of a file share
329
-		try {
330
-			if ($shareNode instanceof \OCP\Files\File && $path !== '') {
331
-				$this->emitAccessShareHook($share, 404, 'Share not found');
332
-				throw new NotFoundException();
333
-			}
334
-		} catch (\Exception $e) {
335
-			$this->emitAccessShareHook($share, 404, 'Share not found');
336
-			throw $e;
337
-		}
338
-
339
-		$shareTmpl = [];
340
-		$shareTmpl['owner'] = '';
341
-		$shareTmpl['shareOwner'] = '';
342
-
343
-		$owner = $this->userManager->get($share->getShareOwner());
344
-		if ($owner instanceof IUser) {
345
-			$ownerAccount = $this->accountManager->getAccount($owner);
346
-
347
-			$ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
348
-			if ($ownerName->getScope() === IAccountManager::VISIBILITY_PUBLIC) {
349
-				$shareTmpl['owner'] = $owner->getUID();
350
-				$shareTmpl['shareOwner'] = $owner->getDisplayName();
351
-			}
352
-		}
353
-
354
-		$shareTmpl['filename'] = $shareNode->getName();
355
-		$shareTmpl['directory_path'] = $share->getTarget();
356
-		$shareTmpl['note'] = $share->getNote();
357
-		$shareTmpl['mimetype'] = $shareNode->getMimetype();
358
-		$shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
359
-		$shareTmpl['dirToken'] = $this->getToken();
360
-		$shareTmpl['sharingToken'] = $this->getToken();
361
-		$shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
362
-		$shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
363
-		$shareTmpl['dir'] = '';
364
-		$shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
365
-		$shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
366
-		$shareTmpl['hideDownload'] = $share->getHideDownload();
367
-
368
-		$hideFileList = false;
369
-
370
-		if ($shareNode instanceof \OCP\Files\Folder) {
371
-			$shareIsFolder = true;
372
-
373
-			try {
374
-				$folderNode = $shareNode->get($path);
375
-			} catch (\OCP\Files\NotFoundException $e) {
376
-				$this->emitAccessShareHook($share, 404, 'Share not found');
377
-				throw new NotFoundException();
378
-			}
379
-
380
-			$shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
381
-
382
-			/*
88
+    /** @var IConfig */
89
+    protected $config;
90
+    /** @var IUserManager */
91
+    protected $userManager;
92
+    /** @var ILogger */
93
+    protected $logger;
94
+    /** @var \OCP\Activity\IManager */
95
+    protected $activityManager;
96
+    /** @var IPreview */
97
+    protected $previewManager;
98
+    /** @var IRootFolder */
99
+    protected $rootFolder;
100
+    /** @var FederatedShareProvider */
101
+    protected $federatedShareProvider;
102
+    /** @var IAccountManager */
103
+    protected $accountManager;
104
+    /** @var EventDispatcherInterface */
105
+    protected $eventDispatcher;
106
+    /** @var IL10N */
107
+    protected $l10n;
108
+    /** @var Defaults */
109
+    protected $defaults;
110
+    /** @var ShareManager */
111
+    protected $shareManager;
112
+
113
+    /** @var Share\IShare */
114
+    protected $share;
115
+
116
+    /**
117
+     * @param string $appName
118
+     * @param IRequest $request
119
+     * @param IConfig $config
120
+     * @param IURLGenerator $urlGenerator
121
+     * @param IUserManager $userManager
122
+     * @param ILogger $logger
123
+     * @param \OCP\Activity\IManager $activityManager
124
+     * @param \OCP\Share\IManager $shareManager
125
+     * @param ISession $session
126
+     * @param IPreview $previewManager
127
+     * @param IRootFolder $rootFolder
128
+     * @param FederatedShareProvider $federatedShareProvider
129
+     * @param IAccountManager $accountManager
130
+     * @param EventDispatcherInterface $eventDispatcher
131
+     * @param IL10N $l10n
132
+     * @param Defaults $defaults
133
+     */
134
+    public function __construct(string $appName,
135
+                                IRequest $request,
136
+                                IConfig $config,
137
+                                IURLGenerator $urlGenerator,
138
+                                IUserManager $userManager,
139
+                                ILogger $logger,
140
+                                \OCP\Activity\IManager $activityManager,
141
+                                ShareManager $shareManager,
142
+                                ISession $session,
143
+                                IPreview $previewManager,
144
+                                IRootFolder $rootFolder,
145
+                                FederatedShareProvider $federatedShareProvider,
146
+                                IAccountManager $accountManager,
147
+                                EventDispatcherInterface $eventDispatcher,
148
+                                IL10N $l10n,
149
+                                Defaults $defaults) {
150
+        parent::__construct($appName, $request, $session, $urlGenerator);
151
+
152
+        $this->config = $config;
153
+        $this->userManager = $userManager;
154
+        $this->logger = $logger;
155
+        $this->activityManager = $activityManager;
156
+        $this->previewManager = $previewManager;
157
+        $this->rootFolder = $rootFolder;
158
+        $this->federatedShareProvider = $federatedShareProvider;
159
+        $this->accountManager = $accountManager;
160
+        $this->eventDispatcher = $eventDispatcher;
161
+        $this->l10n = $l10n;
162
+        $this->defaults = $defaults;
163
+        $this->shareManager = $shareManager;
164
+    }
165
+
166
+    /**
167
+     * @PublicPage
168
+     * @NoCSRFRequired
169
+     *
170
+     * Show the authentication page
171
+     * The form has to submit to the authenticate method route
172
+     */
173
+    public function showAuthenticate(): TemplateResponse {
174
+        $templateParameters = ['share' => $this->share];
175
+
176
+        $event = new GenericEvent(null, $templateParameters);
177
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
178
+
179
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
180
+        if ($this->share->getSendPasswordByTalk()) {
181
+            $csp = new ContentSecurityPolicy();
182
+            $csp->addAllowedConnectDomain('*');
183
+            $csp->addAllowedMediaDomain('blob:');
184
+            $response->setContentSecurityPolicy($csp);
185
+        }
186
+
187
+        return $response;
188
+    }
189
+
190
+    /**
191
+     * The template to show when authentication failed
192
+     */
193
+    protected function showAuthFailed(): TemplateResponse {
194
+        $templateParameters = ['share' => $this->share, 'wrongpw' => true];
195
+
196
+        $event = new GenericEvent(null, $templateParameters);
197
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts::publicShareAuth', $event);
198
+
199
+        $response = new TemplateResponse('core', 'publicshareauth', $templateParameters, 'guest');
200
+        if ($this->share->getSendPasswordByTalk()) {
201
+            $csp = new ContentSecurityPolicy();
202
+            $csp->addAllowedConnectDomain('*');
203
+            $csp->addAllowedMediaDomain('blob:');
204
+            $response->setContentSecurityPolicy($csp);
205
+        }
206
+
207
+        return $response;
208
+    }
209
+
210
+    protected function verifyPassword(string $password): bool {
211
+        return $this->shareManager->checkPassword($this->share, $password);
212
+    }
213
+
214
+    protected function getPasswordHash(): string {
215
+        return $this->share->getPassword();
216
+    }
217
+
218
+    public function isValidToken(): bool {
219
+        try {
220
+            $this->share = $this->shareManager->getShareByToken($this->getToken());
221
+        } catch (ShareNotFound $e) {
222
+            return false;
223
+        }
224
+
225
+        return true;
226
+    }
227
+
228
+    protected function isPasswordProtected(): bool {
229
+        return $this->share->getPassword() !== null;
230
+    }
231
+
232
+    protected function authSucceeded() {
233
+        // For share this was always set so it is still used in other apps
234
+        $this->session->set('public_link_authenticated', (string)$this->share->getId());
235
+    }
236
+
237
+    protected function authFailed() {
238
+        $this->emitAccessShareHook($this->share, 403, 'Wrong password');
239
+    }
240
+
241
+    /**
242
+     * throws hooks when a share is attempted to be accessed
243
+     *
244
+     * @param \OCP\Share\IShare|string $share the Share instance if available,
245
+     * otherwise token
246
+     * @param int $errorCode
247
+     * @param string $errorMessage
248
+     * @throws \OC\HintException
249
+     * @throws \OC\ServerNotAvailableException
250
+     */
251
+    protected function emitAccessShareHook($share, $errorCode = 200, $errorMessage = '') {
252
+        $itemType = $itemSource = $uidOwner = '';
253
+        $token = $share;
254
+        $exception = null;
255
+        if ($share instanceof \OCP\Share\IShare) {
256
+            try {
257
+                $token = $share->getToken();
258
+                $uidOwner = $share->getSharedBy();
259
+                $itemType = $share->getNodeType();
260
+                $itemSource = $share->getNodeId();
261
+            } catch (\Exception $e) {
262
+                // we log what we know and pass on the exception afterwards
263
+                $exception = $e;
264
+            }
265
+        }
266
+        \OC_Hook::emit(Share::class, 'share_link_access', [
267
+            'itemType' => $itemType,
268
+            'itemSource' => $itemSource,
269
+            'uidOwner' => $uidOwner,
270
+            'token' => $token,
271
+            'errorCode' => $errorCode,
272
+            'errorMessage' => $errorMessage,
273
+        ]);
274
+        if (!is_null($exception)) {
275
+            throw $exception;
276
+        }
277
+    }
278
+
279
+    /**
280
+     * Validate the permissions of the share
281
+     *
282
+     * @param Share\IShare $share
283
+     * @return bool
284
+     */
285
+    private function validateShare(\OCP\Share\IShare $share) {
286
+        // If the owner is disabled no access to the linke is granted
287
+        $owner = $this->userManager->get($share->getShareOwner());
288
+        if ($owner === null || !$owner->isEnabled()) {
289
+            return false;
290
+        }
291
+
292
+        // If the initiator of the share is disabled no access is granted
293
+        $initiator = $this->userManager->get($share->getSharedBy());
294
+        if ($initiator === null || !$initiator->isEnabled()) {
295
+            return false;
296
+        }
297
+
298
+        return $share->getNode()->isReadable() && $share->getNode()->isShareable();
299
+    }
300
+
301
+    /**
302
+     * @PublicPage
303
+     * @NoCSRFRequired
304
+     *
305
+     *
306
+     * @param string $path
307
+     * @return TemplateResponse
308
+     * @throws NotFoundException
309
+     * @throws \Exception
310
+     */
311
+    public function showShare($path = ''): TemplateResponse {
312
+        \OC_User::setIncognitoMode(true);
313
+
314
+        // Check whether share exists
315
+        try {
316
+            $share = $this->shareManager->getShareByToken($this->getToken());
317
+        } catch (ShareNotFound $e) {
318
+            $this->emitAccessShareHook($this->getToken(), 404, 'Share not found');
319
+            throw new NotFoundException();
320
+        }
321
+
322
+        if (!$this->validateShare($share)) {
323
+            throw new NotFoundException();
324
+        }
325
+
326
+        $shareNode = $share->getNode();
327
+
328
+        // We can't get the path of a file share
329
+        try {
330
+            if ($shareNode instanceof \OCP\Files\File && $path !== '') {
331
+                $this->emitAccessShareHook($share, 404, 'Share not found');
332
+                throw new NotFoundException();
333
+            }
334
+        } catch (\Exception $e) {
335
+            $this->emitAccessShareHook($share, 404, 'Share not found');
336
+            throw $e;
337
+        }
338
+
339
+        $shareTmpl = [];
340
+        $shareTmpl['owner'] = '';
341
+        $shareTmpl['shareOwner'] = '';
342
+
343
+        $owner = $this->userManager->get($share->getShareOwner());
344
+        if ($owner instanceof IUser) {
345
+            $ownerAccount = $this->accountManager->getAccount($owner);
346
+
347
+            $ownerName = $ownerAccount->getProperty(IAccountManager::PROPERTY_DISPLAYNAME);
348
+            if ($ownerName->getScope() === IAccountManager::VISIBILITY_PUBLIC) {
349
+                $shareTmpl['owner'] = $owner->getUID();
350
+                $shareTmpl['shareOwner'] = $owner->getDisplayName();
351
+            }
352
+        }
353
+
354
+        $shareTmpl['filename'] = $shareNode->getName();
355
+        $shareTmpl['directory_path'] = $share->getTarget();
356
+        $shareTmpl['note'] = $share->getNote();
357
+        $shareTmpl['mimetype'] = $shareNode->getMimetype();
358
+        $shareTmpl['previewSupported'] = $this->previewManager->isMimeSupported($shareNode->getMimetype());
359
+        $shareTmpl['dirToken'] = $this->getToken();
360
+        $shareTmpl['sharingToken'] = $this->getToken();
361
+        $shareTmpl['server2serversharing'] = $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
362
+        $shareTmpl['protected'] = $share->getPassword() !== null ? 'true' : 'false';
363
+        $shareTmpl['dir'] = '';
364
+        $shareTmpl['nonHumanFileSize'] = $shareNode->getSize();
365
+        $shareTmpl['fileSize'] = \OCP\Util::humanFileSize($shareNode->getSize());
366
+        $shareTmpl['hideDownload'] = $share->getHideDownload();
367
+
368
+        $hideFileList = false;
369
+
370
+        if ($shareNode instanceof \OCP\Files\Folder) {
371
+            $shareIsFolder = true;
372
+
373
+            try {
374
+                $folderNode = $shareNode->get($path);
375
+            } catch (\OCP\Files\NotFoundException $e) {
376
+                $this->emitAccessShareHook($share, 404, 'Share not found');
377
+                throw new NotFoundException();
378
+            }
379
+
380
+            $shareTmpl['dir'] = $shareNode->getRelativePath($folderNode->getPath());
381
+
382
+            /*
383 383
 			 * The OC_Util methods require a view. This just uses the node API
384 384
 			 */
385
-			$freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
386
-			if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
387
-				$freeSpace = max($freeSpace, 0);
388
-			} else {
389
-				$freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
390
-			}
391
-
392
-			$hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
393
-			$maxUploadFilesize = $freeSpace;
394
-
395
-			$folder = new Template('files', 'list', '');
396
-
397
-			$folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
398
-			$folder->assign('dirToken', $this->getToken());
399
-			$folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
400
-			$folder->assign('isPublic', true);
401
-			$folder->assign('hideFileList', $hideFileList);
402
-			$folder->assign('publicUploadEnabled', 'no');
403
-			// default to list view
404
-			$folder->assign('showgridview', false);
405
-			$folder->assign('uploadMaxFilesize', $maxUploadFilesize);
406
-			$folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
407
-			$folder->assign('freeSpace', $freeSpace);
408
-			$folder->assign('usedSpacePercent', 0);
409
-			$folder->assign('trash', false);
410
-			$shareTmpl['folder'] = $folder->fetchPage();
411
-		} else {
412
-			$shareIsFolder = false;
413
-		}
414
-
415
-		// default to list view
416
-		$shareTmpl['showgridview'] = false;
417
-
418
-		$shareTmpl['hideFileList'] = $hideFileList;
419
-		$shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
420
-		$shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
421
-		$shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
422
-		$shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
423
-		$shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
424
-		$shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
425
-		$shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
426
-		$shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
427
-
428
-		if ($shareTmpl['previewSupported']) {
429
-			$shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
430
-				['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
431
-			$ogPreview = $shareTmpl['previewImage'];
432
-
433
-			// We just have direct previews for image files
434
-			if ($shareNode->getMimePart() === 'image') {
435
-				$shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
436
-
437
-				$ogPreview = $shareTmpl['previewURL'];
438
-
439
-				//Whatapp is kind of picky about their size requirements
440
-				if ($this->request->isUserAgent(['/^WhatsApp/'])) {
441
-					$ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
442
-						'token' => $this->getToken(),
443
-						'x' => 256,
444
-						'y' => 256,
445
-						'a' => true,
446
-					]);
447
-				}
448
-			}
449
-		} else {
450
-			$shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
451
-			$ogPreview = $shareTmpl['previewImage'];
452
-		}
453
-
454
-		// Load files we need
455
-		\OCP\Util::addScript('files', 'semaphore');
456
-		\OCP\Util::addScript('files', 'file-upload');
457
-		\OCP\Util::addStyle('files_sharing', 'publicView');
458
-		\OCP\Util::addScript('files_sharing', 'public');
459
-		\OCP\Util::addScript('files_sharing', 'templates');
460
-		\OCP\Util::addScript('files', 'fileactions');
461
-		\OCP\Util::addScript('files', 'fileactionsmenu');
462
-		\OCP\Util::addScript('files', 'jquery.fileupload');
463
-		\OCP\Util::addScript('files_sharing', 'files_drop');
464
-
465
-		if (isset($shareTmpl['folder'])) {
466
-			// JS required for folders
467
-			\OCP\Util::addStyle('files', 'merged');
468
-			\OCP\Util::addScript('files', 'filesummary');
469
-			\OCP\Util::addScript('files', 'templates');
470
-			\OCP\Util::addScript('files', 'breadcrumb');
471
-			\OCP\Util::addScript('files', 'fileinfomodel');
472
-			\OCP\Util::addScript('files', 'newfilemenu');
473
-			\OCP\Util::addScript('files', 'files');
474
-			\OCP\Util::addScript('files', 'filemultiselectmenu');
475
-			\OCP\Util::addScript('files', 'filelist');
476
-			\OCP\Util::addScript('files', 'keyboardshortcuts');
477
-			\OCP\Util::addScript('files', 'operationprogressbar');
478
-
479
-			// Load Viewer scripts
480
-			if (class_exists(LoadViewer::class)) {
481
-				$this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
482
-			}
483
-		}
484
-
485
-		// OpenGraph Support: http://ogp.me/
486
-		\OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
487
-		\OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
488
-		\OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
489
-		\OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
490
-		\OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
491
-		\OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
492
-
493
-		$event = new GenericEvent(null, ['share' => $share]);
494
-		$this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
495
-
496
-		$csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
497
-		$csp->addAllowedFrameDomain('\'self\'');
498
-
499
-		$response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
500
-		$response->setHeaderTitle($shareTmpl['filename']);
501
-		if ($shareTmpl['shareOwner'] !== '') {
502
-			$response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
503
-		}
504
-
505
-		$isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
506
-
507
-		if ($isNoneFileDropFolder && !$share->getHideDownload()) {
508
-			\OCP\Util::addScript('files_sharing', 'public_note');
509
-
510
-			$downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
-			$downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
512
-			$download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
-			$downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
514
-			$directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
515
-			$externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
-
517
-			$responseComposer = [];
518
-
519
-			if ($shareIsFolder) {
520
-				$responseComposer[] = $downloadAllWhite;
521
-				$responseComposer[] = $downloadAll;
522
-			} else {
523
-				$responseComposer[] = $downloadWhite;
524
-				$responseComposer[] = $download;
525
-			}
526
-			$responseComposer[] = $directLink;
527
-			if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
-				$responseComposer[] = $externalShare;
529
-			}
530
-
531
-			$response->setHeaderActions($responseComposer);
532
-		}
533
-
534
-		$response->setContentSecurityPolicy($csp);
535
-
536
-		$this->emitAccessShareHook($share);
537
-
538
-		return $response;
539
-	}
540
-
541
-	/**
542
-	 * @PublicPage
543
-	 * @NoCSRFRequired
544
-	 * @NoSameSiteCookieRequired
545
-	 *
546
-	 * @param string $token
547
-	 * @param string $files
548
-	 * @param string $path
549
-	 * @param string $downloadStartSecret
550
-	 * @return void|\OCP\AppFramework\Http\Response
551
-	 * @throws NotFoundException
552
-	 */
553
-	public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
-		\OC_User::setIncognitoMode(true);
555
-
556
-		$share = $this->shareManager->getShareByToken($token);
557
-
558
-		if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
-			return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
560
-		}
561
-
562
-		$files_list = null;
563
-		if (!is_null($files)) { // download selected files
564
-			$files_list = json_decode($files);
565
-			// in case we get only a single file
566
-			if ($files_list === null) {
567
-				$files_list = [$files];
568
-			}
569
-			// Just in case $files is a single int like '1234'
570
-			if (!is_array($files_list)) {
571
-				$files_list = [$files_list];
572
-			}
573
-		}
574
-
575
-		if (!$this->validateShare($share)) {
576
-			throw new NotFoundException();
577
-		}
578
-
579
-		$userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
-		$originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
-
582
-
583
-		// Single file share
584
-		if ($share->getNode() instanceof \OCP\Files\File) {
585
-			// Single file download
586
-			$this->singleFileDownloaded($share, $share->getNode());
587
-		}
588
-		// Directory share
589
-		else {
590
-			/** @var \OCP\Files\Folder $node */
591
-			$node = $share->getNode();
592
-
593
-			// Try to get the path
594
-			if ($path !== '') {
595
-				try {
596
-					$node = $node->get($path);
597
-				} catch (NotFoundException $e) {
598
-					$this->emitAccessShareHook($share, 404, 'Share not found');
599
-					return new NotFoundResponse();
600
-				}
601
-			}
602
-
603
-			$originalSharePath = $userFolder->getRelativePath($node->getPath());
604
-
605
-			if ($node instanceof \OCP\Files\File) {
606
-				// Single file download
607
-				$this->singleFileDownloaded($share, $share->getNode());
608
-			} else {
609
-				try {
610
-					if (!empty($files_list)) {
611
-						$this->fileListDownloaded($share, $files_list, $node);
612
-					} else {
613
-						// The folder is downloaded
614
-						$this->singleFileDownloaded($share, $share->getNode());
615
-					}
616
-				} catch (NotFoundException $e) {
617
-					return new NotFoundResponse();
618
-				}
619
-			}
620
-		}
621
-
622
-		/* FIXME: We should do this all nicely in OCP */
623
-		OC_Util::tearDownFS();
624
-		OC_Util::setupFS($share->getShareOwner());
625
-
626
-		/**
627
-		 * this sets a cookie to be able to recognize the start of the download
628
-		 * the content must not be longer than 32 characters and must only contain
629
-		 * alphanumeric characters
630
-		 */
631
-		if (!empty($downloadStartSecret)
632
-			&& !isset($downloadStartSecret[32])
633
-			&& preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
-
635
-			// FIXME: set on the response once we use an actual app framework response
636
-			setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
-		}
638
-
639
-		$this->emitAccessShareHook($share);
640
-
641
-		$server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
-
643
-		/**
644
-		 * Http range requests support
645
-		 */
646
-		if (isset($_SERVER['HTTP_RANGE'])) {
647
-			$server_params['range'] = $this->request->getHeader('Range');
648
-		}
649
-
650
-		// download selected files
651
-		if (!is_null($files) && $files !== '') {
652
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
-			// after dispatching the request which results in a "Cannot modify header information" notice.
654
-			OC_Files::get($originalSharePath, $files_list, $server_params);
655
-			exit();
656
-		} else {
657
-			// FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
-			// after dispatching the request which results in a "Cannot modify header information" notice.
659
-			OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
-			exit();
661
-		}
662
-	}
663
-
664
-	/**
665
-	 * create activity for every downloaded file
666
-	 *
667
-	 * @param Share\IShare $share
668
-	 * @param array $files_list
669
-	 * @param \OCP\Files\Folder $node
670
-	 * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
-	 */
672
-	protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
-		if ($share->getHideDownload() && count($files_list) > 1) {
674
-			throw new NotFoundException('Downloading more than 1 file');
675
-		}
676
-
677
-		foreach ($files_list as $file) {
678
-			$subNode = $node->get($file);
679
-			$this->singleFileDownloaded($share, $subNode);
680
-		}
681
-	}
682
-
683
-	/**
684
-	 * create activity if a single file was downloaded from a link share
685
-	 *
686
-	 * @param Share\IShare $share
687
-	 * @throws NotFoundException when trying to download a folder of a "hide download" share
688
-	 */
689
-	protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
-		if ($share->getHideDownload() && $node instanceof Folder) {
691
-			throw new NotFoundException('Downloading a folder');
692
-		}
693
-
694
-		$fileId = $node->getId();
695
-
696
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
-		$userNodeList = $userFolder->getById($fileId);
698
-		$userNode = $userNodeList[0];
699
-		$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
-		$userPath = $userFolder->getRelativePath($userNode->getPath());
701
-		$ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
-
703
-		$parameters = [$userPath];
704
-
705
-		if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
-			if ($node instanceof \OCP\Files\File) {
707
-				$subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
-			} else {
709
-				$subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
-			}
711
-			$parameters[] = $share->getSharedWith();
712
-		} else {
713
-			if ($node instanceof \OCP\Files\File) {
714
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
-			} else {
716
-				$subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
-			}
718
-		}
719
-
720
-		$this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
-
722
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
723
-			$parameters[0] = $ownerPath;
724
-			$this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
-		}
726
-	}
727
-
728
-	/**
729
-	 * publish activity
730
-	 *
731
-	 * @param string $subject
732
-	 * @param array $parameters
733
-	 * @param string $affectedUser
734
-	 * @param int $fileId
735
-	 * @param string $filePath
736
-	 */
737
-	protected function publishActivity($subject,
738
-										array $parameters,
739
-										$affectedUser,
740
-										$fileId,
741
-										$filePath) {
742
-		$event = $this->activityManager->generateEvent();
743
-		$event->setApp('files_sharing')
744
-			->setType('public_links')
745
-			->setSubject($subject, $parameters)
746
-			->setAffectedUser($affectedUser)
747
-			->setObject('files', $fileId, $filePath);
748
-		$this->activityManager->publish($event);
749
-	}
385
+            $freeSpace = $share->getNode()->getStorage()->free_space($share->getNode()->getInternalPath());
386
+            if ($freeSpace < \OCP\Files\FileInfo::SPACE_UNLIMITED) {
387
+                $freeSpace = max($freeSpace, 0);
388
+            } else {
389
+                $freeSpace = (INF > 0) ? INF: PHP_INT_MAX; // work around https://bugs.php.net/bug.php?id=69188
390
+            }
391
+
392
+            $hideFileList = !($share->getPermissions() & \OCP\Constants::PERMISSION_READ);
393
+            $maxUploadFilesize = $freeSpace;
394
+
395
+            $folder = new Template('files', 'list', '');
396
+
397
+            $folder->assign('dir', $shareNode->getRelativePath($folderNode->getPath()));
398
+            $folder->assign('dirToken', $this->getToken());
399
+            $folder->assign('permissions', \OCP\Constants::PERMISSION_READ);
400
+            $folder->assign('isPublic', true);
401
+            $folder->assign('hideFileList', $hideFileList);
402
+            $folder->assign('publicUploadEnabled', 'no');
403
+            // default to list view
404
+            $folder->assign('showgridview', false);
405
+            $folder->assign('uploadMaxFilesize', $maxUploadFilesize);
406
+            $folder->assign('uploadMaxHumanFilesize', \OCP\Util::humanFileSize($maxUploadFilesize));
407
+            $folder->assign('freeSpace', $freeSpace);
408
+            $folder->assign('usedSpacePercent', 0);
409
+            $folder->assign('trash', false);
410
+            $shareTmpl['folder'] = $folder->fetchPage();
411
+        } else {
412
+            $shareIsFolder = false;
413
+        }
414
+
415
+        // default to list view
416
+        $shareTmpl['showgridview'] = false;
417
+
418
+        $shareTmpl['hideFileList'] = $hideFileList;
419
+        $shareTmpl['downloadURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.downloadShare', ['token' => $this->getToken()]);
420
+        $shareTmpl['shareUrl'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare', ['token' => $this->getToken()]);
421
+        $shareTmpl['maxSizeAnimateGif'] = $this->config->getSystemValue('max_filesize_animated_gifs_public_sharing', 10);
422
+        $shareTmpl['previewEnabled'] = $this->config->getSystemValue('enable_previews', true);
423
+        $shareTmpl['previewMaxX'] = $this->config->getSystemValue('preview_max_x', 1024);
424
+        $shareTmpl['previewMaxY'] = $this->config->getSystemValue('preview_max_y', 1024);
425
+        $shareTmpl['disclaimer'] = $this->config->getAppValue('core', 'shareapi_public_link_disclaimertext', null);
426
+        $shareTmpl['previewURL'] = $shareTmpl['downloadURL'];
427
+
428
+        if ($shareTmpl['previewSupported']) {
429
+            $shareTmpl['previewImage'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview',
430
+                ['x' => 200, 'y' => 200, 'file' => $shareTmpl['directory_path'], 'token' => $shareTmpl['dirToken']]);
431
+            $ogPreview = $shareTmpl['previewImage'];
432
+
433
+            // We just have direct previews for image files
434
+            if ($shareNode->getMimePart() === 'image') {
435
+                $shareTmpl['previewURL'] = $this->urlGenerator->linkToRouteAbsolute('files_sharing.publicpreview.directLink', ['token' => $this->getToken()]);
436
+
437
+                $ogPreview = $shareTmpl['previewURL'];
438
+
439
+                //Whatapp is kind of picky about their size requirements
440
+                if ($this->request->isUserAgent(['/^WhatsApp/'])) {
441
+                    $ogPreview = $this->urlGenerator->linkToRouteAbsolute('files_sharing.PublicPreview.getPreview', [
442
+                        'token' => $this->getToken(),
443
+                        'x' => 256,
444
+                        'y' => 256,
445
+                        'a' => true,
446
+                    ]);
447
+                }
448
+            }
449
+        } else {
450
+            $shareTmpl['previewImage'] = $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'favicon-fb.png'));
451
+            $ogPreview = $shareTmpl['previewImage'];
452
+        }
453
+
454
+        // Load files we need
455
+        \OCP\Util::addScript('files', 'semaphore');
456
+        \OCP\Util::addScript('files', 'file-upload');
457
+        \OCP\Util::addStyle('files_sharing', 'publicView');
458
+        \OCP\Util::addScript('files_sharing', 'public');
459
+        \OCP\Util::addScript('files_sharing', 'templates');
460
+        \OCP\Util::addScript('files', 'fileactions');
461
+        \OCP\Util::addScript('files', 'fileactionsmenu');
462
+        \OCP\Util::addScript('files', 'jquery.fileupload');
463
+        \OCP\Util::addScript('files_sharing', 'files_drop');
464
+
465
+        if (isset($shareTmpl['folder'])) {
466
+            // JS required for folders
467
+            \OCP\Util::addStyle('files', 'merged');
468
+            \OCP\Util::addScript('files', 'filesummary');
469
+            \OCP\Util::addScript('files', 'templates');
470
+            \OCP\Util::addScript('files', 'breadcrumb');
471
+            \OCP\Util::addScript('files', 'fileinfomodel');
472
+            \OCP\Util::addScript('files', 'newfilemenu');
473
+            \OCP\Util::addScript('files', 'files');
474
+            \OCP\Util::addScript('files', 'filemultiselectmenu');
475
+            \OCP\Util::addScript('files', 'filelist');
476
+            \OCP\Util::addScript('files', 'keyboardshortcuts');
477
+            \OCP\Util::addScript('files', 'operationprogressbar');
478
+
479
+            // Load Viewer scripts
480
+            if (class_exists(LoadViewer::class)) {
481
+                $this->eventDispatcher->dispatch(LoadViewer::class, new LoadViewer());
482
+            }
483
+        }
484
+
485
+        // OpenGraph Support: http://ogp.me/
486
+        \OCP\Util::addHeader('meta', ['property' => "og:title", 'content' => $shareTmpl['filename']]);
487
+        \OCP\Util::addHeader('meta', ['property' => "og:description", 'content' => $this->defaults->getName() . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : '')]);
488
+        \OCP\Util::addHeader('meta', ['property' => "og:site_name", 'content' => $this->defaults->getName()]);
489
+        \OCP\Util::addHeader('meta', ['property' => "og:url", 'content' => $shareTmpl['shareUrl']]);
490
+        \OCP\Util::addHeader('meta', ['property' => "og:type", 'content' => "object"]);
491
+        \OCP\Util::addHeader('meta', ['property' => "og:image", 'content' => $ogPreview]);
492
+
493
+        $event = new GenericEvent(null, ['share' => $share]);
494
+        $this->eventDispatcher->dispatch('OCA\Files_Sharing::loadAdditionalScripts', $event);
495
+
496
+        $csp = new \OCP\AppFramework\Http\ContentSecurityPolicy();
497
+        $csp->addAllowedFrameDomain('\'self\'');
498
+
499
+        $response = new PublicTemplateResponse($this->appName, 'public', $shareTmpl);
500
+        $response->setHeaderTitle($shareTmpl['filename']);
501
+        if ($shareTmpl['shareOwner'] !== '') {
502
+            $response->setHeaderDetails($this->l10n->t('shared by %s', [$shareTmpl['shareOwner']]));
503
+        }
504
+
505
+        $isNoneFileDropFolder = $shareIsFolder === false || $share->getPermissions() !== \OCP\Constants::PERMISSION_CREATE;
506
+
507
+        if ($isNoneFileDropFolder && !$share->getHideDownload()) {
508
+            \OCP\Util::addScript('files_sharing', 'public_note');
509
+
510
+            $downloadWhite = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
511
+            $downloadAllWhite = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download-white', $shareTmpl['downloadURL'], 0);
512
+            $download = new SimpleMenuAction('download', $this->l10n->t('Download'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
513
+            $downloadAll = new SimpleMenuAction('download', $this->l10n->t('Download all files'), 'icon-download', $shareTmpl['downloadURL'], 10, $shareTmpl['fileSize']);
514
+            $directLink = new LinkMenuAction($this->l10n->t('Direct link'), 'icon-public', $shareTmpl['previewURL']);
515
+            $externalShare = new ExternalShareMenuAction($this->l10n->t('Add to your Nextcloud'), 'icon-external', $shareTmpl['owner'], $shareTmpl['shareOwner'], $shareTmpl['filename']);
516
+
517
+            $responseComposer = [];
518
+
519
+            if ($shareIsFolder) {
520
+                $responseComposer[] = $downloadAllWhite;
521
+                $responseComposer[] = $downloadAll;
522
+            } else {
523
+                $responseComposer[] = $downloadWhite;
524
+                $responseComposer[] = $download;
525
+            }
526
+            $responseComposer[] = $directLink;
527
+            if ($this->federatedShareProvider->isOutgoingServer2serverShareEnabled()) {
528
+                $responseComposer[] = $externalShare;
529
+            }
530
+
531
+            $response->setHeaderActions($responseComposer);
532
+        }
533
+
534
+        $response->setContentSecurityPolicy($csp);
535
+
536
+        $this->emitAccessShareHook($share);
537
+
538
+        return $response;
539
+    }
540
+
541
+    /**
542
+     * @PublicPage
543
+     * @NoCSRFRequired
544
+     * @NoSameSiteCookieRequired
545
+     *
546
+     * @param string $token
547
+     * @param string $files
548
+     * @param string $path
549
+     * @param string $downloadStartSecret
550
+     * @return void|\OCP\AppFramework\Http\Response
551
+     * @throws NotFoundException
552
+     */
553
+    public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') {
554
+        \OC_User::setIncognitoMode(true);
555
+
556
+        $share = $this->shareManager->getShareByToken($token);
557
+
558
+        if (!($share->getPermissions() & \OCP\Constants::PERMISSION_READ)) {
559
+            return new \OCP\AppFramework\Http\DataResponse('Share is read-only');
560
+        }
561
+
562
+        $files_list = null;
563
+        if (!is_null($files)) { // download selected files
564
+            $files_list = json_decode($files);
565
+            // in case we get only a single file
566
+            if ($files_list === null) {
567
+                $files_list = [$files];
568
+            }
569
+            // Just in case $files is a single int like '1234'
570
+            if (!is_array($files_list)) {
571
+                $files_list = [$files_list];
572
+            }
573
+        }
574
+
575
+        if (!$this->validateShare($share)) {
576
+            throw new NotFoundException();
577
+        }
578
+
579
+        $userFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
580
+        $originalSharePath = $userFolder->getRelativePath($share->getNode()->getPath());
581
+
582
+
583
+        // Single file share
584
+        if ($share->getNode() instanceof \OCP\Files\File) {
585
+            // Single file download
586
+            $this->singleFileDownloaded($share, $share->getNode());
587
+        }
588
+        // Directory share
589
+        else {
590
+            /** @var \OCP\Files\Folder $node */
591
+            $node = $share->getNode();
592
+
593
+            // Try to get the path
594
+            if ($path !== '') {
595
+                try {
596
+                    $node = $node->get($path);
597
+                } catch (NotFoundException $e) {
598
+                    $this->emitAccessShareHook($share, 404, 'Share not found');
599
+                    return new NotFoundResponse();
600
+                }
601
+            }
602
+
603
+            $originalSharePath = $userFolder->getRelativePath($node->getPath());
604
+
605
+            if ($node instanceof \OCP\Files\File) {
606
+                // Single file download
607
+                $this->singleFileDownloaded($share, $share->getNode());
608
+            } else {
609
+                try {
610
+                    if (!empty($files_list)) {
611
+                        $this->fileListDownloaded($share, $files_list, $node);
612
+                    } else {
613
+                        // The folder is downloaded
614
+                        $this->singleFileDownloaded($share, $share->getNode());
615
+                    }
616
+                } catch (NotFoundException $e) {
617
+                    return new NotFoundResponse();
618
+                }
619
+            }
620
+        }
621
+
622
+        /* FIXME: We should do this all nicely in OCP */
623
+        OC_Util::tearDownFS();
624
+        OC_Util::setupFS($share->getShareOwner());
625
+
626
+        /**
627
+         * this sets a cookie to be able to recognize the start of the download
628
+         * the content must not be longer than 32 characters and must only contain
629
+         * alphanumeric characters
630
+         */
631
+        if (!empty($downloadStartSecret)
632
+            && !isset($downloadStartSecret[32])
633
+            && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) {
634
+
635
+            // FIXME: set on the response once we use an actual app framework response
636
+            setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/');
637
+        }
638
+
639
+        $this->emitAccessShareHook($share);
640
+
641
+        $server_params = [ 'head' => $this->request->getMethod() === 'HEAD' ];
642
+
643
+        /**
644
+         * Http range requests support
645
+         */
646
+        if (isset($_SERVER['HTTP_RANGE'])) {
647
+            $server_params['range'] = $this->request->getHeader('Range');
648
+        }
649
+
650
+        // download selected files
651
+        if (!is_null($files) && $files !== '') {
652
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
653
+            // after dispatching the request which results in a "Cannot modify header information" notice.
654
+            OC_Files::get($originalSharePath, $files_list, $server_params);
655
+            exit();
656
+        } else {
657
+            // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well
658
+            // after dispatching the request which results in a "Cannot modify header information" notice.
659
+            OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $server_params);
660
+            exit();
661
+        }
662
+    }
663
+
664
+    /**
665
+     * create activity for every downloaded file
666
+     *
667
+     * @param Share\IShare $share
668
+     * @param array $files_list
669
+     * @param \OCP\Files\Folder $node
670
+     * @throws NotFoundException when trying to download a folder or multiple files of a "hide download" share
671
+     */
672
+    protected function fileListDownloaded(Share\IShare $share, array $files_list, \OCP\Files\Folder $node) {
673
+        if ($share->getHideDownload() && count($files_list) > 1) {
674
+            throw new NotFoundException('Downloading more than 1 file');
675
+        }
676
+
677
+        foreach ($files_list as $file) {
678
+            $subNode = $node->get($file);
679
+            $this->singleFileDownloaded($share, $subNode);
680
+        }
681
+    }
682
+
683
+    /**
684
+     * create activity if a single file was downloaded from a link share
685
+     *
686
+     * @param Share\IShare $share
687
+     * @throws NotFoundException when trying to download a folder of a "hide download" share
688
+     */
689
+    protected function singleFileDownloaded(Share\IShare $share, \OCP\Files\Node $node) {
690
+        if ($share->getHideDownload() && $node instanceof Folder) {
691
+            throw new NotFoundException('Downloading a folder');
692
+        }
693
+
694
+        $fileId = $node->getId();
695
+
696
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
697
+        $userNodeList = $userFolder->getById($fileId);
698
+        $userNode = $userNodeList[0];
699
+        $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
700
+        $userPath = $userFolder->getRelativePath($userNode->getPath());
701
+        $ownerPath = $ownerFolder->getRelativePath($node->getPath());
702
+
703
+        $parameters = [$userPath];
704
+
705
+        if ($share->getShareType() === IShare::TYPE_EMAIL) {
706
+            if ($node instanceof \OCP\Files\File) {
707
+                $subject = Downloads::SUBJECT_SHARED_FILE_BY_EMAIL_DOWNLOADED;
708
+            } else {
709
+                $subject = Downloads::SUBJECT_SHARED_FOLDER_BY_EMAIL_DOWNLOADED;
710
+            }
711
+            $parameters[] = $share->getSharedWith();
712
+        } else {
713
+            if ($node instanceof \OCP\Files\File) {
714
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED;
715
+            } else {
716
+                $subject = Downloads::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED;
717
+            }
718
+        }
719
+
720
+        $this->publishActivity($subject, $parameters, $share->getSharedBy(), $fileId, $userPath);
721
+
722
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
723
+            $parameters[0] = $ownerPath;
724
+            $this->publishActivity($subject, $parameters, $share->getShareOwner(), $fileId, $ownerPath);
725
+        }
726
+    }
727
+
728
+    /**
729
+     * publish activity
730
+     *
731
+     * @param string $subject
732
+     * @param array $parameters
733
+     * @param string $affectedUser
734
+     * @param int $fileId
735
+     * @param string $filePath
736
+     */
737
+    protected function publishActivity($subject,
738
+                                        array $parameters,
739
+                                        $affectedUser,
740
+                                        $fileId,
741
+                                        $filePath) {
742
+        $event = $this->activityManager->generateEvent();
743
+        $event->setApp('files_sharing')
744
+            ->setType('public_links')
745
+            ->setSubject($subject, $parameters)
746
+            ->setAffectedUser($affectedUser)
747
+            ->setObject('files', $fileId, $filePath);
748
+        $this->activityManager->publish($event);
749
+    }
750 750
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Node.php 1 patch
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -48,372 +48,372 @@
 block discarded – undo
48 48
 
49 49
 abstract class Node implements \Sabre\DAV\INode {
50 50
 
51
-	/**
52
-	 * @var \OC\Files\View
53
-	 */
54
-	protected $fileView;
55
-
56
-	/**
57
-	 * The path to the current node
58
-	 *
59
-	 * @var string
60
-	 */
61
-	protected $path;
62
-
63
-	/**
64
-	 * node properties cache
65
-	 *
66
-	 * @var array
67
-	 */
68
-	protected $property_cache = null;
69
-
70
-	/**
71
-	 * @var \OCP\Files\FileInfo
72
-	 */
73
-	protected $info;
74
-
75
-	/**
76
-	 * @var IManager
77
-	 */
78
-	protected $shareManager;
79
-
80
-	/**
81
-	 * Sets up the node, expects a full path name
82
-	 *
83
-	 * @param \OC\Files\View $view
84
-	 * @param \OCP\Files\FileInfo $info
85
-	 * @param IManager $shareManager
86
-	 */
87
-	public function __construct(View $view, FileInfo $info, IManager $shareManager = null) {
88
-		$this->fileView = $view;
89
-		$this->path = $this->fileView->getRelativePath($info->getPath());
90
-		$this->info = $info;
91
-		if ($shareManager) {
92
-			$this->shareManager = $shareManager;
93
-		} else {
94
-			$this->shareManager = \OC::$server->getShareManager();
95
-		}
96
-	}
97
-
98
-	protected function refreshInfo() {
99
-		$this->info = $this->fileView->getFileInfo($this->path);
100
-	}
101
-
102
-	/**
103
-	 *  Returns the name of the node
104
-	 *
105
-	 * @return string
106
-	 */
107
-	public function getName() {
108
-		return $this->info->getName();
109
-	}
110
-
111
-	/**
112
-	 * Returns the full path
113
-	 *
114
-	 * @return string
115
-	 */
116
-	public function getPath() {
117
-		return $this->path;
118
-	}
119
-
120
-	/**
121
-	 * Renames the node
122
-	 *
123
-	 * @param string $name The new name
124
-	 * @throws \Sabre\DAV\Exception\BadRequest
125
-	 * @throws \Sabre\DAV\Exception\Forbidden
126
-	 */
127
-	public function setName($name) {
128
-
129
-		// rename is only allowed if the update privilege is granted
130
-		if (!$this->info->isUpdateable()) {
131
-			throw new \Sabre\DAV\Exception\Forbidden();
132
-		}
133
-
134
-		list($parentPath,) = \Sabre\Uri\split($this->path);
135
-		list(, $newName) = \Sabre\Uri\split($name);
136
-
137
-		// verify path of the target
138
-		$this->verifyPath();
139
-
140
-		$newPath = $parentPath . '/' . $newName;
141
-
142
-		if (!$this->fileView->rename($this->path, $newPath)) {
143
-			throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
144
-		}
145
-
146
-		$this->path = $newPath;
147
-
148
-		$this->refreshInfo();
149
-	}
150
-
151
-	public function setPropertyCache($property_cache) {
152
-		$this->property_cache = $property_cache;
153
-	}
154
-
155
-	/**
156
-	 * Returns the last modification time, as a unix timestamp
157
-	 *
158
-	 * @return int timestamp as integer
159
-	 */
160
-	public function getLastModified() {
161
-		$timestamp = $this->info->getMtime();
162
-		if (!empty($timestamp)) {
163
-			return (int)$timestamp;
164
-		}
165
-		return $timestamp;
166
-	}
167
-
168
-	/**
169
-	 *  sets the last modification time of the file (mtime) to the value given
170
-	 *  in the second parameter or to now if the second param is empty.
171
-	 *  Even if the modification time is set to a custom value the access time is set to now.
172
-	 */
173
-	public function touch($mtime) {
174
-		$mtime = $this->sanitizeMtime($mtime);
175
-		$this->fileView->touch($this->path, $mtime);
176
-		$this->refreshInfo();
177
-	}
178
-
179
-	/**
180
-	 * Returns the ETag for a file
181
-	 *
182
-	 * An ETag is a unique identifier representing the current version of the
183
-	 * file. If the file changes, the ETag MUST change.  The ETag is an
184
-	 * arbitrary string, but MUST be surrounded by double-quotes.
185
-	 *
186
-	 * Return null if the ETag can not effectively be determined
187
-	 *
188
-	 * @return string
189
-	 */
190
-	public function getETag() {
191
-		return '"' . $this->info->getEtag() . '"';
192
-	}
193
-
194
-	/**
195
-	 * Sets the ETag
196
-	 *
197
-	 * @param string $etag
198
-	 *
199
-	 * @return int file id of updated file or -1 on failure
200
-	 */
201
-	public function setETag($etag) {
202
-		return $this->fileView->putFileInfo($this->path, ['etag' => $etag]);
203
-	}
204
-
205
-	public function setCreationTime(int $time) {
206
-		return $this->fileView->putFileInfo($this->path, ['creation_time' => $time]);
207
-	}
208
-
209
-	public function setUploadTime(int $time) {
210
-		return $this->fileView->putFileInfo($this->path, ['upload_time' => $time]);
211
-	}
212
-
213
-	/**
214
-	 * Returns the size of the node, in bytes
215
-	 *
216
-	 * @return integer
217
-	 */
218
-	public function getSize() {
219
-		return $this->info->getSize();
220
-	}
221
-
222
-	/**
223
-	 * Returns the cache's file id
224
-	 *
225
-	 * @return int
226
-	 */
227
-	public function getId() {
228
-		return $this->info->getId();
229
-	}
230
-
231
-	/**
232
-	 * @return string|null
233
-	 */
234
-	public function getFileId() {
235
-		if ($this->info->getId()) {
236
-			$instanceId = \OC_Util::getInstanceId();
237
-			$id = sprintf('%08d', $this->info->getId());
238
-			return $id . $instanceId;
239
-		}
240
-
241
-		return null;
242
-	}
243
-
244
-	/**
245
-	 * @return integer
246
-	 */
247
-	public function getInternalFileId() {
248
-		return $this->info->getId();
249
-	}
250
-
251
-	/**
252
-	 * @param string $user
253
-	 * @return int
254
-	 */
255
-	public function getSharePermissions($user) {
256
-
257
-		// check of we access a federated share
258
-		if ($user !== null) {
259
-			try {
260
-				$share = $this->shareManager->getShareByToken($user);
261
-				return $share->getPermissions();
262
-			} catch (ShareNotFound $e) {
263
-				// ignore
264
-			}
265
-		}
266
-
267
-		try {
268
-			$storage = $this->info->getStorage();
269
-		} catch (StorageNotAvailableException $e) {
270
-			$storage = null;
271
-		}
272
-
273
-		if ($storage && $storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
274
-			/** @var \OCA\Files_Sharing\SharedStorage $storage */
275
-			$permissions = (int)$storage->getShare()->getPermissions();
276
-		} else {
277
-			$permissions = $this->info->getPermissions();
278
-		}
279
-
280
-		/*
51
+    /**
52
+     * @var \OC\Files\View
53
+     */
54
+    protected $fileView;
55
+
56
+    /**
57
+     * The path to the current node
58
+     *
59
+     * @var string
60
+     */
61
+    protected $path;
62
+
63
+    /**
64
+     * node properties cache
65
+     *
66
+     * @var array
67
+     */
68
+    protected $property_cache = null;
69
+
70
+    /**
71
+     * @var \OCP\Files\FileInfo
72
+     */
73
+    protected $info;
74
+
75
+    /**
76
+     * @var IManager
77
+     */
78
+    protected $shareManager;
79
+
80
+    /**
81
+     * Sets up the node, expects a full path name
82
+     *
83
+     * @param \OC\Files\View $view
84
+     * @param \OCP\Files\FileInfo $info
85
+     * @param IManager $shareManager
86
+     */
87
+    public function __construct(View $view, FileInfo $info, IManager $shareManager = null) {
88
+        $this->fileView = $view;
89
+        $this->path = $this->fileView->getRelativePath($info->getPath());
90
+        $this->info = $info;
91
+        if ($shareManager) {
92
+            $this->shareManager = $shareManager;
93
+        } else {
94
+            $this->shareManager = \OC::$server->getShareManager();
95
+        }
96
+    }
97
+
98
+    protected function refreshInfo() {
99
+        $this->info = $this->fileView->getFileInfo($this->path);
100
+    }
101
+
102
+    /**
103
+     *  Returns the name of the node
104
+     *
105
+     * @return string
106
+     */
107
+    public function getName() {
108
+        return $this->info->getName();
109
+    }
110
+
111
+    /**
112
+     * Returns the full path
113
+     *
114
+     * @return string
115
+     */
116
+    public function getPath() {
117
+        return $this->path;
118
+    }
119
+
120
+    /**
121
+     * Renames the node
122
+     *
123
+     * @param string $name The new name
124
+     * @throws \Sabre\DAV\Exception\BadRequest
125
+     * @throws \Sabre\DAV\Exception\Forbidden
126
+     */
127
+    public function setName($name) {
128
+
129
+        // rename is only allowed if the update privilege is granted
130
+        if (!$this->info->isUpdateable()) {
131
+            throw new \Sabre\DAV\Exception\Forbidden();
132
+        }
133
+
134
+        list($parentPath,) = \Sabre\Uri\split($this->path);
135
+        list(, $newName) = \Sabre\Uri\split($name);
136
+
137
+        // verify path of the target
138
+        $this->verifyPath();
139
+
140
+        $newPath = $parentPath . '/' . $newName;
141
+
142
+        if (!$this->fileView->rename($this->path, $newPath)) {
143
+            throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
144
+        }
145
+
146
+        $this->path = $newPath;
147
+
148
+        $this->refreshInfo();
149
+    }
150
+
151
+    public function setPropertyCache($property_cache) {
152
+        $this->property_cache = $property_cache;
153
+    }
154
+
155
+    /**
156
+     * Returns the last modification time, as a unix timestamp
157
+     *
158
+     * @return int timestamp as integer
159
+     */
160
+    public function getLastModified() {
161
+        $timestamp = $this->info->getMtime();
162
+        if (!empty($timestamp)) {
163
+            return (int)$timestamp;
164
+        }
165
+        return $timestamp;
166
+    }
167
+
168
+    /**
169
+     *  sets the last modification time of the file (mtime) to the value given
170
+     *  in the second parameter or to now if the second param is empty.
171
+     *  Even if the modification time is set to a custom value the access time is set to now.
172
+     */
173
+    public function touch($mtime) {
174
+        $mtime = $this->sanitizeMtime($mtime);
175
+        $this->fileView->touch($this->path, $mtime);
176
+        $this->refreshInfo();
177
+    }
178
+
179
+    /**
180
+     * Returns the ETag for a file
181
+     *
182
+     * An ETag is a unique identifier representing the current version of the
183
+     * file. If the file changes, the ETag MUST change.  The ETag is an
184
+     * arbitrary string, but MUST be surrounded by double-quotes.
185
+     *
186
+     * Return null if the ETag can not effectively be determined
187
+     *
188
+     * @return string
189
+     */
190
+    public function getETag() {
191
+        return '"' . $this->info->getEtag() . '"';
192
+    }
193
+
194
+    /**
195
+     * Sets the ETag
196
+     *
197
+     * @param string $etag
198
+     *
199
+     * @return int file id of updated file or -1 on failure
200
+     */
201
+    public function setETag($etag) {
202
+        return $this->fileView->putFileInfo($this->path, ['etag' => $etag]);
203
+    }
204
+
205
+    public function setCreationTime(int $time) {
206
+        return $this->fileView->putFileInfo($this->path, ['creation_time' => $time]);
207
+    }
208
+
209
+    public function setUploadTime(int $time) {
210
+        return $this->fileView->putFileInfo($this->path, ['upload_time' => $time]);
211
+    }
212
+
213
+    /**
214
+     * Returns the size of the node, in bytes
215
+     *
216
+     * @return integer
217
+     */
218
+    public function getSize() {
219
+        return $this->info->getSize();
220
+    }
221
+
222
+    /**
223
+     * Returns the cache's file id
224
+     *
225
+     * @return int
226
+     */
227
+    public function getId() {
228
+        return $this->info->getId();
229
+    }
230
+
231
+    /**
232
+     * @return string|null
233
+     */
234
+    public function getFileId() {
235
+        if ($this->info->getId()) {
236
+            $instanceId = \OC_Util::getInstanceId();
237
+            $id = sprintf('%08d', $this->info->getId());
238
+            return $id . $instanceId;
239
+        }
240
+
241
+        return null;
242
+    }
243
+
244
+    /**
245
+     * @return integer
246
+     */
247
+    public function getInternalFileId() {
248
+        return $this->info->getId();
249
+    }
250
+
251
+    /**
252
+     * @param string $user
253
+     * @return int
254
+     */
255
+    public function getSharePermissions($user) {
256
+
257
+        // check of we access a federated share
258
+        if ($user !== null) {
259
+            try {
260
+                $share = $this->shareManager->getShareByToken($user);
261
+                return $share->getPermissions();
262
+            } catch (ShareNotFound $e) {
263
+                // ignore
264
+            }
265
+        }
266
+
267
+        try {
268
+            $storage = $this->info->getStorage();
269
+        } catch (StorageNotAvailableException $e) {
270
+            $storage = null;
271
+        }
272
+
273
+        if ($storage && $storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
274
+            /** @var \OCA\Files_Sharing\SharedStorage $storage */
275
+            $permissions = (int)$storage->getShare()->getPermissions();
276
+        } else {
277
+            $permissions = $this->info->getPermissions();
278
+        }
279
+
280
+        /*
281 281
 		 * We can always share non moveable mount points with DELETE and UPDATE
282 282
 		 * Eventually we need to do this properly
283 283
 		 */
284
-		$mountpoint = $this->info->getMountPoint();
285
-		if (!($mountpoint instanceof MoveableMount)) {
286
-			$mountpointpath = $mountpoint->getMountPoint();
287
-			if (substr($mountpointpath, -1) === '/') {
288
-				$mountpointpath = substr($mountpointpath, 0, -1);
289
-			}
290
-
291
-			if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) {
292
-				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
293
-			}
294
-		}
295
-
296
-		/*
284
+        $mountpoint = $this->info->getMountPoint();
285
+        if (!($mountpoint instanceof MoveableMount)) {
286
+            $mountpointpath = $mountpoint->getMountPoint();
287
+            if (substr($mountpointpath, -1) === '/') {
288
+                $mountpointpath = substr($mountpointpath, 0, -1);
289
+            }
290
+
291
+            if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) {
292
+                $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
293
+            }
294
+        }
295
+
296
+        /*
297 297
 		 * Files can't have create or delete permissions
298 298
 		 */
299
-		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
300
-			$permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
301
-		}
302
-
303
-		return $permissions;
304
-	}
305
-
306
-	/**
307
-	 * @param string $user
308
-	 * @return string
309
-	 */
310
-	public function getNoteFromShare($user) {
311
-		if ($user === null) {
312
-			return '';
313
-		}
314
-
315
-		$types = [
316
-			IShare::TYPE_USER,
317
-			IShare::TYPE_GROUP,
318
-			IShare::TYPE_CIRCLE,
319
-			IShare::TYPE_ROOM
320
-		];
321
-
322
-		foreach ($types as $shareType) {
323
-			$shares = $this->shareManager->getSharedWith($user, $shareType, $this, -1);
324
-			foreach ($shares as $share) {
325
-				$note = $share->getNote();
326
-				if ($share->getShareOwner() !== $user && !empty($note)) {
327
-					return $note;
328
-				}
329
-			}
330
-		}
331
-
332
-		return '';
333
-	}
334
-
335
-	/**
336
-	 * @return string
337
-	 */
338
-	public function getDavPermissions() {
339
-		$p = '';
340
-		if ($this->info->isShared()) {
341
-			$p .= 'S';
342
-		}
343
-		if ($this->info->isShareable()) {
344
-			$p .= 'R';
345
-		}
346
-		if ($this->info->isMounted()) {
347
-			$p .= 'M';
348
-		}
349
-		if ($this->info->isReadable()) {
350
-			$p .= 'G';
351
-		}
352
-		if ($this->info->isDeletable()) {
353
-			$p .= 'D';
354
-		}
355
-		if ($this->info->isUpdateable()) {
356
-			$p .= 'NV'; // Renameable, Moveable
357
-		}
358
-		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
359
-			if ($this->info->isUpdateable()) {
360
-				$p .= 'W';
361
-			}
362
-		} else {
363
-			if ($this->info->isCreatable()) {
364
-				$p .= 'CK';
365
-			}
366
-		}
367
-		return $p;
368
-	}
369
-
370
-	public function getOwner() {
371
-		return $this->info->getOwner();
372
-	}
373
-
374
-	protected function verifyPath() {
375
-		try {
376
-			$fileName = basename($this->info->getPath());
377
-			$this->fileView->verifyPath($this->path, $fileName);
378
-		} catch (\OCP\Files\InvalidPathException $ex) {
379
-			throw new InvalidPath($ex->getMessage());
380
-		}
381
-	}
382
-
383
-	/**
384
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
385
-	 */
386
-	public function acquireLock($type) {
387
-		$this->fileView->lockFile($this->path, $type);
388
-	}
389
-
390
-	/**
391
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
392
-	 */
393
-	public function releaseLock($type) {
394
-		$this->fileView->unlockFile($this->path, $type);
395
-	}
396
-
397
-	/**
398
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
399
-	 */
400
-	public function changeLock($type) {
401
-		$this->fileView->changeLock($this->path, $type);
402
-	}
403
-
404
-	public function getFileInfo() {
405
-		return $this->info;
406
-	}
407
-
408
-	protected function sanitizeMtime($mtimeFromRequest) {
409
-		// In PHP 5.X "is_numeric" returns true for strings in hexadecimal
410
-		// notation. This is no longer the case in PHP 7.X, so this check
411
-		// ensures that strings with hexadecimal notations fail too in PHP 5.X.
412
-		$isHexadecimal = is_string($mtimeFromRequest) && preg_match('/^\s*0[xX]/', $mtimeFromRequest);
413
-		if ($isHexadecimal || !is_numeric($mtimeFromRequest)) {
414
-			throw new \InvalidArgumentException('X-OC-MTime header must be an integer (unix timestamp).');
415
-		}
416
-
417
-		return (int)$mtimeFromRequest;
418
-	}
299
+        if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
300
+            $permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
301
+        }
302
+
303
+        return $permissions;
304
+    }
305
+
306
+    /**
307
+     * @param string $user
308
+     * @return string
309
+     */
310
+    public function getNoteFromShare($user) {
311
+        if ($user === null) {
312
+            return '';
313
+        }
314
+
315
+        $types = [
316
+            IShare::TYPE_USER,
317
+            IShare::TYPE_GROUP,
318
+            IShare::TYPE_CIRCLE,
319
+            IShare::TYPE_ROOM
320
+        ];
321
+
322
+        foreach ($types as $shareType) {
323
+            $shares = $this->shareManager->getSharedWith($user, $shareType, $this, -1);
324
+            foreach ($shares as $share) {
325
+                $note = $share->getNote();
326
+                if ($share->getShareOwner() !== $user && !empty($note)) {
327
+                    return $note;
328
+                }
329
+            }
330
+        }
331
+
332
+        return '';
333
+    }
334
+
335
+    /**
336
+     * @return string
337
+     */
338
+    public function getDavPermissions() {
339
+        $p = '';
340
+        if ($this->info->isShared()) {
341
+            $p .= 'S';
342
+        }
343
+        if ($this->info->isShareable()) {
344
+            $p .= 'R';
345
+        }
346
+        if ($this->info->isMounted()) {
347
+            $p .= 'M';
348
+        }
349
+        if ($this->info->isReadable()) {
350
+            $p .= 'G';
351
+        }
352
+        if ($this->info->isDeletable()) {
353
+            $p .= 'D';
354
+        }
355
+        if ($this->info->isUpdateable()) {
356
+            $p .= 'NV'; // Renameable, Moveable
357
+        }
358
+        if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
359
+            if ($this->info->isUpdateable()) {
360
+                $p .= 'W';
361
+            }
362
+        } else {
363
+            if ($this->info->isCreatable()) {
364
+                $p .= 'CK';
365
+            }
366
+        }
367
+        return $p;
368
+    }
369
+
370
+    public function getOwner() {
371
+        return $this->info->getOwner();
372
+    }
373
+
374
+    protected function verifyPath() {
375
+        try {
376
+            $fileName = basename($this->info->getPath());
377
+            $this->fileView->verifyPath($this->path, $fileName);
378
+        } catch (\OCP\Files\InvalidPathException $ex) {
379
+            throw new InvalidPath($ex->getMessage());
380
+        }
381
+    }
382
+
383
+    /**
384
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
385
+     */
386
+    public function acquireLock($type) {
387
+        $this->fileView->lockFile($this->path, $type);
388
+    }
389
+
390
+    /**
391
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
392
+     */
393
+    public function releaseLock($type) {
394
+        $this->fileView->unlockFile($this->path, $type);
395
+    }
396
+
397
+    /**
398
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
399
+     */
400
+    public function changeLock($type) {
401
+        $this->fileView->changeLock($this->path, $type);
402
+    }
403
+
404
+    public function getFileInfo() {
405
+        return $this->info;
406
+    }
407
+
408
+    protected function sanitizeMtime($mtimeFromRequest) {
409
+        // In PHP 5.X "is_numeric" returns true for strings in hexadecimal
410
+        // notation. This is no longer the case in PHP 7.X, so this check
411
+        // ensures that strings with hexadecimal notations fail too in PHP 5.X.
412
+        $isHexadecimal = is_string($mtimeFromRequest) && preg_match('/^\s*0[xX]/', $mtimeFromRequest);
413
+        if ($isHexadecimal || !is_numeric($mtimeFromRequest)) {
414
+            throw new \InvalidArgumentException('X-OC-MTime header must be an integer (unix timestamp).');
415
+        }
416
+
417
+        return (int)$mtimeFromRequest;
418
+    }
419 419
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/SharesPlugin.php 1 patch
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -35,181 +35,181 @@
 block discarded – undo
35 35
  * Sabre Plugin to provide share-related properties
36 36
  */
37 37
 class SharesPlugin extends \Sabre\DAV\ServerPlugin {
38
-	public const NS_OWNCLOUD = 'http://owncloud.org/ns';
39
-	public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
40
-	public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
41
-	public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
42
-
43
-	/**
44
-	 * Reference to main server object
45
-	 *
46
-	 * @var \Sabre\DAV\Server
47
-	 */
48
-	private $server;
49
-
50
-	/**
51
-	 * @var \OCP\Share\IManager
52
-	 */
53
-	private $shareManager;
54
-
55
-	/**
56
-	 * @var \Sabre\DAV\Tree
57
-	 */
58
-	private $tree;
59
-
60
-	/**
61
-	 * @var string
62
-	 */
63
-	private $userId;
64
-
65
-	/**
66
-	 * @var \OCP\Files\Folder
67
-	 */
68
-	private $userFolder;
69
-
70
-	/** @var IShare[] */
71
-	private $cachedShares = [];
72
-
73
-	private $cachedFolders = [];
74
-
75
-	/**
76
-	 * @param \Sabre\DAV\Tree $tree tree
77
-	 * @param IUserSession $userSession user session
78
-	 * @param \OCP\Files\Folder $userFolder user home folder
79
-	 * @param \OCP\Share\IManager $shareManager share manager
80
-	 */
81
-	public function __construct(
82
-		\Sabre\DAV\Tree $tree,
83
-		IUserSession $userSession,
84
-		\OCP\Files\Folder $userFolder,
85
-		\OCP\Share\IManager $shareManager
86
-	) {
87
-		$this->tree = $tree;
88
-		$this->shareManager = $shareManager;
89
-		$this->userFolder = $userFolder;
90
-		$this->userId = $userSession->getUser()->getUID();
91
-	}
92
-
93
-	/**
94
-	 * This initializes the plugin.
95
-	 *
96
-	 * This function is called by \Sabre\DAV\Server, after
97
-	 * addPlugin is called.
98
-	 *
99
-	 * This method should set up the required event subscriptions.
100
-	 *
101
-	 * @param \Sabre\DAV\Server $server
102
-	 */
103
-	public function initialize(\Sabre\DAV\Server $server) {
104
-		$server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
105
-		$server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
106
-		$server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
107
-		$server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
108
-
109
-		$this->server = $server;
110
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
111
-	}
112
-
113
-	private function getShare(\OCP\Files\Node $node): array {
114
-		$result = [];
115
-		$requestedShareTypes = [
116
-			IShare::TYPE_USER,
117
-			IShare::TYPE_GROUP,
118
-			IShare::TYPE_LINK,
119
-			IShare::TYPE_REMOTE,
120
-			IShare::TYPE_EMAIL,
121
-			IShare::TYPE_ROOM,
122
-			IShare::TYPE_CIRCLE,
123
-		];
124
-		foreach ($requestedShareTypes as $requestedShareType) {
125
-			$shares = $this->shareManager->getSharesBy(
126
-				$this->userId,
127
-				$requestedShareType,
128
-				$node,
129
-				false,
130
-				-1
131
-			);
132
-			foreach ($shares as $share) {
133
-				$result[] = $share;
134
-			}
135
-		}
136
-		return $result;
137
-	}
138
-
139
-	private function getSharesFolder(\OCP\Files\Folder $node): array {
140
-		return $this->shareManager->getSharesInFolder(
141
-			$this->userId,
142
-			$node,
143
-			true
144
-		);
145
-	}
146
-
147
-	private function getShares(\Sabre\DAV\INode $sabreNode): array {
148
-		if (isset($this->cachedShares[$sabreNode->getId()])) {
149
-			$shares = $this->cachedShares[$sabreNode->getId()];
150
-		} else {
151
-			list($parentPath,) = \Sabre\Uri\split($sabreNode->getPath());
152
-			if ($parentPath === '') {
153
-				$parentPath = '/';
154
-			}
155
-			// if we already cached the folder this file is in we know there are no shares for this file
156
-			if (array_search($parentPath, $this->cachedFolders) === false) {
157
-				$node = $this->userFolder->get($sabreNode->getPath());
158
-				$shares = $this->getShare($node);
159
-				$this->cachedShares[$sabreNode->getId()] = $shares;
160
-			} else {
161
-				return [];
162
-			}
163
-		}
164
-
165
-		return $shares;
166
-	}
167
-
168
-	/**
169
-	 * Adds shares to propfind response
170
-	 *
171
-	 * @param PropFind $propFind propfind object
172
-	 * @param \Sabre\DAV\INode $sabreNode sabre node
173
-	 */
174
-	public function handleGetProperties(
175
-		PropFind $propFind,
176
-		\Sabre\DAV\INode $sabreNode
177
-	) {
178
-		if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
179
-			return;
180
-		}
181
-
182
-		// need prefetch ?
183
-		if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
184
-			&& $propFind->getDepth() !== 0
185
-			&& (
186
-				!is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
187
-				!is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
188
-			)
189
-		) {
190
-			$folderNode = $this->userFolder->get($sabreNode->getPath());
191
-
192
-			$this->cachedFolders[] = $sabreNode->getPath();
193
-			$childShares = $this->getSharesFolder($folderNode);
194
-			foreach ($childShares as $id => $shares) {
195
-				$this->cachedShares[$id] = $shares;
196
-			}
197
-		}
198
-
199
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
200
-			$shares = $this->getShares($sabreNode);
201
-
202
-			$shareTypes = array_unique(array_map(function (IShare $share) {
203
-				return $share->getShareType();
204
-			}, $shares));
205
-
206
-			return new ShareTypeList($shareTypes);
207
-		});
208
-
209
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
210
-			$shares = $this->getShares($sabreNode);
211
-
212
-			return new ShareeList($shares);
213
-		});
214
-	}
38
+    public const NS_OWNCLOUD = 'http://owncloud.org/ns';
39
+    public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
40
+    public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
41
+    public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
42
+
43
+    /**
44
+     * Reference to main server object
45
+     *
46
+     * @var \Sabre\DAV\Server
47
+     */
48
+    private $server;
49
+
50
+    /**
51
+     * @var \OCP\Share\IManager
52
+     */
53
+    private $shareManager;
54
+
55
+    /**
56
+     * @var \Sabre\DAV\Tree
57
+     */
58
+    private $tree;
59
+
60
+    /**
61
+     * @var string
62
+     */
63
+    private $userId;
64
+
65
+    /**
66
+     * @var \OCP\Files\Folder
67
+     */
68
+    private $userFolder;
69
+
70
+    /** @var IShare[] */
71
+    private $cachedShares = [];
72
+
73
+    private $cachedFolders = [];
74
+
75
+    /**
76
+     * @param \Sabre\DAV\Tree $tree tree
77
+     * @param IUserSession $userSession user session
78
+     * @param \OCP\Files\Folder $userFolder user home folder
79
+     * @param \OCP\Share\IManager $shareManager share manager
80
+     */
81
+    public function __construct(
82
+        \Sabre\DAV\Tree $tree,
83
+        IUserSession $userSession,
84
+        \OCP\Files\Folder $userFolder,
85
+        \OCP\Share\IManager $shareManager
86
+    ) {
87
+        $this->tree = $tree;
88
+        $this->shareManager = $shareManager;
89
+        $this->userFolder = $userFolder;
90
+        $this->userId = $userSession->getUser()->getUID();
91
+    }
92
+
93
+    /**
94
+     * This initializes the plugin.
95
+     *
96
+     * This function is called by \Sabre\DAV\Server, after
97
+     * addPlugin is called.
98
+     *
99
+     * This method should set up the required event subscriptions.
100
+     *
101
+     * @param \Sabre\DAV\Server $server
102
+     */
103
+    public function initialize(\Sabre\DAV\Server $server) {
104
+        $server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
105
+        $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
106
+        $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
107
+        $server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
108
+
109
+        $this->server = $server;
110
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
111
+    }
112
+
113
+    private function getShare(\OCP\Files\Node $node): array {
114
+        $result = [];
115
+        $requestedShareTypes = [
116
+            IShare::TYPE_USER,
117
+            IShare::TYPE_GROUP,
118
+            IShare::TYPE_LINK,
119
+            IShare::TYPE_REMOTE,
120
+            IShare::TYPE_EMAIL,
121
+            IShare::TYPE_ROOM,
122
+            IShare::TYPE_CIRCLE,
123
+        ];
124
+        foreach ($requestedShareTypes as $requestedShareType) {
125
+            $shares = $this->shareManager->getSharesBy(
126
+                $this->userId,
127
+                $requestedShareType,
128
+                $node,
129
+                false,
130
+                -1
131
+            );
132
+            foreach ($shares as $share) {
133
+                $result[] = $share;
134
+            }
135
+        }
136
+        return $result;
137
+    }
138
+
139
+    private function getSharesFolder(\OCP\Files\Folder $node): array {
140
+        return $this->shareManager->getSharesInFolder(
141
+            $this->userId,
142
+            $node,
143
+            true
144
+        );
145
+    }
146
+
147
+    private function getShares(\Sabre\DAV\INode $sabreNode): array {
148
+        if (isset($this->cachedShares[$sabreNode->getId()])) {
149
+            $shares = $this->cachedShares[$sabreNode->getId()];
150
+        } else {
151
+            list($parentPath,) = \Sabre\Uri\split($sabreNode->getPath());
152
+            if ($parentPath === '') {
153
+                $parentPath = '/';
154
+            }
155
+            // if we already cached the folder this file is in we know there are no shares for this file
156
+            if (array_search($parentPath, $this->cachedFolders) === false) {
157
+                $node = $this->userFolder->get($sabreNode->getPath());
158
+                $shares = $this->getShare($node);
159
+                $this->cachedShares[$sabreNode->getId()] = $shares;
160
+            } else {
161
+                return [];
162
+            }
163
+        }
164
+
165
+        return $shares;
166
+    }
167
+
168
+    /**
169
+     * Adds shares to propfind response
170
+     *
171
+     * @param PropFind $propFind propfind object
172
+     * @param \Sabre\DAV\INode $sabreNode sabre node
173
+     */
174
+    public function handleGetProperties(
175
+        PropFind $propFind,
176
+        \Sabre\DAV\INode $sabreNode
177
+    ) {
178
+        if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
179
+            return;
180
+        }
181
+
182
+        // need prefetch ?
183
+        if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
184
+            && $propFind->getDepth() !== 0
185
+            && (
186
+                !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
187
+                !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
188
+            )
189
+        ) {
190
+            $folderNode = $this->userFolder->get($sabreNode->getPath());
191
+
192
+            $this->cachedFolders[] = $sabreNode->getPath();
193
+            $childShares = $this->getSharesFolder($folderNode);
194
+            foreach ($childShares as $id => $shares) {
195
+                $this->cachedShares[$id] = $shares;
196
+            }
197
+        }
198
+
199
+        $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
200
+            $shares = $this->getShares($sabreNode);
201
+
202
+            $shareTypes = array_unique(array_map(function (IShare $share) {
203
+                return $share->getShareType();
204
+            }, $shares));
205
+
206
+            return new ShareTypeList($shareTypes);
207
+        });
208
+
209
+        $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
210
+            $shares = $this->getShares($sabreNode);
211
+
212
+            return new ShareeList($shares);
213
+        });
214
+    }
215 215
 }
Please login to merge, or discard this patch.
apps/sharebymail/lib/ShareByMailProvider.php 1 patch
Indentation   +1130 added lines, -1130 removed lines patch added patch discarded remove patch
@@ -69,1141 +69,1141 @@
 block discarded – undo
69 69
  */
70 70
 class ShareByMailProvider implements IShareProvider {
71 71
 
72
-	/** @var  IDBConnection */
73
-	private $dbConnection;
74
-
75
-	/** @var ILogger */
76
-	private $logger;
77
-
78
-	/** @var ISecureRandom */
79
-	private $secureRandom;
80
-
81
-	/** @var IUserManager */
82
-	private $userManager;
83
-
84
-	/** @var IRootFolder */
85
-	private $rootFolder;
86
-
87
-	/** @var IL10N */
88
-	private $l;
89
-
90
-	/** @var IMailer */
91
-	private $mailer;
92
-
93
-	/** @var IURLGenerator */
94
-	private $urlGenerator;
95
-
96
-	/** @var IManager  */
97
-	private $activityManager;
98
-
99
-	/** @var SettingsManager */
100
-	private $settingsManager;
101
-
102
-	/** @var Defaults */
103
-	private $defaults;
104
-
105
-	/** @var IHasher */
106
-	private $hasher;
107
-
108
-	/** @var  CapabilitiesManager */
109
-	private $capabilitiesManager;
110
-
111
-	/**
112
-	 * Return the identifier of this provider.
113
-	 *
114
-	 * @return string Containing only [a-zA-Z0-9]
115
-	 */
116
-	public function identifier() {
117
-		return 'ocMailShare';
118
-	}
119
-
120
-	/**
121
-	 * DefaultShareProvider constructor.
122
-	 *
123
-	 * @param IDBConnection $connection
124
-	 * @param ISecureRandom $secureRandom
125
-	 * @param IUserManager $userManager
126
-	 * @param IRootFolder $rootFolder
127
-	 * @param IL10N $l
128
-	 * @param ILogger $logger
129
-	 * @param IMailer $mailer
130
-	 * @param IURLGenerator $urlGenerator
131
-	 * @param IManager $activityManager
132
-	 * @param SettingsManager $settingsManager
133
-	 * @param Defaults $defaults
134
-	 * @param IHasher $hasher
135
-	 * @param CapabilitiesManager $capabilitiesManager
136
-	 */
137
-	public function __construct(
138
-		IDBConnection $connection,
139
-		ISecureRandom $secureRandom,
140
-		IUserManager $userManager,
141
-		IRootFolder $rootFolder,
142
-		IL10N $l,
143
-		ILogger $logger,
144
-		IMailer $mailer,
145
-		IURLGenerator $urlGenerator,
146
-		IManager $activityManager,
147
-		SettingsManager $settingsManager,
148
-		Defaults $defaults,
149
-		IHasher $hasher,
150
-		CapabilitiesManager $capabilitiesManager
151
-	) {
152
-		$this->dbConnection = $connection;
153
-		$this->secureRandom = $secureRandom;
154
-		$this->userManager = $userManager;
155
-		$this->rootFolder = $rootFolder;
156
-		$this->l = $l;
157
-		$this->logger = $logger;
158
-		$this->mailer = $mailer;
159
-		$this->urlGenerator = $urlGenerator;
160
-		$this->activityManager = $activityManager;
161
-		$this->settingsManager = $settingsManager;
162
-		$this->defaults = $defaults;
163
-		$this->hasher = $hasher;
164
-		$this->capabilitiesManager = $capabilitiesManager;
165
-	}
166
-
167
-	/**
168
-	 * Share a path
169
-	 *
170
-	 * @param IShare $share
171
-	 * @return IShare The share object
172
-	 * @throws ShareNotFound
173
-	 * @throws \Exception
174
-	 */
175
-	public function create(IShare $share) {
176
-		$shareWith = $share->getSharedWith();
177
-		/*
72
+    /** @var  IDBConnection */
73
+    private $dbConnection;
74
+
75
+    /** @var ILogger */
76
+    private $logger;
77
+
78
+    /** @var ISecureRandom */
79
+    private $secureRandom;
80
+
81
+    /** @var IUserManager */
82
+    private $userManager;
83
+
84
+    /** @var IRootFolder */
85
+    private $rootFolder;
86
+
87
+    /** @var IL10N */
88
+    private $l;
89
+
90
+    /** @var IMailer */
91
+    private $mailer;
92
+
93
+    /** @var IURLGenerator */
94
+    private $urlGenerator;
95
+
96
+    /** @var IManager  */
97
+    private $activityManager;
98
+
99
+    /** @var SettingsManager */
100
+    private $settingsManager;
101
+
102
+    /** @var Defaults */
103
+    private $defaults;
104
+
105
+    /** @var IHasher */
106
+    private $hasher;
107
+
108
+    /** @var  CapabilitiesManager */
109
+    private $capabilitiesManager;
110
+
111
+    /**
112
+     * Return the identifier of this provider.
113
+     *
114
+     * @return string Containing only [a-zA-Z0-9]
115
+     */
116
+    public function identifier() {
117
+        return 'ocMailShare';
118
+    }
119
+
120
+    /**
121
+     * DefaultShareProvider constructor.
122
+     *
123
+     * @param IDBConnection $connection
124
+     * @param ISecureRandom $secureRandom
125
+     * @param IUserManager $userManager
126
+     * @param IRootFolder $rootFolder
127
+     * @param IL10N $l
128
+     * @param ILogger $logger
129
+     * @param IMailer $mailer
130
+     * @param IURLGenerator $urlGenerator
131
+     * @param IManager $activityManager
132
+     * @param SettingsManager $settingsManager
133
+     * @param Defaults $defaults
134
+     * @param IHasher $hasher
135
+     * @param CapabilitiesManager $capabilitiesManager
136
+     */
137
+    public function __construct(
138
+        IDBConnection $connection,
139
+        ISecureRandom $secureRandom,
140
+        IUserManager $userManager,
141
+        IRootFolder $rootFolder,
142
+        IL10N $l,
143
+        ILogger $logger,
144
+        IMailer $mailer,
145
+        IURLGenerator $urlGenerator,
146
+        IManager $activityManager,
147
+        SettingsManager $settingsManager,
148
+        Defaults $defaults,
149
+        IHasher $hasher,
150
+        CapabilitiesManager $capabilitiesManager
151
+    ) {
152
+        $this->dbConnection = $connection;
153
+        $this->secureRandom = $secureRandom;
154
+        $this->userManager = $userManager;
155
+        $this->rootFolder = $rootFolder;
156
+        $this->l = $l;
157
+        $this->logger = $logger;
158
+        $this->mailer = $mailer;
159
+        $this->urlGenerator = $urlGenerator;
160
+        $this->activityManager = $activityManager;
161
+        $this->settingsManager = $settingsManager;
162
+        $this->defaults = $defaults;
163
+        $this->hasher = $hasher;
164
+        $this->capabilitiesManager = $capabilitiesManager;
165
+    }
166
+
167
+    /**
168
+     * Share a path
169
+     *
170
+     * @param IShare $share
171
+     * @return IShare The share object
172
+     * @throws ShareNotFound
173
+     * @throws \Exception
174
+     */
175
+    public function create(IShare $share) {
176
+        $shareWith = $share->getSharedWith();
177
+        /*
178 178
 		 * Check if file is not already shared with the remote user
179 179
 		 */
180
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
181
-		if (!empty($alreadyShared)) {
182
-			$message = 'Sharing %1$s failed, this item is already shared with %2$s';
183
-			$message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
184
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
185
-			throw new \Exception($message_t);
186
-		}
187
-
188
-		// if the admin enforces a password for all mail shares we create a
189
-		// random password and send it to the recipient
190
-		$password = $share->getPassword() ?: '';
191
-		$passwordEnforced = $this->settingsManager->enforcePasswordProtection();
192
-		if ($passwordEnforced && empty($password)) {
193
-			$password = $this->autoGeneratePassword($share);
194
-		}
195
-
196
-		if (!empty($password)) {
197
-			$share->setPassword($this->hasher->hash($password));
198
-		}
199
-
200
-		$shareId = $this->createMailShare($share);
201
-		$send = $this->sendPassword($share, $password);
202
-		if ($passwordEnforced && $send === false) {
203
-			$this->sendPasswordToOwner($share, $password);
204
-		}
205
-
206
-		$this->createShareActivity($share);
207
-		$data = $this->getRawShare($shareId);
208
-
209
-		return $this->createShareObject($data);
210
-	}
211
-
212
-	/**
213
-	 * auto generate password in case of password enforcement on mail shares
214
-	 *
215
-	 * @param IShare $share
216
-	 * @return string
217
-	 * @throws \Exception
218
-	 */
219
-	protected function autoGeneratePassword($share) {
220
-		$initiatorUser = $this->userManager->get($share->getSharedBy());
221
-		$initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
222
-		$allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
223
-
224
-		if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
225
-			throw new \Exception(
226
-				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
227
-			);
228
-		}
229
-
230
-		$passwordPolicy = $this->getPasswordPolicy();
231
-		$passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
232
-		$passwordLength = 8;
233
-		if (!empty($passwordPolicy)) {
234
-			$passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
235
-			$passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
236
-		}
237
-
238
-		$password = $this->secureRandom->generate($passwordLength, $passwordCharset);
239
-
240
-		return $password;
241
-	}
242
-
243
-	/**
244
-	 * get password policy
245
-	 *
246
-	 * @return array
247
-	 */
248
-	protected function getPasswordPolicy() {
249
-		$capabilities = $this->capabilitiesManager->getCapabilities();
250
-		if (isset($capabilities['password_policy'])) {
251
-			return $capabilities['password_policy'];
252
-		}
253
-
254
-		return [];
255
-	}
256
-
257
-	/**
258
-	 * create activity if a file/folder was shared by mail
259
-	 *
260
-	 * @param IShare $share
261
-	 * @param string $type
262
-	 */
263
-	protected function createShareActivity(IShare $share, string $type = 'share') {
264
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
265
-
266
-		$this->publishActivity(
267
-			$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
268
-			[$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
269
-			$share->getSharedBy(),
270
-			$share->getNode()->getId(),
271
-			(string) $userFolder->getRelativePath($share->getNode()->getPath())
272
-		);
273
-
274
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
275
-			$ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
-			$fileId = $share->getNode()->getId();
277
-			$nodes = $ownerFolder->getById($fileId);
278
-			$ownerPath = $nodes[0]->getPath();
279
-			$this->publishActivity(
280
-				$type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
281
-				[$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
282
-				$share->getShareOwner(),
283
-				$fileId,
284
-				(string) $ownerFolder->getRelativePath($ownerPath)
285
-			);
286
-		}
287
-	}
288
-
289
-	/**
290
-	 * create activity if a file/folder was shared by mail
291
-	 *
292
-	 * @param IShare $share
293
-	 * @param string $sharedWith
294
-	 * @param bool $sendToSelf
295
-	 */
296
-	protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
297
-		$userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
298
-
299
-		if ($sendToSelf) {
300
-			$this->publishActivity(
301
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
302
-				[$userFolder->getRelativePath($share->getNode()->getPath())],
303
-				$share->getSharedBy(),
304
-				$share->getNode()->getId(),
305
-				(string) $userFolder->getRelativePath($share->getNode()->getPath())
306
-			);
307
-		} else {
308
-			$this->publishActivity(
309
-				Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
310
-				[$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
311
-				$share->getSharedBy(),
312
-				$share->getNode()->getId(),
313
-				(string) $userFolder->getRelativePath($share->getNode()->getPath())
314
-			);
315
-		}
316
-	}
317
-
318
-
319
-	/**
320
-	 * publish activity if a file/folder was shared by mail
321
-	 *
322
-	 * @param string $subject
323
-	 * @param array $parameters
324
-	 * @param string $affectedUser
325
-	 * @param int $fileId
326
-	 * @param string $filePath
327
-	 */
328
-	protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath) {
329
-		$event = $this->activityManager->generateEvent();
330
-		$event->setApp('sharebymail')
331
-			->setType('shared')
332
-			->setSubject($subject, $parameters)
333
-			->setAffectedUser($affectedUser)
334
-			->setObject('files', $fileId, $filePath);
335
-		$this->activityManager->publish($event);
336
-	}
337
-
338
-	/**
339
-	 * @param IShare $share
340
-	 * @return int
341
-	 * @throws \Exception
342
-	 */
343
-	protected function createMailShare(IShare $share) {
344
-		$share->setToken($this->generateToken());
345
-		$shareId = $this->addShareToDB(
346
-			$share->getNodeId(),
347
-			$share->getNodeType(),
348
-			$share->getSharedWith(),
349
-			$share->getSharedBy(),
350
-			$share->getShareOwner(),
351
-			$share->getPermissions(),
352
-			$share->getToken(),
353
-			$share->getPassword(),
354
-			$share->getSendPasswordByTalk(),
355
-			$share->getHideDownload()
356
-		);
357
-
358
-		try {
359
-			$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
360
-				['token' => $share->getToken()]);
361
-			$this->sendMailNotification(
362
-				$share->getNode()->getName(),
363
-				$link,
364
-				$share->getSharedBy(),
365
-				$share->getSharedWith(),
366
-				$share->getExpirationDate()
367
-			);
368
-		} catch (HintException $hintException) {
369
-			$this->logger->logException($hintException, [
370
-				'message' => 'Failed to send share by mail.',
371
-				'level' => ILogger::ERROR,
372
-				'app' => 'sharebymail',
373
-			]);
374
-			$this->removeShareFromTable($shareId);
375
-			throw $hintException;
376
-		} catch (\Exception $e) {
377
-			$this->logger->logException($e, [
378
-				'message' => 'Failed to send share by mail.',
379
-				'level' => ILogger::ERROR,
380
-				'app' => 'sharebymail',
381
-			]);
382
-			$this->removeShareFromTable($shareId);
383
-			throw new HintException('Failed to send share by mail',
384
-				$this->l->t('Failed to send share by email'));
385
-		}
386
-
387
-		return $shareId;
388
-	}
389
-
390
-	/**
391
-	 * @param string $filename
392
-	 * @param string $link
393
-	 * @param string $initiator
394
-	 * @param string $shareWith
395
-	 * @param \DateTime|null $expiration
396
-	 * @throws \Exception If mail couldn't be sent
397
-	 */
398
-	protected function sendMailNotification($filename,
399
-											$link,
400
-											$initiator,
401
-											$shareWith,
402
-											\DateTime $expiration = null) {
403
-		$initiatorUser = $this->userManager->get($initiator);
404
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
405
-		$message = $this->mailer->createMessage();
406
-
407
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
408
-			'filename' => $filename,
409
-			'link' => $link,
410
-			'initiator' => $initiatorDisplayName,
411
-			'expiration' => $expiration,
412
-			'shareWith' => $shareWith,
413
-		]);
414
-
415
-		$emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
416
-		$emailTemplate->addHeader();
417
-		$emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
418
-		$text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
419
-
420
-		$emailTemplate->addBodyText(
421
-			htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
422
-			$text
423
-		);
424
-		$emailTemplate->addBodyButton(
425
-			$this->l->t('Open »%s«', [$filename]),
426
-			$link
427
-		);
428
-
429
-		$message->setTo([$shareWith]);
430
-
431
-		// The "From" contains the sharers name
432
-		$instanceName = $this->defaults->getName();
433
-		$senderName = $this->l->t(
434
-			'%1$s via %2$s',
435
-			[
436
-				$initiatorDisplayName,
437
-				$instanceName
438
-			]
439
-		);
440
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
441
-
442
-		// The "Reply-To" is set to the sharer if an mail address is configured
443
-		// also the default footer contains a "Do not reply" which needs to be adjusted.
444
-		$initiatorEmail = $initiatorUser->getEMailAddress();
445
-		if ($initiatorEmail !== null) {
446
-			$message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
447
-			$emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
448
-		} else {
449
-			$emailTemplate->addFooter();
450
-		}
451
-
452
-		$message->useTemplate($emailTemplate);
453
-		$this->mailer->send($message);
454
-	}
455
-
456
-	/**
457
-	 * send password to recipient of a mail share
458
-	 *
459
-	 * @param IShare $share
460
-	 * @param string $password
461
-	 * @return bool
462
-	 */
463
-	protected function sendPassword(IShare $share, $password) {
464
-		$filename = $share->getNode()->getName();
465
-		$initiator = $share->getSharedBy();
466
-		$shareWith = $share->getSharedWith();
467
-
468
-		if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
469
-			return false;
470
-		}
471
-
472
-		$initiatorUser = $this->userManager->get($initiator);
473
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
474
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
475
-
476
-		$plainBodyPart = $this->l->t("%1\$s shared »%2\$s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
477
-		$htmlBodyPart = $this->l->t('%1$s shared »%2$s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
478
-
479
-		$message = $this->mailer->createMessage();
480
-
481
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
482
-			'filename' => $filename,
483
-			'password' => $password,
484
-			'initiator' => $initiatorDisplayName,
485
-			'initiatorEmail' => $initiatorEmailAddress,
486
-			'shareWith' => $shareWith,
487
-		]);
488
-
489
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
490
-		$emailTemplate->addHeader();
491
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
492
-		$emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
493
-		$emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
494
-		$emailTemplate->addBodyText($password);
495
-
496
-		// The "From" contains the sharers name
497
-		$instanceName = $this->defaults->getName();
498
-		$senderName = $this->l->t(
499
-			'%1$s via %2$s',
500
-			[
501
-				$initiatorDisplayName,
502
-				$instanceName
503
-			]
504
-		);
505
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
506
-		if ($initiatorEmailAddress !== null) {
507
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
508
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
509
-		} else {
510
-			$emailTemplate->addFooter();
511
-		}
512
-
513
-		$message->setTo([$shareWith]);
514
-		$message->useTemplate($emailTemplate);
515
-		$this->mailer->send($message);
516
-
517
-		$this->createPasswordSendActivity($share, $shareWith, false);
518
-
519
-		return true;
520
-	}
521
-
522
-	protected function sendNote(IShare $share) {
523
-		$recipient = $share->getSharedWith();
524
-
525
-
526
-		$filename = $share->getNode()->getName();
527
-		$initiator = $share->getSharedBy();
528
-		$note = $share->getNote();
529
-
530
-		$initiatorUser = $this->userManager->get($initiator);
531
-		$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
532
-		$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
533
-
534
-		$plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
535
-		$htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
536
-
537
-		$message = $this->mailer->createMessage();
538
-
539
-		$emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
540
-
541
-		$emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
542
-		$emailTemplate->addHeader();
543
-		$emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
544
-		$emailTemplate->addBodyText(htmlspecialchars($note), $note);
545
-
546
-		$link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
547
-			['token' => $share->getToken()]);
548
-		$emailTemplate->addBodyButton(
549
-			$this->l->t('Open »%s«', [$filename]),
550
-			$link
551
-		);
552
-
553
-		// The "From" contains the sharers name
554
-		$instanceName = $this->defaults->getName();
555
-		$senderName = $this->l->t(
556
-			'%1$s via %2$s',
557
-			[
558
-				$initiatorDisplayName,
559
-				$instanceName
560
-			]
561
-		);
562
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
563
-		if ($initiatorEmailAddress !== null) {
564
-			$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
565
-			$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
566
-		} else {
567
-			$emailTemplate->addFooter();
568
-		}
569
-
570
-		$message->setTo([$recipient]);
571
-		$message->useTemplate($emailTemplate);
572
-		$this->mailer->send($message);
573
-	}
574
-
575
-	/**
576
-	 * send auto generated password to the owner. This happens if the admin enforces
577
-	 * a password for mail shares and forbid to send the password by mail to the recipient
578
-	 *
579
-	 * @param IShare $share
580
-	 * @param string $password
581
-	 * @return bool
582
-	 * @throws \Exception
583
-	 */
584
-	protected function sendPasswordToOwner(IShare $share, $password) {
585
-		$filename = $share->getNode()->getName();
586
-		$initiator = $this->userManager->get($share->getSharedBy());
587
-		$initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
588
-		$initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
589
-		$shareWith = $share->getSharedWith();
590
-
591
-		if ($initiatorEMailAddress === null) {
592
-			throw new \Exception(
593
-				$this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
594
-			);
595
-		}
596
-
597
-		$bodyPart = $this->l->t('You just shared »%1$s« with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
598
-
599
-		$message = $this->mailer->createMessage();
600
-		$emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
601
-			'filename' => $filename,
602
-			'password' => $password,
603
-			'initiator' => $initiatorDisplayName,
604
-			'initiatorEmail' => $initiatorEMailAddress,
605
-			'shareWith' => $shareWith,
606
-		]);
607
-
608
-		$emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared by you with %2$s', [$filename, $shareWith]));
609
-		$emailTemplate->addHeader();
610
-		$emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
611
-		$emailTemplate->addBodyText($bodyPart);
612
-		$emailTemplate->addBodyText($this->l->t('This is the password:'));
613
-		$emailTemplate->addBodyText($password);
614
-		$emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
615
-		$emailTemplate->addFooter();
616
-
617
-		$instanceName = $this->defaults->getName();
618
-		$senderName = $this->l->t(
619
-			'%1$s via %2$s',
620
-			[
621
-				$initiatorDisplayName,
622
-				$instanceName
623
-			]
624
-		);
625
-		$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
626
-		$message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
627
-		$message->useTemplate($emailTemplate);
628
-		$this->mailer->send($message);
629
-
630
-		$this->createPasswordSendActivity($share, $shareWith, true);
631
-
632
-		return true;
633
-	}
634
-
635
-	/**
636
-	 * generate share token
637
-	 *
638
-	 * @return string
639
-	 */
640
-	protected function generateToken($size = 15) {
641
-		$token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
642
-		return $token;
643
-	}
644
-
645
-	/**
646
-	 * Get all children of this share
647
-	 *
648
-	 * @param IShare $parent
649
-	 * @return IShare[]
650
-	 */
651
-	public function getChildren(IShare $parent) {
652
-		$children = [];
653
-
654
-		$qb = $this->dbConnection->getQueryBuilder();
655
-		$qb->select('*')
656
-			->from('share')
657
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
658
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
659
-			->orderBy('id');
660
-
661
-		$cursor = $qb->execute();
662
-		while ($data = $cursor->fetch()) {
663
-			$children[] = $this->createShareObject($data);
664
-		}
665
-		$cursor->closeCursor();
666
-
667
-		return $children;
668
-	}
669
-
670
-	/**
671
-	 * add share to the database and return the ID
672
-	 *
673
-	 * @param int $itemSource
674
-	 * @param string $itemType
675
-	 * @param string $shareWith
676
-	 * @param string $sharedBy
677
-	 * @param string $uidOwner
678
-	 * @param int $permissions
679
-	 * @param string $token
680
-	 * @param string $password
681
-	 * @param bool $sendPasswordByTalk
682
-	 * @param bool $hideDownload
683
-	 * @return int
684
-	 */
685
-	protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload) {
686
-		$qb = $this->dbConnection->getQueryBuilder();
687
-		$qb->insert('share')
688
-			->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
689
-			->setValue('item_type', $qb->createNamedParameter($itemType))
690
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
691
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
692
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
693
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
694
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
695
-			->setValue('permissions', $qb->createNamedParameter($permissions))
696
-			->setValue('token', $qb->createNamedParameter($token))
697
-			->setValue('password', $qb->createNamedParameter($password))
698
-			->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
699
-			->setValue('stime', $qb->createNamedParameter(time()))
700
-			->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT));
701
-
702
-		/*
180
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_EMAIL, $share->getNode(), 1, 0);
181
+        if (!empty($alreadyShared)) {
182
+            $message = 'Sharing %1$s failed, this item is already shared with %2$s';
183
+            $message_t = $this->l->t('Sharing %1$s failed, this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
184
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
185
+            throw new \Exception($message_t);
186
+        }
187
+
188
+        // if the admin enforces a password for all mail shares we create a
189
+        // random password and send it to the recipient
190
+        $password = $share->getPassword() ?: '';
191
+        $passwordEnforced = $this->settingsManager->enforcePasswordProtection();
192
+        if ($passwordEnforced && empty($password)) {
193
+            $password = $this->autoGeneratePassword($share);
194
+        }
195
+
196
+        if (!empty($password)) {
197
+            $share->setPassword($this->hasher->hash($password));
198
+        }
199
+
200
+        $shareId = $this->createMailShare($share);
201
+        $send = $this->sendPassword($share, $password);
202
+        if ($passwordEnforced && $send === false) {
203
+            $this->sendPasswordToOwner($share, $password);
204
+        }
205
+
206
+        $this->createShareActivity($share);
207
+        $data = $this->getRawShare($shareId);
208
+
209
+        return $this->createShareObject($data);
210
+    }
211
+
212
+    /**
213
+     * auto generate password in case of password enforcement on mail shares
214
+     *
215
+     * @param IShare $share
216
+     * @return string
217
+     * @throws \Exception
218
+     */
219
+    protected function autoGeneratePassword($share) {
220
+        $initiatorUser = $this->userManager->get($share->getSharedBy());
221
+        $initiatorEMailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
222
+        $allowPasswordByMail = $this->settingsManager->sendPasswordByMail();
223
+
224
+        if ($initiatorEMailAddress === null && !$allowPasswordByMail) {
225
+            throw new \Exception(
226
+                $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
227
+            );
228
+        }
229
+
230
+        $passwordPolicy = $this->getPasswordPolicy();
231
+        $passwordCharset = ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_DIGITS;
232
+        $passwordLength = 8;
233
+        if (!empty($passwordPolicy)) {
234
+            $passwordLength = (int)$passwordPolicy['minLength'] > 0 ? (int)$passwordPolicy['minLength'] : $passwordLength;
235
+            $passwordCharset .= $passwordPolicy['enforceSpecialCharacters'] ? ISecureRandom::CHAR_SYMBOLS : '';
236
+        }
237
+
238
+        $password = $this->secureRandom->generate($passwordLength, $passwordCharset);
239
+
240
+        return $password;
241
+    }
242
+
243
+    /**
244
+     * get password policy
245
+     *
246
+     * @return array
247
+     */
248
+    protected function getPasswordPolicy() {
249
+        $capabilities = $this->capabilitiesManager->getCapabilities();
250
+        if (isset($capabilities['password_policy'])) {
251
+            return $capabilities['password_policy'];
252
+        }
253
+
254
+        return [];
255
+    }
256
+
257
+    /**
258
+     * create activity if a file/folder was shared by mail
259
+     *
260
+     * @param IShare $share
261
+     * @param string $type
262
+     */
263
+    protected function createShareActivity(IShare $share, string $type = 'share') {
264
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
265
+
266
+        $this->publishActivity(
267
+            $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_SELF : Activity::SUBJECT_UNSHARED_EMAIL_SELF,
268
+            [$userFolder->getRelativePath($share->getNode()->getPath()), $share->getSharedWith()],
269
+            $share->getSharedBy(),
270
+            $share->getNode()->getId(),
271
+            (string) $userFolder->getRelativePath($share->getNode()->getPath())
272
+        );
273
+
274
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
275
+            $ownerFolder = $this->rootFolder->getUserFolder($share->getShareOwner());
276
+            $fileId = $share->getNode()->getId();
277
+            $nodes = $ownerFolder->getById($fileId);
278
+            $ownerPath = $nodes[0]->getPath();
279
+            $this->publishActivity(
280
+                $type === 'share' ? Activity::SUBJECT_SHARED_EMAIL_BY : Activity::SUBJECT_UNSHARED_EMAIL_BY,
281
+                [$ownerFolder->getRelativePath($ownerPath), $share->getSharedWith(), $share->getSharedBy()],
282
+                $share->getShareOwner(),
283
+                $fileId,
284
+                (string) $ownerFolder->getRelativePath($ownerPath)
285
+            );
286
+        }
287
+    }
288
+
289
+    /**
290
+     * create activity if a file/folder was shared by mail
291
+     *
292
+     * @param IShare $share
293
+     * @param string $sharedWith
294
+     * @param bool $sendToSelf
295
+     */
296
+    protected function createPasswordSendActivity(IShare $share, $sharedWith, $sendToSelf) {
297
+        $userFolder = $this->rootFolder->getUserFolder($share->getSharedBy());
298
+
299
+        if ($sendToSelf) {
300
+            $this->publishActivity(
301
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND_SELF,
302
+                [$userFolder->getRelativePath($share->getNode()->getPath())],
303
+                $share->getSharedBy(),
304
+                $share->getNode()->getId(),
305
+                (string) $userFolder->getRelativePath($share->getNode()->getPath())
306
+            );
307
+        } else {
308
+            $this->publishActivity(
309
+                Activity::SUBJECT_SHARED_EMAIL_PASSWORD_SEND,
310
+                [$userFolder->getRelativePath($share->getNode()->getPath()), $sharedWith],
311
+                $share->getSharedBy(),
312
+                $share->getNode()->getId(),
313
+                (string) $userFolder->getRelativePath($share->getNode()->getPath())
314
+            );
315
+        }
316
+    }
317
+
318
+
319
+    /**
320
+     * publish activity if a file/folder was shared by mail
321
+     *
322
+     * @param string $subject
323
+     * @param array $parameters
324
+     * @param string $affectedUser
325
+     * @param int $fileId
326
+     * @param string $filePath
327
+     */
328
+    protected function publishActivity(string $subject, array $parameters, string $affectedUser, int $fileId, string $filePath) {
329
+        $event = $this->activityManager->generateEvent();
330
+        $event->setApp('sharebymail')
331
+            ->setType('shared')
332
+            ->setSubject($subject, $parameters)
333
+            ->setAffectedUser($affectedUser)
334
+            ->setObject('files', $fileId, $filePath);
335
+        $this->activityManager->publish($event);
336
+    }
337
+
338
+    /**
339
+     * @param IShare $share
340
+     * @return int
341
+     * @throws \Exception
342
+     */
343
+    protected function createMailShare(IShare $share) {
344
+        $share->setToken($this->generateToken());
345
+        $shareId = $this->addShareToDB(
346
+            $share->getNodeId(),
347
+            $share->getNodeType(),
348
+            $share->getSharedWith(),
349
+            $share->getSharedBy(),
350
+            $share->getShareOwner(),
351
+            $share->getPermissions(),
352
+            $share->getToken(),
353
+            $share->getPassword(),
354
+            $share->getSendPasswordByTalk(),
355
+            $share->getHideDownload()
356
+        );
357
+
358
+        try {
359
+            $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
360
+                ['token' => $share->getToken()]);
361
+            $this->sendMailNotification(
362
+                $share->getNode()->getName(),
363
+                $link,
364
+                $share->getSharedBy(),
365
+                $share->getSharedWith(),
366
+                $share->getExpirationDate()
367
+            );
368
+        } catch (HintException $hintException) {
369
+            $this->logger->logException($hintException, [
370
+                'message' => 'Failed to send share by mail.',
371
+                'level' => ILogger::ERROR,
372
+                'app' => 'sharebymail',
373
+            ]);
374
+            $this->removeShareFromTable($shareId);
375
+            throw $hintException;
376
+        } catch (\Exception $e) {
377
+            $this->logger->logException($e, [
378
+                'message' => 'Failed to send share by mail.',
379
+                'level' => ILogger::ERROR,
380
+                'app' => 'sharebymail',
381
+            ]);
382
+            $this->removeShareFromTable($shareId);
383
+            throw new HintException('Failed to send share by mail',
384
+                $this->l->t('Failed to send share by email'));
385
+        }
386
+
387
+        return $shareId;
388
+    }
389
+
390
+    /**
391
+     * @param string $filename
392
+     * @param string $link
393
+     * @param string $initiator
394
+     * @param string $shareWith
395
+     * @param \DateTime|null $expiration
396
+     * @throws \Exception If mail couldn't be sent
397
+     */
398
+    protected function sendMailNotification($filename,
399
+                                            $link,
400
+                                            $initiator,
401
+                                            $shareWith,
402
+                                            \DateTime $expiration = null) {
403
+        $initiatorUser = $this->userManager->get($initiator);
404
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
405
+        $message = $this->mailer->createMessage();
406
+
407
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientNotification', [
408
+            'filename' => $filename,
409
+            'link' => $link,
410
+            'initiator' => $initiatorDisplayName,
411
+            'expiration' => $expiration,
412
+            'shareWith' => $shareWith,
413
+        ]);
414
+
415
+        $emailTemplate->setSubject($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]));
416
+        $emailTemplate->addHeader();
417
+        $emailTemplate->addHeading($this->l->t('%1$s shared »%2$s« with you', [$initiatorDisplayName, $filename]), false);
418
+        $text = $this->l->t('%1$s shared »%2$s« with you.', [$initiatorDisplayName, $filename]);
419
+
420
+        $emailTemplate->addBodyText(
421
+            htmlspecialchars($text . ' ' . $this->l->t('Click the button below to open it.')),
422
+            $text
423
+        );
424
+        $emailTemplate->addBodyButton(
425
+            $this->l->t('Open »%s«', [$filename]),
426
+            $link
427
+        );
428
+
429
+        $message->setTo([$shareWith]);
430
+
431
+        // The "From" contains the sharers name
432
+        $instanceName = $this->defaults->getName();
433
+        $senderName = $this->l->t(
434
+            '%1$s via %2$s',
435
+            [
436
+                $initiatorDisplayName,
437
+                $instanceName
438
+            ]
439
+        );
440
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
441
+
442
+        // The "Reply-To" is set to the sharer if an mail address is configured
443
+        // also the default footer contains a "Do not reply" which needs to be adjusted.
444
+        $initiatorEmail = $initiatorUser->getEMailAddress();
445
+        if ($initiatorEmail !== null) {
446
+            $message->setReplyTo([$initiatorEmail => $initiatorDisplayName]);
447
+            $emailTemplate->addFooter($instanceName . ($this->defaults->getSlogan() !== '' ? ' - ' . $this->defaults->getSlogan() : ''));
448
+        } else {
449
+            $emailTemplate->addFooter();
450
+        }
451
+
452
+        $message->useTemplate($emailTemplate);
453
+        $this->mailer->send($message);
454
+    }
455
+
456
+    /**
457
+     * send password to recipient of a mail share
458
+     *
459
+     * @param IShare $share
460
+     * @param string $password
461
+     * @return bool
462
+     */
463
+    protected function sendPassword(IShare $share, $password) {
464
+        $filename = $share->getNode()->getName();
465
+        $initiator = $share->getSharedBy();
466
+        $shareWith = $share->getSharedWith();
467
+
468
+        if ($password === '' || $this->settingsManager->sendPasswordByMail() === false || $share->getSendPasswordByTalk()) {
469
+            return false;
470
+        }
471
+
472
+        $initiatorUser = $this->userManager->get($initiator);
473
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
474
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
475
+
476
+        $plainBodyPart = $this->l->t("%1\$s shared »%2\$s« with you.\nYou should have already received a separate mail with a link to access it.\n", [$initiatorDisplayName, $filename]);
477
+        $htmlBodyPart = $this->l->t('%1$s shared »%2$s« with you. You should have already received a separate mail with a link to access it.', [$initiatorDisplayName, $filename]);
478
+
479
+        $message = $this->mailer->createMessage();
480
+
481
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.RecipientPasswordNotification', [
482
+            'filename' => $filename,
483
+            'password' => $password,
484
+            'initiator' => $initiatorDisplayName,
485
+            'initiatorEmail' => $initiatorEmailAddress,
486
+            'shareWith' => $shareWith,
487
+        ]);
488
+
489
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared to you by %2$s', [$filename, $initiatorDisplayName]));
490
+        $emailTemplate->addHeader();
491
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
492
+        $emailTemplate->addBodyText(htmlspecialchars($htmlBodyPart), $plainBodyPart);
493
+        $emailTemplate->addBodyText($this->l->t('It is protected with the following password:'));
494
+        $emailTemplate->addBodyText($password);
495
+
496
+        // The "From" contains the sharers name
497
+        $instanceName = $this->defaults->getName();
498
+        $senderName = $this->l->t(
499
+            '%1$s via %2$s',
500
+            [
501
+                $initiatorDisplayName,
502
+                $instanceName
503
+            ]
504
+        );
505
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
506
+        if ($initiatorEmailAddress !== null) {
507
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
508
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
509
+        } else {
510
+            $emailTemplate->addFooter();
511
+        }
512
+
513
+        $message->setTo([$shareWith]);
514
+        $message->useTemplate($emailTemplate);
515
+        $this->mailer->send($message);
516
+
517
+        $this->createPasswordSendActivity($share, $shareWith, false);
518
+
519
+        return true;
520
+    }
521
+
522
+    protected function sendNote(IShare $share) {
523
+        $recipient = $share->getSharedWith();
524
+
525
+
526
+        $filename = $share->getNode()->getName();
527
+        $initiator = $share->getSharedBy();
528
+        $note = $share->getNote();
529
+
530
+        $initiatorUser = $this->userManager->get($initiator);
531
+        $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
532
+        $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
533
+
534
+        $plainHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
535
+        $htmlHeading = $this->l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
536
+
537
+        $message = $this->mailer->createMessage();
538
+
539
+        $emailTemplate = $this->mailer->createEMailTemplate('shareByMail.sendNote');
540
+
541
+        $emailTemplate->setSubject($this->l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
542
+        $emailTemplate->addHeader();
543
+        $emailTemplate->addHeading(htmlspecialchars($htmlHeading), $plainHeading);
544
+        $emailTemplate->addBodyText(htmlspecialchars($note), $note);
545
+
546
+        $link = $this->urlGenerator->linkToRouteAbsolute('files_sharing.sharecontroller.showShare',
547
+            ['token' => $share->getToken()]);
548
+        $emailTemplate->addBodyButton(
549
+            $this->l->t('Open »%s«', [$filename]),
550
+            $link
551
+        );
552
+
553
+        // The "From" contains the sharers name
554
+        $instanceName = $this->defaults->getName();
555
+        $senderName = $this->l->t(
556
+            '%1$s via %2$s',
557
+            [
558
+                $initiatorDisplayName,
559
+                $instanceName
560
+            ]
561
+        );
562
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
563
+        if ($initiatorEmailAddress !== null) {
564
+            $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
565
+            $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
566
+        } else {
567
+            $emailTemplate->addFooter();
568
+        }
569
+
570
+        $message->setTo([$recipient]);
571
+        $message->useTemplate($emailTemplate);
572
+        $this->mailer->send($message);
573
+    }
574
+
575
+    /**
576
+     * send auto generated password to the owner. This happens if the admin enforces
577
+     * a password for mail shares and forbid to send the password by mail to the recipient
578
+     *
579
+     * @param IShare $share
580
+     * @param string $password
581
+     * @return bool
582
+     * @throws \Exception
583
+     */
584
+    protected function sendPasswordToOwner(IShare $share, $password) {
585
+        $filename = $share->getNode()->getName();
586
+        $initiator = $this->userManager->get($share->getSharedBy());
587
+        $initiatorEMailAddress = ($initiator instanceof IUser) ? $initiator->getEMailAddress() : null;
588
+        $initiatorDisplayName = ($initiator instanceof IUser) ? $initiator->getDisplayName() : $share->getSharedBy();
589
+        $shareWith = $share->getSharedWith();
590
+
591
+        if ($initiatorEMailAddress === null) {
592
+            throw new \Exception(
593
+                $this->l->t("We can't send you the auto-generated password. Please set a valid email address in your personal settings and try again.")
594
+            );
595
+        }
596
+
597
+        $bodyPart = $this->l->t('You just shared »%1$s« with %2$s. The share was already sent to the recipient. Due to the security policies defined by the administrator of %3$s each share needs to be protected by password and it is not allowed to send the password directly to the recipient. Therefore you need to forward the password manually to the recipient.', [$filename, $shareWith, $this->defaults->getName()]);
598
+
599
+        $message = $this->mailer->createMessage();
600
+        $emailTemplate = $this->mailer->createEMailTemplate('sharebymail.OwnerPasswordNotification', [
601
+            'filename' => $filename,
602
+            'password' => $password,
603
+            'initiator' => $initiatorDisplayName,
604
+            'initiatorEmail' => $initiatorEMailAddress,
605
+            'shareWith' => $shareWith,
606
+        ]);
607
+
608
+        $emailTemplate->setSubject($this->l->t('Password to access »%1$s« shared by you with %2$s', [$filename, $shareWith]));
609
+        $emailTemplate->addHeader();
610
+        $emailTemplate->addHeading($this->l->t('Password to access »%s«', [$filename]), false);
611
+        $emailTemplate->addBodyText($bodyPart);
612
+        $emailTemplate->addBodyText($this->l->t('This is the password:'));
613
+        $emailTemplate->addBodyText($password);
614
+        $emailTemplate->addBodyText($this->l->t('You can choose a different password at any time in the share dialog.'));
615
+        $emailTemplate->addFooter();
616
+
617
+        $instanceName = $this->defaults->getName();
618
+        $senderName = $this->l->t(
619
+            '%1$s via %2$s',
620
+            [
621
+                $initiatorDisplayName,
622
+                $instanceName
623
+            ]
624
+        );
625
+        $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
626
+        $message->setTo([$initiatorEMailAddress => $initiatorDisplayName]);
627
+        $message->useTemplate($emailTemplate);
628
+        $this->mailer->send($message);
629
+
630
+        $this->createPasswordSendActivity($share, $shareWith, true);
631
+
632
+        return true;
633
+    }
634
+
635
+    /**
636
+     * generate share token
637
+     *
638
+     * @return string
639
+     */
640
+    protected function generateToken($size = 15) {
641
+        $token = $this->secureRandom->generate($size, ISecureRandom::CHAR_HUMAN_READABLE);
642
+        return $token;
643
+    }
644
+
645
+    /**
646
+     * Get all children of this share
647
+     *
648
+     * @param IShare $parent
649
+     * @return IShare[]
650
+     */
651
+    public function getChildren(IShare $parent) {
652
+        $children = [];
653
+
654
+        $qb = $this->dbConnection->getQueryBuilder();
655
+        $qb->select('*')
656
+            ->from('share')
657
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
658
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
659
+            ->orderBy('id');
660
+
661
+        $cursor = $qb->execute();
662
+        while ($data = $cursor->fetch()) {
663
+            $children[] = $this->createShareObject($data);
664
+        }
665
+        $cursor->closeCursor();
666
+
667
+        return $children;
668
+    }
669
+
670
+    /**
671
+     * add share to the database and return the ID
672
+     *
673
+     * @param int $itemSource
674
+     * @param string $itemType
675
+     * @param string $shareWith
676
+     * @param string $sharedBy
677
+     * @param string $uidOwner
678
+     * @param int $permissions
679
+     * @param string $token
680
+     * @param string $password
681
+     * @param bool $sendPasswordByTalk
682
+     * @param bool $hideDownload
683
+     * @return int
684
+     */
685
+    protected function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $password, $sendPasswordByTalk, $hideDownload) {
686
+        $qb = $this->dbConnection->getQueryBuilder();
687
+        $qb->insert('share')
688
+            ->setValue('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
689
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
690
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
691
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
692
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
693
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
694
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
695
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
696
+            ->setValue('token', $qb->createNamedParameter($token))
697
+            ->setValue('password', $qb->createNamedParameter($password))
698
+            ->setValue('password_by_talk', $qb->createNamedParameter($sendPasswordByTalk, IQueryBuilder::PARAM_BOOL))
699
+            ->setValue('stime', $qb->createNamedParameter(time()))
700
+            ->setValue('hide_download', $qb->createNamedParameter((int)$hideDownload, IQueryBuilder::PARAM_INT));
701
+
702
+        /*
703 703
 		 * Added to fix https://github.com/owncloud/core/issues/22215
704 704
 		 * Can be removed once we get rid of ajax/share.php
705 705
 		 */
706
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
707
-
708
-		$qb->execute();
709
-		$id = $qb->getLastInsertId();
710
-
711
-		return (int)$id;
712
-	}
713
-
714
-	/**
715
-	 * Update a share
716
-	 *
717
-	 * @param IShare $share
718
-	 * @param string|null $plainTextPassword
719
-	 * @return IShare The share object
720
-	 */
721
-	public function update(IShare $share, $plainTextPassword = null) {
722
-		$originalShare = $this->getShareById($share->getId());
723
-
724
-		// a real password was given
725
-		$validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
726
-
727
-		if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
728
-								($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
729
-			$this->sendPassword($share, $plainTextPassword);
730
-		}
731
-		/*
706
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
707
+
708
+        $qb->execute();
709
+        $id = $qb->getLastInsertId();
710
+
711
+        return (int)$id;
712
+    }
713
+
714
+    /**
715
+     * Update a share
716
+     *
717
+     * @param IShare $share
718
+     * @param string|null $plainTextPassword
719
+     * @return IShare The share object
720
+     */
721
+    public function update(IShare $share, $plainTextPassword = null) {
722
+        $originalShare = $this->getShareById($share->getId());
723
+
724
+        // a real password was given
725
+        $validPassword = $plainTextPassword !== null && $plainTextPassword !== '';
726
+
727
+        if ($validPassword && ($originalShare->getPassword() !== $share->getPassword() ||
728
+                                ($originalShare->getSendPasswordByTalk() && !$share->getSendPasswordByTalk()))) {
729
+            $this->sendPassword($share, $plainTextPassword);
730
+        }
731
+        /*
732 732
 		 * We allow updating the permissions and password of mail shares
733 733
 		 */
734
-		$qb = $this->dbConnection->getQueryBuilder();
735
-		$qb->update('share')
736
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
737
-			->set('permissions', $qb->createNamedParameter($share->getPermissions()))
738
-			->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
739
-			->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
740
-			->set('password', $qb->createNamedParameter($share->getPassword()))
741
-			->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
742
-			->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
743
-			->set('note', $qb->createNamedParameter($share->getNote()))
744
-			->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
745
-			->execute();
746
-
747
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
748
-			$this->sendNote($share);
749
-		}
750
-
751
-		return $share;
752
-	}
753
-
754
-	/**
755
-	 * @inheritdoc
756
-	 */
757
-	public function move(IShare $share, $recipient) {
758
-		/**
759
-		 * nothing to do here, mail shares are only outgoing shares
760
-		 */
761
-		return $share;
762
-	}
763
-
764
-	/**
765
-	 * Delete a share (owner unShares the file)
766
-	 *
767
-	 * @param IShare $share
768
-	 */
769
-	public function delete(IShare $share) {
770
-		try {
771
-			$this->createShareActivity($share, 'unshare');
772
-		} catch (\Exception $e) {
773
-		}
774
-
775
-		$this->removeShareFromTable($share->getId());
776
-	}
777
-
778
-	/**
779
-	 * @inheritdoc
780
-	 */
781
-	public function deleteFromSelf(IShare $share, $recipient) {
782
-		// nothing to do here, mail shares are only outgoing shares
783
-	}
784
-
785
-	public function restore(IShare $share, string $recipient): IShare {
786
-		throw new GenericShareException('not implemented');
787
-	}
788
-
789
-	/**
790
-	 * @inheritdoc
791
-	 */
792
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
793
-		$qb = $this->dbConnection->getQueryBuilder();
794
-		$qb->select('*')
795
-			->from('share');
796
-
797
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
798
-
799
-		/**
800
-		 * Reshares for this user are shares where they are the owner.
801
-		 */
802
-		if ($reshares === false) {
803
-			//Special case for old shares created via the web UI
804
-			$or1 = $qb->expr()->andX(
805
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
806
-				$qb->expr()->isNull('uid_initiator')
807
-			);
808
-
809
-			$qb->andWhere(
810
-				$qb->expr()->orX(
811
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
812
-					$or1
813
-				)
814
-			);
815
-		} else {
816
-			$qb->andWhere(
817
-				$qb->expr()->orX(
818
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
819
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
820
-				)
821
-			);
822
-		}
823
-
824
-		if ($node !== null) {
825
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
826
-		}
827
-
828
-		if ($limit !== -1) {
829
-			$qb->setMaxResults($limit);
830
-		}
831
-
832
-		$qb->setFirstResult($offset);
833
-		$qb->orderBy('id');
834
-
835
-		$cursor = $qb->execute();
836
-		$shares = [];
837
-		while ($data = $cursor->fetch()) {
838
-			$shares[] = $this->createShareObject($data);
839
-		}
840
-		$cursor->closeCursor();
841
-
842
-		return $shares;
843
-	}
844
-
845
-	/**
846
-	 * @inheritdoc
847
-	 */
848
-	public function getShareById($id, $recipientId = null) {
849
-		$qb = $this->dbConnection->getQueryBuilder();
850
-
851
-		$qb->select('*')
852
-			->from('share')
853
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
854
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
855
-
856
-		$cursor = $qb->execute();
857
-		$data = $cursor->fetch();
858
-		$cursor->closeCursor();
859
-
860
-		if ($data === false) {
861
-			throw new ShareNotFound();
862
-		}
863
-
864
-		try {
865
-			$share = $this->createShareObject($data);
866
-		} catch (InvalidShare $e) {
867
-			throw new ShareNotFound();
868
-		}
869
-
870
-		return $share;
871
-	}
872
-
873
-	/**
874
-	 * Get shares for a given path
875
-	 *
876
-	 * @param \OCP\Files\Node $path
877
-	 * @return IShare[]
878
-	 */
879
-	public function getSharesByPath(Node $path) {
880
-		$qb = $this->dbConnection->getQueryBuilder();
881
-
882
-		$cursor = $qb->select('*')
883
-			->from('share')
884
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
885
-			->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
886
-			->execute();
887
-
888
-		$shares = [];
889
-		while ($data = $cursor->fetch()) {
890
-			$shares[] = $this->createShareObject($data);
891
-		}
892
-		$cursor->closeCursor();
893
-
894
-		return $shares;
895
-	}
896
-
897
-	/**
898
-	 * @inheritdoc
899
-	 */
900
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
901
-		/** @var IShare[] $shares */
902
-		$shares = [];
903
-
904
-		//Get shares directly with this user
905
-		$qb = $this->dbConnection->getQueryBuilder();
906
-		$qb->select('*')
907
-			->from('share');
908
-
909
-		// Order by id
910
-		$qb->orderBy('id');
911
-
912
-		// Set limit and offset
913
-		if ($limit !== -1) {
914
-			$qb->setMaxResults($limit);
915
-		}
916
-		$qb->setFirstResult($offset);
917
-
918
-		$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
919
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
920
-
921
-		// Filter by node if provided
922
-		if ($node !== null) {
923
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
924
-		}
925
-
926
-		$cursor = $qb->execute();
927
-
928
-		while ($data = $cursor->fetch()) {
929
-			$shares[] = $this->createShareObject($data);
930
-		}
931
-		$cursor->closeCursor();
932
-
933
-
934
-		return $shares;
935
-	}
936
-
937
-	/**
938
-	 * Get a share by token
939
-	 *
940
-	 * @param string $token
941
-	 * @return IShare
942
-	 * @throws ShareNotFound
943
-	 */
944
-	public function getShareByToken($token) {
945
-		$qb = $this->dbConnection->getQueryBuilder();
946
-
947
-		$cursor = $qb->select('*')
948
-			->from('share')
949
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
950
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
951
-			->execute();
952
-
953
-		$data = $cursor->fetch();
954
-
955
-		if ($data === false) {
956
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
957
-		}
958
-
959
-		try {
960
-			$share = $this->createShareObject($data);
961
-		} catch (InvalidShare $e) {
962
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
963
-		}
964
-
965
-		return $share;
966
-	}
967
-
968
-	/**
969
-	 * remove share from table
970
-	 *
971
-	 * @param string $shareId
972
-	 */
973
-	protected function removeShareFromTable($shareId) {
974
-		$qb = $this->dbConnection->getQueryBuilder();
975
-		$qb->delete('share')
976
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
977
-		$qb->execute();
978
-	}
979
-
980
-	/**
981
-	 * Create a share object from an database row
982
-	 *
983
-	 * @param array $data
984
-	 * @return IShare
985
-	 * @throws InvalidShare
986
-	 * @throws ShareNotFound
987
-	 */
988
-	protected function createShareObject($data) {
989
-		$share = new Share($this->rootFolder, $this->userManager);
990
-		$share->setId((int)$data['id'])
991
-			->setShareType((int)$data['share_type'])
992
-			->setPermissions((int)$data['permissions'])
993
-			->setTarget($data['file_target'])
994
-			->setMailSend((bool)$data['mail_send'])
995
-			->setNote($data['note'])
996
-			->setToken($data['token']);
997
-
998
-		$shareTime = new \DateTime();
999
-		$shareTime->setTimestamp((int)$data['stime']);
1000
-		$share->setShareTime($shareTime);
1001
-		$share->setSharedWith($data['share_with']);
1002
-		$share->setPassword($data['password']);
1003
-		$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1004
-		$share->setHideDownload((bool)$data['hide_download']);
1005
-
1006
-		if ($data['uid_initiator'] !== null) {
1007
-			$share->setShareOwner($data['uid_owner']);
1008
-			$share->setSharedBy($data['uid_initiator']);
1009
-		} else {
1010
-			//OLD SHARE
1011
-			$share->setSharedBy($data['uid_owner']);
1012
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1013
-
1014
-			$owner = $path->getOwner();
1015
-			$share->setShareOwner($owner->getUID());
1016
-		}
1017
-
1018
-		if ($data['expiration'] !== null) {
1019
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1020
-			if ($expiration !== false) {
1021
-				$share->setExpirationDate($expiration);
1022
-			}
1023
-		}
1024
-
1025
-		$share->setNodeId((int)$data['file_source']);
1026
-		$share->setNodeType($data['item_type']);
1027
-
1028
-		$share->setProviderId($this->identifier());
1029
-
1030
-		return $share;
1031
-	}
1032
-
1033
-	/**
1034
-	 * Get the node with file $id for $user
1035
-	 *
1036
-	 * @param string $userId
1037
-	 * @param int $id
1038
-	 * @return \OCP\Files\File|\OCP\Files\Folder
1039
-	 * @throws InvalidShare
1040
-	 */
1041
-	private function getNode($userId, $id) {
1042
-		try {
1043
-			$userFolder = $this->rootFolder->getUserFolder($userId);
1044
-		} catch (NoUserException $e) {
1045
-			throw new InvalidShare();
1046
-		}
1047
-
1048
-		$nodes = $userFolder->getById($id);
1049
-
1050
-		if (empty($nodes)) {
1051
-			throw new InvalidShare();
1052
-		}
1053
-
1054
-		return $nodes[0];
1055
-	}
1056
-
1057
-	/**
1058
-	 * A user is deleted from the system
1059
-	 * So clean up the relevant shares.
1060
-	 *
1061
-	 * @param string $uid
1062
-	 * @param int $shareType
1063
-	 */
1064
-	public function userDeleted($uid, $shareType) {
1065
-		$qb = $this->dbConnection->getQueryBuilder();
1066
-
1067
-		$qb->delete('share')
1068
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1069
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1070
-			->execute();
1071
-	}
1072
-
1073
-	/**
1074
-	 * This provider does not support group shares
1075
-	 *
1076
-	 * @param string $gid
1077
-	 */
1078
-	public function groupDeleted($gid) {
1079
-	}
1080
-
1081
-	/**
1082
-	 * This provider does not support group shares
1083
-	 *
1084
-	 * @param string $uid
1085
-	 * @param string $gid
1086
-	 */
1087
-	public function userDeletedFromGroup($uid, $gid) {
1088
-	}
1089
-
1090
-	/**
1091
-	 * get database row of a give share
1092
-	 *
1093
-	 * @param $id
1094
-	 * @return array
1095
-	 * @throws ShareNotFound
1096
-	 */
1097
-	protected function getRawShare($id) {
1098
-
1099
-		// Now fetch the inserted share and create a complete share object
1100
-		$qb = $this->dbConnection->getQueryBuilder();
1101
-		$qb->select('*')
1102
-			->from('share')
1103
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1104
-
1105
-		$cursor = $qb->execute();
1106
-		$data = $cursor->fetch();
1107
-		$cursor->closeCursor();
1108
-
1109
-		if ($data === false) {
1110
-			throw new ShareNotFound;
1111
-		}
1112
-
1113
-		return $data;
1114
-	}
1115
-
1116
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
1117
-		$qb = $this->dbConnection->getQueryBuilder();
1118
-		$qb->select('*')
1119
-			->from('share', 's')
1120
-			->andWhere($qb->expr()->orX(
1121
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1122
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1123
-			))
1124
-			->andWhere(
1125
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1126
-			);
1127
-
1128
-		/**
1129
-		 * Reshares for this user are shares where they are the owner.
1130
-		 */
1131
-		if ($reshares === false) {
1132
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1133
-		} else {
1134
-			$qb->andWhere(
1135
-				$qb->expr()->orX(
1136
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1137
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1138
-				)
1139
-			);
1140
-		}
1141
-
1142
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1143
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1144
-
1145
-		$qb->orderBy('id');
1146
-
1147
-		$cursor = $qb->execute();
1148
-		$shares = [];
1149
-		while ($data = $cursor->fetch()) {
1150
-			$shares[$data['fileid']][] = $this->createShareObject($data);
1151
-		}
1152
-		$cursor->closeCursor();
1153
-
1154
-		return $shares;
1155
-	}
1156
-
1157
-	/**
1158
-	 * @inheritdoc
1159
-	 */
1160
-	public function getAccessList($nodes, $currentAccess) {
1161
-		$ids = [];
1162
-		foreach ($nodes as $node) {
1163
-			$ids[] = $node->getId();
1164
-		}
1165
-
1166
-		$qb = $this->dbConnection->getQueryBuilder();
1167
-		$qb->select('share_with')
1168
-			->from('share')
1169
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1170
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1171
-			->andWhere($qb->expr()->orX(
1172
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1173
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1174
-			))
1175
-			->setMaxResults(1);
1176
-		$cursor = $qb->execute();
1177
-
1178
-		$mail = $cursor->fetch() !== false;
1179
-		$cursor->closeCursor();
1180
-
1181
-		return ['public' => $mail];
1182
-	}
1183
-
1184
-	public function getAllShares(): iterable {
1185
-		$qb = $this->dbConnection->getQueryBuilder();
1186
-
1187
-		$qb->select('*')
1188
-			->from('share')
1189
-			->where(
1190
-				$qb->expr()->orX(
1191
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
1192
-				)
1193
-			);
1194
-
1195
-		$cursor = $qb->execute();
1196
-		while ($data = $cursor->fetch()) {
1197
-			try {
1198
-				$share = $this->createShareObject($data);
1199
-			} catch (InvalidShare $e) {
1200
-				continue;
1201
-			} catch (ShareNotFound $e) {
1202
-				continue;
1203
-			}
1204
-
1205
-			yield $share;
1206
-		}
1207
-		$cursor->closeCursor();
1208
-	}
734
+        $qb = $this->dbConnection->getQueryBuilder();
735
+        $qb->update('share')
736
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
737
+            ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
738
+            ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
739
+            ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
740
+            ->set('password', $qb->createNamedParameter($share->getPassword()))
741
+            ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
742
+            ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
743
+            ->set('note', $qb->createNamedParameter($share->getNote()))
744
+            ->set('hide_download', $qb->createNamedParameter((int)$share->getHideDownload(), IQueryBuilder::PARAM_INT))
745
+            ->execute();
746
+
747
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
748
+            $this->sendNote($share);
749
+        }
750
+
751
+        return $share;
752
+    }
753
+
754
+    /**
755
+     * @inheritdoc
756
+     */
757
+    public function move(IShare $share, $recipient) {
758
+        /**
759
+         * nothing to do here, mail shares are only outgoing shares
760
+         */
761
+        return $share;
762
+    }
763
+
764
+    /**
765
+     * Delete a share (owner unShares the file)
766
+     *
767
+     * @param IShare $share
768
+     */
769
+    public function delete(IShare $share) {
770
+        try {
771
+            $this->createShareActivity($share, 'unshare');
772
+        } catch (\Exception $e) {
773
+        }
774
+
775
+        $this->removeShareFromTable($share->getId());
776
+    }
777
+
778
+    /**
779
+     * @inheritdoc
780
+     */
781
+    public function deleteFromSelf(IShare $share, $recipient) {
782
+        // nothing to do here, mail shares are only outgoing shares
783
+    }
784
+
785
+    public function restore(IShare $share, string $recipient): IShare {
786
+        throw new GenericShareException('not implemented');
787
+    }
788
+
789
+    /**
790
+     * @inheritdoc
791
+     */
792
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
793
+        $qb = $this->dbConnection->getQueryBuilder();
794
+        $qb->select('*')
795
+            ->from('share');
796
+
797
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
798
+
799
+        /**
800
+         * Reshares for this user are shares where they are the owner.
801
+         */
802
+        if ($reshares === false) {
803
+            //Special case for old shares created via the web UI
804
+            $or1 = $qb->expr()->andX(
805
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
806
+                $qb->expr()->isNull('uid_initiator')
807
+            );
808
+
809
+            $qb->andWhere(
810
+                $qb->expr()->orX(
811
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
812
+                    $or1
813
+                )
814
+            );
815
+        } else {
816
+            $qb->andWhere(
817
+                $qb->expr()->orX(
818
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
819
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
820
+                )
821
+            );
822
+        }
823
+
824
+        if ($node !== null) {
825
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
826
+        }
827
+
828
+        if ($limit !== -1) {
829
+            $qb->setMaxResults($limit);
830
+        }
831
+
832
+        $qb->setFirstResult($offset);
833
+        $qb->orderBy('id');
834
+
835
+        $cursor = $qb->execute();
836
+        $shares = [];
837
+        while ($data = $cursor->fetch()) {
838
+            $shares[] = $this->createShareObject($data);
839
+        }
840
+        $cursor->closeCursor();
841
+
842
+        return $shares;
843
+    }
844
+
845
+    /**
846
+     * @inheritdoc
847
+     */
848
+    public function getShareById($id, $recipientId = null) {
849
+        $qb = $this->dbConnection->getQueryBuilder();
850
+
851
+        $qb->select('*')
852
+            ->from('share')
853
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
854
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
855
+
856
+        $cursor = $qb->execute();
857
+        $data = $cursor->fetch();
858
+        $cursor->closeCursor();
859
+
860
+        if ($data === false) {
861
+            throw new ShareNotFound();
862
+        }
863
+
864
+        try {
865
+            $share = $this->createShareObject($data);
866
+        } catch (InvalidShare $e) {
867
+            throw new ShareNotFound();
868
+        }
869
+
870
+        return $share;
871
+    }
872
+
873
+    /**
874
+     * Get shares for a given path
875
+     *
876
+     * @param \OCP\Files\Node $path
877
+     * @return IShare[]
878
+     */
879
+    public function getSharesByPath(Node $path) {
880
+        $qb = $this->dbConnection->getQueryBuilder();
881
+
882
+        $cursor = $qb->select('*')
883
+            ->from('share')
884
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
885
+            ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
886
+            ->execute();
887
+
888
+        $shares = [];
889
+        while ($data = $cursor->fetch()) {
890
+            $shares[] = $this->createShareObject($data);
891
+        }
892
+        $cursor->closeCursor();
893
+
894
+        return $shares;
895
+    }
896
+
897
+    /**
898
+     * @inheritdoc
899
+     */
900
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
901
+        /** @var IShare[] $shares */
902
+        $shares = [];
903
+
904
+        //Get shares directly with this user
905
+        $qb = $this->dbConnection->getQueryBuilder();
906
+        $qb->select('*')
907
+            ->from('share');
908
+
909
+        // Order by id
910
+        $qb->orderBy('id');
911
+
912
+        // Set limit and offset
913
+        if ($limit !== -1) {
914
+            $qb->setMaxResults($limit);
915
+        }
916
+        $qb->setFirstResult($offset);
917
+
918
+        $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)));
919
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
920
+
921
+        // Filter by node if provided
922
+        if ($node !== null) {
923
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
924
+        }
925
+
926
+        $cursor = $qb->execute();
927
+
928
+        while ($data = $cursor->fetch()) {
929
+            $shares[] = $this->createShareObject($data);
930
+        }
931
+        $cursor->closeCursor();
932
+
933
+
934
+        return $shares;
935
+    }
936
+
937
+    /**
938
+     * Get a share by token
939
+     *
940
+     * @param string $token
941
+     * @return IShare
942
+     * @throws ShareNotFound
943
+     */
944
+    public function getShareByToken($token) {
945
+        $qb = $this->dbConnection->getQueryBuilder();
946
+
947
+        $cursor = $qb->select('*')
948
+            ->from('share')
949
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
950
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
951
+            ->execute();
952
+
953
+        $data = $cursor->fetch();
954
+
955
+        if ($data === false) {
956
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
957
+        }
958
+
959
+        try {
960
+            $share = $this->createShareObject($data);
961
+        } catch (InvalidShare $e) {
962
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
963
+        }
964
+
965
+        return $share;
966
+    }
967
+
968
+    /**
969
+     * remove share from table
970
+     *
971
+     * @param string $shareId
972
+     */
973
+    protected function removeShareFromTable($shareId) {
974
+        $qb = $this->dbConnection->getQueryBuilder();
975
+        $qb->delete('share')
976
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)));
977
+        $qb->execute();
978
+    }
979
+
980
+    /**
981
+     * Create a share object from an database row
982
+     *
983
+     * @param array $data
984
+     * @return IShare
985
+     * @throws InvalidShare
986
+     * @throws ShareNotFound
987
+     */
988
+    protected function createShareObject($data) {
989
+        $share = new Share($this->rootFolder, $this->userManager);
990
+        $share->setId((int)$data['id'])
991
+            ->setShareType((int)$data['share_type'])
992
+            ->setPermissions((int)$data['permissions'])
993
+            ->setTarget($data['file_target'])
994
+            ->setMailSend((bool)$data['mail_send'])
995
+            ->setNote($data['note'])
996
+            ->setToken($data['token']);
997
+
998
+        $shareTime = new \DateTime();
999
+        $shareTime->setTimestamp((int)$data['stime']);
1000
+        $share->setShareTime($shareTime);
1001
+        $share->setSharedWith($data['share_with']);
1002
+        $share->setPassword($data['password']);
1003
+        $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1004
+        $share->setHideDownload((bool)$data['hide_download']);
1005
+
1006
+        if ($data['uid_initiator'] !== null) {
1007
+            $share->setShareOwner($data['uid_owner']);
1008
+            $share->setSharedBy($data['uid_initiator']);
1009
+        } else {
1010
+            //OLD SHARE
1011
+            $share->setSharedBy($data['uid_owner']);
1012
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
1013
+
1014
+            $owner = $path->getOwner();
1015
+            $share->setShareOwner($owner->getUID());
1016
+        }
1017
+
1018
+        if ($data['expiration'] !== null) {
1019
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1020
+            if ($expiration !== false) {
1021
+                $share->setExpirationDate($expiration);
1022
+            }
1023
+        }
1024
+
1025
+        $share->setNodeId((int)$data['file_source']);
1026
+        $share->setNodeType($data['item_type']);
1027
+
1028
+        $share->setProviderId($this->identifier());
1029
+
1030
+        return $share;
1031
+    }
1032
+
1033
+    /**
1034
+     * Get the node with file $id for $user
1035
+     *
1036
+     * @param string $userId
1037
+     * @param int $id
1038
+     * @return \OCP\Files\File|\OCP\Files\Folder
1039
+     * @throws InvalidShare
1040
+     */
1041
+    private function getNode($userId, $id) {
1042
+        try {
1043
+            $userFolder = $this->rootFolder->getUserFolder($userId);
1044
+        } catch (NoUserException $e) {
1045
+            throw new InvalidShare();
1046
+        }
1047
+
1048
+        $nodes = $userFolder->getById($id);
1049
+
1050
+        if (empty($nodes)) {
1051
+            throw new InvalidShare();
1052
+        }
1053
+
1054
+        return $nodes[0];
1055
+    }
1056
+
1057
+    /**
1058
+     * A user is deleted from the system
1059
+     * So clean up the relevant shares.
1060
+     *
1061
+     * @param string $uid
1062
+     * @param int $shareType
1063
+     */
1064
+    public function userDeleted($uid, $shareType) {
1065
+        $qb = $this->dbConnection->getQueryBuilder();
1066
+
1067
+        $qb->delete('share')
1068
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1069
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
1070
+            ->execute();
1071
+    }
1072
+
1073
+    /**
1074
+     * This provider does not support group shares
1075
+     *
1076
+     * @param string $gid
1077
+     */
1078
+    public function groupDeleted($gid) {
1079
+    }
1080
+
1081
+    /**
1082
+     * This provider does not support group shares
1083
+     *
1084
+     * @param string $uid
1085
+     * @param string $gid
1086
+     */
1087
+    public function userDeletedFromGroup($uid, $gid) {
1088
+    }
1089
+
1090
+    /**
1091
+     * get database row of a give share
1092
+     *
1093
+     * @param $id
1094
+     * @return array
1095
+     * @throws ShareNotFound
1096
+     */
1097
+    protected function getRawShare($id) {
1098
+
1099
+        // Now fetch the inserted share and create a complete share object
1100
+        $qb = $this->dbConnection->getQueryBuilder();
1101
+        $qb->select('*')
1102
+            ->from('share')
1103
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
1104
+
1105
+        $cursor = $qb->execute();
1106
+        $data = $cursor->fetch();
1107
+        $cursor->closeCursor();
1108
+
1109
+        if ($data === false) {
1110
+            throw new ShareNotFound;
1111
+        }
1112
+
1113
+        return $data;
1114
+    }
1115
+
1116
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
1117
+        $qb = $this->dbConnection->getQueryBuilder();
1118
+        $qb->select('*')
1119
+            ->from('share', 's')
1120
+            ->andWhere($qb->expr()->orX(
1121
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1122
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1123
+            ))
1124
+            ->andWhere(
1125
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL))
1126
+            );
1127
+
1128
+        /**
1129
+         * Reshares for this user are shares where they are the owner.
1130
+         */
1131
+        if ($reshares === false) {
1132
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
1133
+        } else {
1134
+            $qb->andWhere(
1135
+                $qb->expr()->orX(
1136
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
1137
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
1138
+                )
1139
+            );
1140
+        }
1141
+
1142
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
1143
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
1144
+
1145
+        $qb->orderBy('id');
1146
+
1147
+        $cursor = $qb->execute();
1148
+        $shares = [];
1149
+        while ($data = $cursor->fetch()) {
1150
+            $shares[$data['fileid']][] = $this->createShareObject($data);
1151
+        }
1152
+        $cursor->closeCursor();
1153
+
1154
+        return $shares;
1155
+    }
1156
+
1157
+    /**
1158
+     * @inheritdoc
1159
+     */
1160
+    public function getAccessList($nodes, $currentAccess) {
1161
+        $ids = [];
1162
+        foreach ($nodes as $node) {
1163
+            $ids[] = $node->getId();
1164
+        }
1165
+
1166
+        $qb = $this->dbConnection->getQueryBuilder();
1167
+        $qb->select('share_with')
1168
+            ->from('share')
1169
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_EMAIL)))
1170
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1171
+            ->andWhere($qb->expr()->orX(
1172
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1173
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1174
+            ))
1175
+            ->setMaxResults(1);
1176
+        $cursor = $qb->execute();
1177
+
1178
+        $mail = $cursor->fetch() !== false;
1179
+        $cursor->closeCursor();
1180
+
1181
+        return ['public' => $mail];
1182
+    }
1183
+
1184
+    public function getAllShares(): iterable {
1185
+        $qb = $this->dbConnection->getQueryBuilder();
1186
+
1187
+        $qb->select('*')
1188
+            ->from('share')
1189
+            ->where(
1190
+                $qb->expr()->orX(
1191
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_EMAIL))
1192
+                )
1193
+            );
1194
+
1195
+        $cursor = $qb->execute();
1196
+        while ($data = $cursor->fetch()) {
1197
+            try {
1198
+                $share = $this->createShareObject($data);
1199
+            } catch (InvalidShare $e) {
1200
+                continue;
1201
+            } catch (ShareNotFound $e) {
1202
+                continue;
1203
+            }
1204
+
1205
+            yield $share;
1206
+        }
1207
+        $cursor->closeCursor();
1208
+    }
1209 1209
 }
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/OCM/CloudFederationProviderFiles.php 2 patches
Indentation   +784 added lines, -784 removed lines patch added patch discarded remove patch
@@ -58,788 +58,788 @@
 block discarded – undo
58 58
 
59 59
 class CloudFederationProviderFiles implements ICloudFederationProvider {
60 60
 
61
-	/** @var IAppManager */
62
-	private $appManager;
63
-
64
-	/** @var FederatedShareProvider */
65
-	private $federatedShareProvider;
66
-
67
-	/** @var AddressHandler */
68
-	private $addressHandler;
69
-
70
-	/** @var ILogger */
71
-	private $logger;
72
-
73
-	/** @var IUserManager */
74
-	private $userManager;
75
-
76
-	/** @var IManager */
77
-	private $shareManager;
78
-
79
-	/** @var ICloudIdManager */
80
-	private $cloudIdManager;
81
-
82
-	/** @var IActivityManager */
83
-	private $activityManager;
84
-
85
-	/** @var INotificationManager */
86
-	private $notificationManager;
87
-
88
-	/** @var IURLGenerator */
89
-	private $urlGenerator;
90
-
91
-	/** @var ICloudFederationFactory */
92
-	private $cloudFederationFactory;
93
-
94
-	/** @var ICloudFederationProviderManager */
95
-	private $cloudFederationProviderManager;
96
-
97
-	/** @var IDBConnection */
98
-	private $connection;
99
-
100
-	/** @var IGroupManager */
101
-	private $groupManager;
102
-
103
-	/**
104
-	 * CloudFederationProvider constructor.
105
-	 *
106
-	 * @param IAppManager $appManager
107
-	 * @param FederatedShareProvider $federatedShareProvider
108
-	 * @param AddressHandler $addressHandler
109
-	 * @param ILogger $logger
110
-	 * @param IUserManager $userManager
111
-	 * @param IManager $shareManager
112
-	 * @param ICloudIdManager $cloudIdManager
113
-	 * @param IActivityManager $activityManager
114
-	 * @param INotificationManager $notificationManager
115
-	 * @param IURLGenerator $urlGenerator
116
-	 * @param ICloudFederationFactory $cloudFederationFactory
117
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
118
-	 * @param IDBConnection $connection
119
-	 * @param IGroupManager $groupManager
120
-	 */
121
-	public function __construct(IAppManager $appManager,
122
-								FederatedShareProvider $federatedShareProvider,
123
-								AddressHandler $addressHandler,
124
-								ILogger $logger,
125
-								IUserManager $userManager,
126
-								IManager $shareManager,
127
-								ICloudIdManager $cloudIdManager,
128
-								IActivityManager $activityManager,
129
-								INotificationManager $notificationManager,
130
-								IURLGenerator $urlGenerator,
131
-								ICloudFederationFactory $cloudFederationFactory,
132
-								ICloudFederationProviderManager $cloudFederationProviderManager,
133
-								IDBConnection $connection,
134
-								IGroupManager $groupManager
135
-	) {
136
-		$this->appManager = $appManager;
137
-		$this->federatedShareProvider = $federatedShareProvider;
138
-		$this->addressHandler = $addressHandler;
139
-		$this->logger = $logger;
140
-		$this->userManager = $userManager;
141
-		$this->shareManager = $shareManager;
142
-		$this->cloudIdManager = $cloudIdManager;
143
-		$this->activityManager = $activityManager;
144
-		$this->notificationManager = $notificationManager;
145
-		$this->urlGenerator = $urlGenerator;
146
-		$this->cloudFederationFactory = $cloudFederationFactory;
147
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
148
-		$this->connection = $connection;
149
-		$this->groupManager = $groupManager;
150
-	}
151
-
152
-
153
-
154
-	/**
155
-	 * @return string
156
-	 */
157
-	public function getShareType() {
158
-		return 'file';
159
-	}
160
-
161
-	/**
162
-	 * share received from another server
163
-	 *
164
-	 * @param ICloudFederationShare $share
165
-	 * @return string provider specific unique ID of the share
166
-	 *
167
-	 * @throws ProviderCouldNotAddShareException
168
-	 * @throws \OCP\AppFramework\QueryException
169
-	 * @throws \OC\HintException
170
-	 * @since 14.0.0
171
-	 */
172
-	public function shareReceived(ICloudFederationShare $share) {
173
-		if (!$this->isS2SEnabled(true)) {
174
-			throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
175
-		}
176
-
177
-		$protocol = $share->getProtocol();
178
-		if ($protocol['name'] !== 'webdav') {
179
-			throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
180
-		}
181
-
182
-		list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
183
-		// for backward compatibility make sure that the remote url stored in the
184
-		// database ends with a trailing slash
185
-		if (substr($remote, -1) !== '/') {
186
-			$remote = $remote . '/';
187
-		}
188
-
189
-		$token = $share->getShareSecret();
190
-		$name = $share->getResourceName();
191
-		$owner = $share->getOwnerDisplayName();
192
-		$sharedBy = $share->getSharedByDisplayName();
193
-		$shareWith = $share->getShareWith();
194
-		$remoteId = $share->getProviderId();
195
-		$sharedByFederatedId = $share->getSharedBy();
196
-		$ownerFederatedId = $share->getOwner();
197
-		$shareType = $this->mapShareTypeToNextcloud($share->getShareType());
198
-
199
-		// if no explicit information about the person who created the share was send
200
-		// we assume that the share comes from the owner
201
-		if ($sharedByFederatedId === null) {
202
-			$sharedBy = $owner;
203
-			$sharedByFederatedId = $ownerFederatedId;
204
-		}
205
-
206
-		if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
207
-			if (!Util::isValidFileName($name)) {
208
-				throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
209
-			}
210
-
211
-			// FIXME this should be a method in the user management instead
212
-			if ($shareType === IShare::TYPE_USER) {
213
-				$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
214
-				Util::emitHook(
215
-					'\OCA\Files_Sharing\API\Server2Server',
216
-					'preLoginNameUsedAsUserName',
217
-					['uid' => &$shareWith]
218
-				);
219
-				$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
220
-
221
-				if (!$this->userManager->userExists($shareWith)) {
222
-					throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
223
-				}
224
-
225
-				\OC_Util::setupFS($shareWith);
226
-			}
227
-
228
-			if ($shareType === IShare::TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
229
-				throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
230
-			}
231
-
232
-			$externalManager = new \OCA\Files_Sharing\External\Manager(
233
-				\OC::$server->getDatabaseConnection(),
234
-				Filesystem::getMountManager(),
235
-				Filesystem::getLoader(),
236
-				\OC::$server->getHTTPClientService(),
237
-				\OC::$server->getNotificationManager(),
238
-				\OC::$server->query(\OCP\OCS\IDiscoveryService::class),
239
-				\OC::$server->getCloudFederationProviderManager(),
240
-				\OC::$server->getCloudFederationFactory(),
241
-				\OC::$server->getGroupManager(),
242
-				\OC::$server->getUserManager(),
243
-				$shareWith
244
-			);
245
-
246
-			try {
247
-				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
248
-				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
249
-
250
-				if ($shareType === IShare::TYPE_USER) {
251
-					$event = $this->activityManager->generateEvent();
252
-					$event->setApp('files_sharing')
253
-						->setType('remote_share')
254
-						->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
255
-						->setAffectedUser($shareWith)
256
-						->setObject('remote_share', (int)$shareId, $name);
257
-					\OC::$server->getActivityManager()->publish($event);
258
-					$this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
259
-				} else {
260
-					$groupMembers = $this->groupManager->get($shareWith)->getUsers();
261
-					foreach ($groupMembers as $user) {
262
-						$event = $this->activityManager->generateEvent();
263
-						$event->setApp('files_sharing')
264
-							->setType('remote_share')
265
-							->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
266
-							->setAffectedUser($user->getUID())
267
-							->setObject('remote_share', (int)$shareId, $name);
268
-						\OC::$server->getActivityManager()->publish($event);
269
-						$this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
270
-					}
271
-				}
272
-				return $shareId;
273
-			} catch (\Exception $e) {
274
-				$this->logger->logException($e, [
275
-					'message' => 'Server can not add remote share.',
276
-					'level' => ILogger::ERROR,
277
-					'app' => 'files_sharing'
278
-				]);
279
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
280
-			}
281
-		}
282
-
283
-		throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
284
-	}
285
-
286
-	/**
287
-	 * notification received from another server
288
-	 *
289
-	 * @param string $notificationType (e.g. SHARE_ACCEPTED)
290
-	 * @param string $providerId id of the share
291
-	 * @param array $notification payload of the notification
292
-	 * @return array data send back to the sender
293
-	 *
294
-	 * @throws ActionNotSupportedException
295
-	 * @throws AuthenticationFailedException
296
-	 * @throws BadRequestException
297
-	 * @throws \OC\HintException
298
-	 * @since 14.0.0
299
-	 */
300
-	public function notificationReceived($notificationType, $providerId, array $notification) {
301
-		switch ($notificationType) {
302
-			case 'SHARE_ACCEPTED':
303
-				return $this->shareAccepted($providerId, $notification);
304
-			case 'SHARE_DECLINED':
305
-				return $this->shareDeclined($providerId, $notification);
306
-			case 'SHARE_UNSHARED':
307
-				return $this->unshare($providerId, $notification);
308
-			case 'REQUEST_RESHARE':
309
-				return $this->reshareRequested($providerId, $notification);
310
-			case 'RESHARE_UNDO':
311
-				return $this->undoReshare($providerId, $notification);
312
-			case 'RESHARE_CHANGE_PERMISSION':
313
-				return $this->updateResharePermissions($providerId, $notification);
314
-		}
315
-
316
-
317
-		throw new BadRequestException([$notificationType]);
318
-	}
319
-
320
-	/**
321
-	 * map OCM share type (strings) to Nextcloud internal share types (integer)
322
-	 *
323
-	 * @param string $shareType
324
-	 * @return int
325
-	 */
326
-	private function mapShareTypeToNextcloud($shareType) {
327
-		$result = IShare::TYPE_USER;
328
-		if ($shareType === 'group') {
329
-			$result = IShare::TYPE_GROUP;
330
-		}
331
-
332
-		return $result;
333
-	}
334
-
335
-	/**
336
-	 * notify user about new federated share
337
-	 *
338
-	 * @param $shareWith
339
-	 * @param $shareId
340
-	 * @param $ownerFederatedId
341
-	 * @param $sharedByFederatedId
342
-	 * @param $name
343
-	 */
344
-	private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner) {
345
-		$notification = $this->notificationManager->createNotification();
346
-		$notification->setApp('files_sharing')
347
-			->setUser($shareWith)
348
-			->setDateTime(new \DateTime())
349
-			->setObject('remote_share', $shareId)
350
-			->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/'), $sharedBy, $owner]);
351
-
352
-		$declineAction = $notification->createAction();
353
-		$declineAction->setLabel('decline')
354
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
355
-		$notification->addAction($declineAction);
356
-
357
-		$acceptAction = $notification->createAction();
358
-		$acceptAction->setLabel('accept')
359
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
360
-		$notification->addAction($acceptAction);
361
-
362
-		$this->notificationManager->notify($notification);
363
-	}
364
-
365
-	/**
366
-	 * process notification that the recipient accepted a share
367
-	 *
368
-	 * @param string $id
369
-	 * @param array $notification
370
-	 * @return array
371
-	 * @throws ActionNotSupportedException
372
-	 * @throws AuthenticationFailedException
373
-	 * @throws BadRequestException
374
-	 * @throws \OC\HintException
375
-	 */
376
-	private function shareAccepted($id, array $notification) {
377
-		if (!$this->isS2SEnabled()) {
378
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
379
-		}
380
-
381
-		if (!isset($notification['sharedSecret'])) {
382
-			throw new BadRequestException(['sharedSecret']);
383
-		}
384
-
385
-		$token = $notification['sharedSecret'];
386
-
387
-		$share = $this->federatedShareProvider->getShareById($id);
388
-
389
-		$this->verifyShare($share, $token);
390
-		$this->executeAcceptShare($share);
391
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
392
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
393
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
394
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
395
-			$notification->setMessage(
396
-				'SHARE_ACCEPTED',
397
-				'file',
398
-				$remoteId,
399
-				[
400
-					'sharedSecret' => $token,
401
-					'message' => 'Recipient accepted the re-share'
402
-				]
403
-
404
-			);
405
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
406
-		}
407
-
408
-		return [];
409
-	}
410
-
411
-	/**
412
-	 * @param IShare $share
413
-	 * @throws ShareNotFound
414
-	 */
415
-	protected function executeAcceptShare(IShare $share) {
416
-		try {
417
-			$fileId = (int)$share->getNode()->getId();
418
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
419
-		} catch (\Exception $e) {
420
-			throw new ShareNotFound();
421
-		}
422
-
423
-		$event = $this->activityManager->generateEvent();
424
-		$event->setApp('files_sharing')
425
-			->setType('remote_share')
426
-			->setAffectedUser($this->getCorrectUid($share))
427
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
428
-			->setObject('files', $fileId, $file)
429
-			->setLink($link);
430
-		$this->activityManager->publish($event);
431
-	}
432
-
433
-	/**
434
-	 * process notification that the recipient declined a share
435
-	 *
436
-	 * @param string $id
437
-	 * @param array $notification
438
-	 * @return array
439
-	 * @throws ActionNotSupportedException
440
-	 * @throws AuthenticationFailedException
441
-	 * @throws BadRequestException
442
-	 * @throws ShareNotFound
443
-	 * @throws \OC\HintException
444
-	 *
445
-	 */
446
-	protected function shareDeclined($id, array $notification) {
447
-		if (!$this->isS2SEnabled()) {
448
-			throw new ActionNotSupportedException('Server does not support federated cloud sharing');
449
-		}
450
-
451
-		if (!isset($notification['sharedSecret'])) {
452
-			throw new BadRequestException(['sharedSecret']);
453
-		}
454
-
455
-		$token = $notification['sharedSecret'];
456
-
457
-		$share = $this->federatedShareProvider->getShareById($id);
458
-
459
-		$this->verifyShare($share, $token);
460
-
461
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
462
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
463
-			$remoteId = $this->federatedShareProvider->getRemoteId($share);
464
-			$notification = $this->cloudFederationFactory->getCloudFederationNotification();
465
-			$notification->setMessage(
466
-				'SHARE_DECLINED',
467
-				'file',
468
-				$remoteId,
469
-				[
470
-					'sharedSecret' => $token,
471
-					'message' => 'Recipient declined the re-share'
472
-				]
473
-
474
-			);
475
-			$this->cloudFederationProviderManager->sendNotification($remote, $notification);
476
-		}
477
-
478
-		$this->executeDeclineShare($share);
479
-
480
-		return [];
481
-	}
482
-
483
-	/**
484
-	 * delete declined share and create a activity
485
-	 *
486
-	 * @param IShare $share
487
-	 * @throws ShareNotFound
488
-	 */
489
-	protected function executeDeclineShare(IShare $share) {
490
-		$this->federatedShareProvider->removeShareFromTable($share);
491
-
492
-		try {
493
-			$fileId = (int)$share->getNode()->getId();
494
-			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
495
-		} catch (\Exception $e) {
496
-			throw new ShareNotFound();
497
-		}
498
-
499
-		$event = $this->activityManager->generateEvent();
500
-		$event->setApp('files_sharing')
501
-			->setType('remote_share')
502
-			->setAffectedUser($this->getCorrectUid($share))
503
-			->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
504
-			->setObject('files', $fileId, $file)
505
-			->setLink($link);
506
-		$this->activityManager->publish($event);
507
-	}
508
-
509
-	/**
510
-	 * received the notification that the owner unshared a file from you
511
-	 *
512
-	 * @param string $id
513
-	 * @param array $notification
514
-	 * @return array
515
-	 * @throws AuthenticationFailedException
516
-	 * @throws BadRequestException
517
-	 */
518
-	private function undoReshare($id, array $notification) {
519
-		if (!isset($notification['sharedSecret'])) {
520
-			throw new BadRequestException(['sharedSecret']);
521
-		}
522
-		$token = $notification['sharedSecret'];
523
-
524
-		$share = $this->federatedShareProvider->getShareById($id);
525
-
526
-		$this->verifyShare($share, $token);
527
-		$this->federatedShareProvider->removeShareFromTable($share);
528
-		return [];
529
-	}
530
-
531
-	/**
532
-	 * unshare file from self
533
-	 *
534
-	 * @param string $id
535
-	 * @param array $notification
536
-	 * @return array
537
-	 * @throws ActionNotSupportedException
538
-	 * @throws BadRequestException
539
-	 */
540
-	private function unshare($id, array $notification) {
541
-		if (!$this->isS2SEnabled(true)) {
542
-			throw new ActionNotSupportedException("incoming shares disabled!");
543
-		}
544
-
545
-		if (!isset($notification['sharedSecret'])) {
546
-			throw new BadRequestException(['sharedSecret']);
547
-		}
548
-		$token = $notification['sharedSecret'];
549
-
550
-		$qb = $this->connection->getQueryBuilder();
551
-		$qb->select('*')
552
-			->from('share_external')
553
-			->where(
554
-				$qb->expr()->andX(
555
-					$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
556
-					$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
557
-				)
558
-			);
559
-
560
-		$result = $qb->execute();
561
-		$share = $result->fetch();
562
-		$result->closeCursor();
563
-
564
-		if ($token && $id && !empty($share)) {
565
-			$remote = $this->cleanupRemote($share['remote']);
566
-
567
-			$owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
568
-			$mountpoint = $share['mountpoint'];
569
-			$user = $share['user'];
570
-
571
-			$qb = $this->connection->getQueryBuilder();
572
-			$qb->delete('share_external')
573
-				->where(
574
-					$qb->expr()->andX(
575
-						$qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
576
-						$qb->expr()->eq('share_token', $qb->createNamedParameter($token))
577
-					)
578
-				);
579
-
580
-			$qb->execute();
581
-
582
-			// delete all child in case of a group share
583
-			$qb = $this->connection->getQueryBuilder();
584
-			$qb->delete('share_external')
585
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
586
-			$qb->execute();
587
-
588
-			if ((int)$share['share_type'] === IShare::TYPE_USER) {
589
-				if ($share['accepted']) {
590
-					$path = trim($mountpoint, '/');
591
-				} else {
592
-					$path = trim($share['name'], '/');
593
-				}
594
-				$notification = $this->notificationManager->createNotification();
595
-				$notification->setApp('files_sharing')
596
-					->setUser($share['user'])
597
-					->setObject('remote_share', (int)$share['id']);
598
-				$this->notificationManager->markProcessed($notification);
599
-
600
-				$event = $this->activityManager->generateEvent();
601
-				$event->setApp('files_sharing')
602
-					->setType('remote_share')
603
-					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
604
-					->setAffectedUser($user)
605
-					->setObject('remote_share', (int)$share['id'], $path);
606
-				\OC::$server->getActivityManager()->publish($event);
607
-			}
608
-		}
609
-
610
-		return [];
611
-	}
612
-
613
-	private function cleanupRemote($remote) {
614
-		$remote = substr($remote, strpos($remote, '://') + 3);
615
-
616
-		return rtrim($remote, '/');
617
-	}
618
-
619
-	/**
620
-	 * recipient of a share request to re-share the file with another user
621
-	 *
622
-	 * @param string $id
623
-	 * @param array $notification
624
-	 * @return array
625
-	 * @throws AuthenticationFailedException
626
-	 * @throws BadRequestException
627
-	 * @throws ProviderCouldNotAddShareException
628
-	 * @throws ShareNotFound
629
-	 */
630
-	protected function reshareRequested($id, array $notification) {
631
-		if (!isset($notification['sharedSecret'])) {
632
-			throw new BadRequestException(['sharedSecret']);
633
-		}
634
-		$token = $notification['sharedSecret'];
635
-
636
-		if (!isset($notification['shareWith'])) {
637
-			throw new BadRequestException(['shareWith']);
638
-		}
639
-		$shareWith = $notification['shareWith'];
640
-
641
-		if (!isset($notification['senderId'])) {
642
-			throw new BadRequestException(['senderId']);
643
-		}
644
-		$senderId = $notification['senderId'];
645
-
646
-		$share = $this->federatedShareProvider->getShareById($id);
647
-		// don't allow to share a file back to the owner
648
-		try {
649
-			list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
650
-			$owner = $share->getShareOwner();
651
-			$currentServer = $this->addressHandler->generateRemoteURL();
652
-			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
653
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
654
-			}
655
-		} catch (\Exception $e) {
656
-			throw new ProviderCouldNotAddShareException($e->getMessage());
657
-		}
658
-
659
-		$this->verifyShare($share, $token);
660
-
661
-		// check if re-sharing is allowed
662
-		if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
663
-			// the recipient of the initial share is now the initiator for the re-share
664
-			$share->setSharedBy($share->getSharedWith());
665
-			$share->setSharedWith($shareWith);
666
-			$result = $this->federatedShareProvider->create($share);
667
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
668
-			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
669
-		} else {
670
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
671
-		}
672
-	}
673
-
674
-	/**
675
-	 * update permission of a re-share so that the share dialog shows the right
676
-	 * permission if the owner or the sender changes the permission
677
-	 *
678
-	 * @param string $id
679
-	 * @param array $notification
680
-	 * @return array
681
-	 * @throws AuthenticationFailedException
682
-	 * @throws BadRequestException
683
-	 */
684
-	protected function updateResharePermissions($id, array $notification) {
685
-		if (!isset($notification['sharedSecret'])) {
686
-			throw new BadRequestException(['sharedSecret']);
687
-		}
688
-		$token = $notification['sharedSecret'];
689
-
690
-		if (!isset($notification['permission'])) {
691
-			throw new BadRequestException(['permission']);
692
-		}
693
-		$ocmPermissions = $notification['permission'];
694
-
695
-		$share = $this->federatedShareProvider->getShareById($id);
696
-
697
-		$ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
698
-
699
-		$this->verifyShare($share, $token);
700
-		$this->updatePermissionsInDatabase($share, $ncPermission);
701
-
702
-		return [];
703
-	}
704
-
705
-	/**
706
-	 * translate OCM Permissions to Nextcloud permissions
707
-	 *
708
-	 * @param array $ocmPermissions
709
-	 * @return int
710
-	 * @throws BadRequestException
711
-	 */
712
-	protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
713
-		$ncPermissions = 0;
714
-		foreach ($ocmPermissions as $permission) {
715
-			switch (strtolower($permission)) {
716
-				case 'read':
717
-					$ncPermissions += Constants::PERMISSION_READ;
718
-					break;
719
-				case 'write':
720
-					$ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
721
-					break;
722
-				case 'share':
723
-					$ncPermissions += Constants::PERMISSION_SHARE;
724
-					break;
725
-				default:
726
-					throw new BadRequestException(['permission']);
727
-			}
728
-		}
729
-
730
-		return $ncPermissions;
731
-	}
732
-
733
-	/**
734
-	 * update permissions in database
735
-	 *
736
-	 * @param IShare $share
737
-	 * @param int $permissions
738
-	 */
739
-	protected function updatePermissionsInDatabase(IShare $share, $permissions) {
740
-		$query = $this->connection->getQueryBuilder();
741
-		$query->update('share')
742
-			->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
743
-			->set('permissions', $query->createNamedParameter($permissions))
744
-			->execute();
745
-	}
746
-
747
-
748
-	/**
749
-	 * get file
750
-	 *
751
-	 * @param string $user
752
-	 * @param int $fileSource
753
-	 * @return array with internal path of the file and a absolute link to it
754
-	 */
755
-	private function getFile($user, $fileSource) {
756
-		\OC_Util::setupFS($user);
757
-
758
-		try {
759
-			$file = Filesystem::getPath($fileSource);
760
-		} catch (NotFoundException $e) {
761
-			$file = null;
762
-		}
763
-		$args = Filesystem::is_dir($file) ? ['dir' => $file] : ['dir' => dirname($file), 'scrollto' => $file];
764
-		$link = Util::linkToAbsolute('files', 'index.php', $args);
765
-
766
-		return [$file, $link];
767
-	}
768
-
769
-	/**
770
-	 * check if we are the initiator or the owner of a re-share and return the correct UID
771
-	 *
772
-	 * @param IShare $share
773
-	 * @return string
774
-	 */
775
-	protected function getCorrectUid(IShare $share) {
776
-		if ($this->userManager->userExists($share->getShareOwner())) {
777
-			return $share->getShareOwner();
778
-		}
779
-
780
-		return $share->getSharedBy();
781
-	}
782
-
783
-
784
-
785
-	/**
786
-	 * check if we got the right share
787
-	 *
788
-	 * @param IShare $share
789
-	 * @param string $token
790
-	 * @return bool
791
-	 * @throws AuthenticationFailedException
792
-	 */
793
-	protected function verifyShare(IShare $share, $token) {
794
-		if (
795
-			$share->getShareType() === IShare::TYPE_REMOTE &&
796
-			$share->getToken() === $token
797
-		) {
798
-			return true;
799
-		}
800
-
801
-		if ($share->getShareType() === IShare::TYPE_CIRCLE) {
802
-			try {
803
-				$knownShare = $this->shareManager->getShareByToken($token);
804
-				if ($knownShare->getId() === $share->getId()) {
805
-					return true;
806
-				}
807
-			} catch (ShareNotFound $e) {
808
-			}
809
-		}
810
-
811
-		throw new AuthenticationFailedException();
812
-	}
813
-
814
-
815
-
816
-	/**
817
-	 * check if server-to-server sharing is enabled
818
-	 *
819
-	 * @param bool $incoming
820
-	 * @return bool
821
-	 */
822
-	private function isS2SEnabled($incoming = false) {
823
-		$result = $this->appManager->isEnabledForUser('files_sharing');
824
-
825
-		if ($incoming) {
826
-			$result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
827
-		} else {
828
-			$result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
829
-		}
830
-
831
-		return $result;
832
-	}
833
-
834
-
835
-	/**
836
-	 * get the supported share types, e.g. "user", "group", etc.
837
-	 *
838
-	 * @return array
839
-	 *
840
-	 * @since 14.0.0
841
-	 */
842
-	public function getSupportedShareTypes() {
843
-		return ['user', 'group'];
844
-	}
61
+    /** @var IAppManager */
62
+    private $appManager;
63
+
64
+    /** @var FederatedShareProvider */
65
+    private $federatedShareProvider;
66
+
67
+    /** @var AddressHandler */
68
+    private $addressHandler;
69
+
70
+    /** @var ILogger */
71
+    private $logger;
72
+
73
+    /** @var IUserManager */
74
+    private $userManager;
75
+
76
+    /** @var IManager */
77
+    private $shareManager;
78
+
79
+    /** @var ICloudIdManager */
80
+    private $cloudIdManager;
81
+
82
+    /** @var IActivityManager */
83
+    private $activityManager;
84
+
85
+    /** @var INotificationManager */
86
+    private $notificationManager;
87
+
88
+    /** @var IURLGenerator */
89
+    private $urlGenerator;
90
+
91
+    /** @var ICloudFederationFactory */
92
+    private $cloudFederationFactory;
93
+
94
+    /** @var ICloudFederationProviderManager */
95
+    private $cloudFederationProviderManager;
96
+
97
+    /** @var IDBConnection */
98
+    private $connection;
99
+
100
+    /** @var IGroupManager */
101
+    private $groupManager;
102
+
103
+    /**
104
+     * CloudFederationProvider constructor.
105
+     *
106
+     * @param IAppManager $appManager
107
+     * @param FederatedShareProvider $federatedShareProvider
108
+     * @param AddressHandler $addressHandler
109
+     * @param ILogger $logger
110
+     * @param IUserManager $userManager
111
+     * @param IManager $shareManager
112
+     * @param ICloudIdManager $cloudIdManager
113
+     * @param IActivityManager $activityManager
114
+     * @param INotificationManager $notificationManager
115
+     * @param IURLGenerator $urlGenerator
116
+     * @param ICloudFederationFactory $cloudFederationFactory
117
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
118
+     * @param IDBConnection $connection
119
+     * @param IGroupManager $groupManager
120
+     */
121
+    public function __construct(IAppManager $appManager,
122
+                                FederatedShareProvider $federatedShareProvider,
123
+                                AddressHandler $addressHandler,
124
+                                ILogger $logger,
125
+                                IUserManager $userManager,
126
+                                IManager $shareManager,
127
+                                ICloudIdManager $cloudIdManager,
128
+                                IActivityManager $activityManager,
129
+                                INotificationManager $notificationManager,
130
+                                IURLGenerator $urlGenerator,
131
+                                ICloudFederationFactory $cloudFederationFactory,
132
+                                ICloudFederationProviderManager $cloudFederationProviderManager,
133
+                                IDBConnection $connection,
134
+                                IGroupManager $groupManager
135
+    ) {
136
+        $this->appManager = $appManager;
137
+        $this->federatedShareProvider = $federatedShareProvider;
138
+        $this->addressHandler = $addressHandler;
139
+        $this->logger = $logger;
140
+        $this->userManager = $userManager;
141
+        $this->shareManager = $shareManager;
142
+        $this->cloudIdManager = $cloudIdManager;
143
+        $this->activityManager = $activityManager;
144
+        $this->notificationManager = $notificationManager;
145
+        $this->urlGenerator = $urlGenerator;
146
+        $this->cloudFederationFactory = $cloudFederationFactory;
147
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
148
+        $this->connection = $connection;
149
+        $this->groupManager = $groupManager;
150
+    }
151
+
152
+
153
+
154
+    /**
155
+     * @return string
156
+     */
157
+    public function getShareType() {
158
+        return 'file';
159
+    }
160
+
161
+    /**
162
+     * share received from another server
163
+     *
164
+     * @param ICloudFederationShare $share
165
+     * @return string provider specific unique ID of the share
166
+     *
167
+     * @throws ProviderCouldNotAddShareException
168
+     * @throws \OCP\AppFramework\QueryException
169
+     * @throws \OC\HintException
170
+     * @since 14.0.0
171
+     */
172
+    public function shareReceived(ICloudFederationShare $share) {
173
+        if (!$this->isS2SEnabled(true)) {
174
+            throw new ProviderCouldNotAddShareException('Server does not support federated cloud sharing', '', Http::STATUS_SERVICE_UNAVAILABLE);
175
+        }
176
+
177
+        $protocol = $share->getProtocol();
178
+        if ($protocol['name'] !== 'webdav') {
179
+            throw new ProviderCouldNotAddShareException('Unsupported protocol for data exchange.', '', Http::STATUS_NOT_IMPLEMENTED);
180
+        }
181
+
182
+        list($ownerUid, $remote) = $this->addressHandler->splitUserRemote($share->getOwner());
183
+        // for backward compatibility make sure that the remote url stored in the
184
+        // database ends with a trailing slash
185
+        if (substr($remote, -1) !== '/') {
186
+            $remote = $remote . '/';
187
+        }
188
+
189
+        $token = $share->getShareSecret();
190
+        $name = $share->getResourceName();
191
+        $owner = $share->getOwnerDisplayName();
192
+        $sharedBy = $share->getSharedByDisplayName();
193
+        $shareWith = $share->getShareWith();
194
+        $remoteId = $share->getProviderId();
195
+        $sharedByFederatedId = $share->getSharedBy();
196
+        $ownerFederatedId = $share->getOwner();
197
+        $shareType = $this->mapShareTypeToNextcloud($share->getShareType());
198
+
199
+        // if no explicit information about the person who created the share was send
200
+        // we assume that the share comes from the owner
201
+        if ($sharedByFederatedId === null) {
202
+            $sharedBy = $owner;
203
+            $sharedByFederatedId = $ownerFederatedId;
204
+        }
205
+
206
+        if ($remote && $token && $name && $owner && $remoteId && $shareWith) {
207
+            if (!Util::isValidFileName($name)) {
208
+                throw new ProviderCouldNotAddShareException('The mountpoint name contains invalid characters.', '', Http::STATUS_BAD_REQUEST);
209
+            }
210
+
211
+            // FIXME this should be a method in the user management instead
212
+            if ($shareType === IShare::TYPE_USER) {
213
+                $this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
214
+                Util::emitHook(
215
+                    '\OCA\Files_Sharing\API\Server2Server',
216
+                    'preLoginNameUsedAsUserName',
217
+                    ['uid' => &$shareWith]
218
+                );
219
+                $this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
220
+
221
+                if (!$this->userManager->userExists($shareWith)) {
222
+                    throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
223
+                }
224
+
225
+                \OC_Util::setupFS($shareWith);
226
+            }
227
+
228
+            if ($shareType === IShare::TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
229
+                throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
230
+            }
231
+
232
+            $externalManager = new \OCA\Files_Sharing\External\Manager(
233
+                \OC::$server->getDatabaseConnection(),
234
+                Filesystem::getMountManager(),
235
+                Filesystem::getLoader(),
236
+                \OC::$server->getHTTPClientService(),
237
+                \OC::$server->getNotificationManager(),
238
+                \OC::$server->query(\OCP\OCS\IDiscoveryService::class),
239
+                \OC::$server->getCloudFederationProviderManager(),
240
+                \OC::$server->getCloudFederationFactory(),
241
+                \OC::$server->getGroupManager(),
242
+                \OC::$server->getUserManager(),
243
+                $shareWith
244
+            );
245
+
246
+            try {
247
+                $externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
248
+                $shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
249
+
250
+                if ($shareType === IShare::TYPE_USER) {
251
+                    $event = $this->activityManager->generateEvent();
252
+                    $event->setApp('files_sharing')
253
+                        ->setType('remote_share')
254
+                        ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
255
+                        ->setAffectedUser($shareWith)
256
+                        ->setObject('remote_share', (int)$shareId, $name);
257
+                    \OC::$server->getActivityManager()->publish($event);
258
+                    $this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
259
+                } else {
260
+                    $groupMembers = $this->groupManager->get($shareWith)->getUsers();
261
+                    foreach ($groupMembers as $user) {
262
+                        $event = $this->activityManager->generateEvent();
263
+                        $event->setApp('files_sharing')
264
+                            ->setType('remote_share')
265
+                            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
266
+                            ->setAffectedUser($user->getUID())
267
+                            ->setObject('remote_share', (int)$shareId, $name);
268
+                        \OC::$server->getActivityManager()->publish($event);
269
+                        $this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
270
+                    }
271
+                }
272
+                return $shareId;
273
+            } catch (\Exception $e) {
274
+                $this->logger->logException($e, [
275
+                    'message' => 'Server can not add remote share.',
276
+                    'level' => ILogger::ERROR,
277
+                    'app' => 'files_sharing'
278
+                ]);
279
+                throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
280
+            }
281
+        }
282
+
283
+        throw new ProviderCouldNotAddShareException('server can not add remote share, missing parameter', '', HTTP::STATUS_BAD_REQUEST);
284
+    }
285
+
286
+    /**
287
+     * notification received from another server
288
+     *
289
+     * @param string $notificationType (e.g. SHARE_ACCEPTED)
290
+     * @param string $providerId id of the share
291
+     * @param array $notification payload of the notification
292
+     * @return array data send back to the sender
293
+     *
294
+     * @throws ActionNotSupportedException
295
+     * @throws AuthenticationFailedException
296
+     * @throws BadRequestException
297
+     * @throws \OC\HintException
298
+     * @since 14.0.0
299
+     */
300
+    public function notificationReceived($notificationType, $providerId, array $notification) {
301
+        switch ($notificationType) {
302
+            case 'SHARE_ACCEPTED':
303
+                return $this->shareAccepted($providerId, $notification);
304
+            case 'SHARE_DECLINED':
305
+                return $this->shareDeclined($providerId, $notification);
306
+            case 'SHARE_UNSHARED':
307
+                return $this->unshare($providerId, $notification);
308
+            case 'REQUEST_RESHARE':
309
+                return $this->reshareRequested($providerId, $notification);
310
+            case 'RESHARE_UNDO':
311
+                return $this->undoReshare($providerId, $notification);
312
+            case 'RESHARE_CHANGE_PERMISSION':
313
+                return $this->updateResharePermissions($providerId, $notification);
314
+        }
315
+
316
+
317
+        throw new BadRequestException([$notificationType]);
318
+    }
319
+
320
+    /**
321
+     * map OCM share type (strings) to Nextcloud internal share types (integer)
322
+     *
323
+     * @param string $shareType
324
+     * @return int
325
+     */
326
+    private function mapShareTypeToNextcloud($shareType) {
327
+        $result = IShare::TYPE_USER;
328
+        if ($shareType === 'group') {
329
+            $result = IShare::TYPE_GROUP;
330
+        }
331
+
332
+        return $result;
333
+    }
334
+
335
+    /**
336
+     * notify user about new federated share
337
+     *
338
+     * @param $shareWith
339
+     * @param $shareId
340
+     * @param $ownerFederatedId
341
+     * @param $sharedByFederatedId
342
+     * @param $name
343
+     */
344
+    private function notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner) {
345
+        $notification = $this->notificationManager->createNotification();
346
+        $notification->setApp('files_sharing')
347
+            ->setUser($shareWith)
348
+            ->setDateTime(new \DateTime())
349
+            ->setObject('remote_share', $shareId)
350
+            ->setSubject('remote_share', [$ownerFederatedId, $sharedByFederatedId, trim($name, '/'), $sharedBy, $owner]);
351
+
352
+        $declineAction = $notification->createAction();
353
+        $declineAction->setLabel('decline')
354
+            ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
355
+        $notification->addAction($declineAction);
356
+
357
+        $acceptAction = $notification->createAction();
358
+        $acceptAction->setLabel('accept')
359
+            ->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
360
+        $notification->addAction($acceptAction);
361
+
362
+        $this->notificationManager->notify($notification);
363
+    }
364
+
365
+    /**
366
+     * process notification that the recipient accepted a share
367
+     *
368
+     * @param string $id
369
+     * @param array $notification
370
+     * @return array
371
+     * @throws ActionNotSupportedException
372
+     * @throws AuthenticationFailedException
373
+     * @throws BadRequestException
374
+     * @throws \OC\HintException
375
+     */
376
+    private function shareAccepted($id, array $notification) {
377
+        if (!$this->isS2SEnabled()) {
378
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
379
+        }
380
+
381
+        if (!isset($notification['sharedSecret'])) {
382
+            throw new BadRequestException(['sharedSecret']);
383
+        }
384
+
385
+        $token = $notification['sharedSecret'];
386
+
387
+        $share = $this->federatedShareProvider->getShareById($id);
388
+
389
+        $this->verifyShare($share, $token);
390
+        $this->executeAcceptShare($share);
391
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
392
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
393
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
394
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
395
+            $notification->setMessage(
396
+                'SHARE_ACCEPTED',
397
+                'file',
398
+                $remoteId,
399
+                [
400
+                    'sharedSecret' => $token,
401
+                    'message' => 'Recipient accepted the re-share'
402
+                ]
403
+
404
+            );
405
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
406
+        }
407
+
408
+        return [];
409
+    }
410
+
411
+    /**
412
+     * @param IShare $share
413
+     * @throws ShareNotFound
414
+     */
415
+    protected function executeAcceptShare(IShare $share) {
416
+        try {
417
+            $fileId = (int)$share->getNode()->getId();
418
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
419
+        } catch (\Exception $e) {
420
+            throw new ShareNotFound();
421
+        }
422
+
423
+        $event = $this->activityManager->generateEvent();
424
+        $event->setApp('files_sharing')
425
+            ->setType('remote_share')
426
+            ->setAffectedUser($this->getCorrectUid($share))
427
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_ACCEPTED, [$share->getSharedWith(), [$fileId => $file]])
428
+            ->setObject('files', $fileId, $file)
429
+            ->setLink($link);
430
+        $this->activityManager->publish($event);
431
+    }
432
+
433
+    /**
434
+     * process notification that the recipient declined a share
435
+     *
436
+     * @param string $id
437
+     * @param array $notification
438
+     * @return array
439
+     * @throws ActionNotSupportedException
440
+     * @throws AuthenticationFailedException
441
+     * @throws BadRequestException
442
+     * @throws ShareNotFound
443
+     * @throws \OC\HintException
444
+     *
445
+     */
446
+    protected function shareDeclined($id, array $notification) {
447
+        if (!$this->isS2SEnabled()) {
448
+            throw new ActionNotSupportedException('Server does not support federated cloud sharing');
449
+        }
450
+
451
+        if (!isset($notification['sharedSecret'])) {
452
+            throw new BadRequestException(['sharedSecret']);
453
+        }
454
+
455
+        $token = $notification['sharedSecret'];
456
+
457
+        $share = $this->federatedShareProvider->getShareById($id);
458
+
459
+        $this->verifyShare($share, $token);
460
+
461
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
462
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
463
+            $remoteId = $this->federatedShareProvider->getRemoteId($share);
464
+            $notification = $this->cloudFederationFactory->getCloudFederationNotification();
465
+            $notification->setMessage(
466
+                'SHARE_DECLINED',
467
+                'file',
468
+                $remoteId,
469
+                [
470
+                    'sharedSecret' => $token,
471
+                    'message' => 'Recipient declined the re-share'
472
+                ]
473
+
474
+            );
475
+            $this->cloudFederationProviderManager->sendNotification($remote, $notification);
476
+        }
477
+
478
+        $this->executeDeclineShare($share);
479
+
480
+        return [];
481
+    }
482
+
483
+    /**
484
+     * delete declined share and create a activity
485
+     *
486
+     * @param IShare $share
487
+     * @throws ShareNotFound
488
+     */
489
+    protected function executeDeclineShare(IShare $share) {
490
+        $this->federatedShareProvider->removeShareFromTable($share);
491
+
492
+        try {
493
+            $fileId = (int)$share->getNode()->getId();
494
+            list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
495
+        } catch (\Exception $e) {
496
+            throw new ShareNotFound();
497
+        }
498
+
499
+        $event = $this->activityManager->generateEvent();
500
+        $event->setApp('files_sharing')
501
+            ->setType('remote_share')
502
+            ->setAffectedUser($this->getCorrectUid($share))
503
+            ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_DECLINED, [$share->getSharedWith(), [$fileId => $file]])
504
+            ->setObject('files', $fileId, $file)
505
+            ->setLink($link);
506
+        $this->activityManager->publish($event);
507
+    }
508
+
509
+    /**
510
+     * received the notification that the owner unshared a file from you
511
+     *
512
+     * @param string $id
513
+     * @param array $notification
514
+     * @return array
515
+     * @throws AuthenticationFailedException
516
+     * @throws BadRequestException
517
+     */
518
+    private function undoReshare($id, array $notification) {
519
+        if (!isset($notification['sharedSecret'])) {
520
+            throw new BadRequestException(['sharedSecret']);
521
+        }
522
+        $token = $notification['sharedSecret'];
523
+
524
+        $share = $this->federatedShareProvider->getShareById($id);
525
+
526
+        $this->verifyShare($share, $token);
527
+        $this->federatedShareProvider->removeShareFromTable($share);
528
+        return [];
529
+    }
530
+
531
+    /**
532
+     * unshare file from self
533
+     *
534
+     * @param string $id
535
+     * @param array $notification
536
+     * @return array
537
+     * @throws ActionNotSupportedException
538
+     * @throws BadRequestException
539
+     */
540
+    private function unshare($id, array $notification) {
541
+        if (!$this->isS2SEnabled(true)) {
542
+            throw new ActionNotSupportedException("incoming shares disabled!");
543
+        }
544
+
545
+        if (!isset($notification['sharedSecret'])) {
546
+            throw new BadRequestException(['sharedSecret']);
547
+        }
548
+        $token = $notification['sharedSecret'];
549
+
550
+        $qb = $this->connection->getQueryBuilder();
551
+        $qb->select('*')
552
+            ->from('share_external')
553
+            ->where(
554
+                $qb->expr()->andX(
555
+                    $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
556
+                    $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
557
+                )
558
+            );
559
+
560
+        $result = $qb->execute();
561
+        $share = $result->fetch();
562
+        $result->closeCursor();
563
+
564
+        if ($token && $id && !empty($share)) {
565
+            $remote = $this->cleanupRemote($share['remote']);
566
+
567
+            $owner = $this->cloudIdManager->getCloudId($share['owner'], $remote);
568
+            $mountpoint = $share['mountpoint'];
569
+            $user = $share['user'];
570
+
571
+            $qb = $this->connection->getQueryBuilder();
572
+            $qb->delete('share_external')
573
+                ->where(
574
+                    $qb->expr()->andX(
575
+                        $qb->expr()->eq('remote_id', $qb->createNamedParameter($id)),
576
+                        $qb->expr()->eq('share_token', $qb->createNamedParameter($token))
577
+                    )
578
+                );
579
+
580
+            $qb->execute();
581
+
582
+            // delete all child in case of a group share
583
+            $qb = $this->connection->getQueryBuilder();
584
+            $qb->delete('share_external')
585
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
586
+            $qb->execute();
587
+
588
+            if ((int)$share['share_type'] === IShare::TYPE_USER) {
589
+                if ($share['accepted']) {
590
+                    $path = trim($mountpoint, '/');
591
+                } else {
592
+                    $path = trim($share['name'], '/');
593
+                }
594
+                $notification = $this->notificationManager->createNotification();
595
+                $notification->setApp('files_sharing')
596
+                    ->setUser($share['user'])
597
+                    ->setObject('remote_share', (int)$share['id']);
598
+                $this->notificationManager->markProcessed($notification);
599
+
600
+                $event = $this->activityManager->generateEvent();
601
+                $event->setApp('files_sharing')
602
+                    ->setType('remote_share')
603
+                    ->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
604
+                    ->setAffectedUser($user)
605
+                    ->setObject('remote_share', (int)$share['id'], $path);
606
+                \OC::$server->getActivityManager()->publish($event);
607
+            }
608
+        }
609
+
610
+        return [];
611
+    }
612
+
613
+    private function cleanupRemote($remote) {
614
+        $remote = substr($remote, strpos($remote, '://') + 3);
615
+
616
+        return rtrim($remote, '/');
617
+    }
618
+
619
+    /**
620
+     * recipient of a share request to re-share the file with another user
621
+     *
622
+     * @param string $id
623
+     * @param array $notification
624
+     * @return array
625
+     * @throws AuthenticationFailedException
626
+     * @throws BadRequestException
627
+     * @throws ProviderCouldNotAddShareException
628
+     * @throws ShareNotFound
629
+     */
630
+    protected function reshareRequested($id, array $notification) {
631
+        if (!isset($notification['sharedSecret'])) {
632
+            throw new BadRequestException(['sharedSecret']);
633
+        }
634
+        $token = $notification['sharedSecret'];
635
+
636
+        if (!isset($notification['shareWith'])) {
637
+            throw new BadRequestException(['shareWith']);
638
+        }
639
+        $shareWith = $notification['shareWith'];
640
+
641
+        if (!isset($notification['senderId'])) {
642
+            throw new BadRequestException(['senderId']);
643
+        }
644
+        $senderId = $notification['senderId'];
645
+
646
+        $share = $this->federatedShareProvider->getShareById($id);
647
+        // don't allow to share a file back to the owner
648
+        try {
649
+            list($user, $remote) = $this->addressHandler->splitUserRemote($shareWith);
650
+            $owner = $share->getShareOwner();
651
+            $currentServer = $this->addressHandler->generateRemoteURL();
652
+            if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
653
+                throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
654
+            }
655
+        } catch (\Exception $e) {
656
+            throw new ProviderCouldNotAddShareException($e->getMessage());
657
+        }
658
+
659
+        $this->verifyShare($share, $token);
660
+
661
+        // check if re-sharing is allowed
662
+        if ($share->getPermissions() & Constants::PERMISSION_SHARE) {
663
+            // the recipient of the initial share is now the initiator for the re-share
664
+            $share->setSharedBy($share->getSharedWith());
665
+            $share->setSharedWith($shareWith);
666
+            $result = $this->federatedShareProvider->create($share);
667
+            $this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
668
+            return ['token' => $result->getToken(), 'providerId' => $result->getId()];
669
+        } else {
670
+            throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
671
+        }
672
+    }
673
+
674
+    /**
675
+     * update permission of a re-share so that the share dialog shows the right
676
+     * permission if the owner or the sender changes the permission
677
+     *
678
+     * @param string $id
679
+     * @param array $notification
680
+     * @return array
681
+     * @throws AuthenticationFailedException
682
+     * @throws BadRequestException
683
+     */
684
+    protected function updateResharePermissions($id, array $notification) {
685
+        if (!isset($notification['sharedSecret'])) {
686
+            throw new BadRequestException(['sharedSecret']);
687
+        }
688
+        $token = $notification['sharedSecret'];
689
+
690
+        if (!isset($notification['permission'])) {
691
+            throw new BadRequestException(['permission']);
692
+        }
693
+        $ocmPermissions = $notification['permission'];
694
+
695
+        $share = $this->federatedShareProvider->getShareById($id);
696
+
697
+        $ncPermission = $this->ocmPermissions2ncPermissions($ocmPermissions);
698
+
699
+        $this->verifyShare($share, $token);
700
+        $this->updatePermissionsInDatabase($share, $ncPermission);
701
+
702
+        return [];
703
+    }
704
+
705
+    /**
706
+     * translate OCM Permissions to Nextcloud permissions
707
+     *
708
+     * @param array $ocmPermissions
709
+     * @return int
710
+     * @throws BadRequestException
711
+     */
712
+    protected function ocmPermissions2ncPermissions(array $ocmPermissions) {
713
+        $ncPermissions = 0;
714
+        foreach ($ocmPermissions as $permission) {
715
+            switch (strtolower($permission)) {
716
+                case 'read':
717
+                    $ncPermissions += Constants::PERMISSION_READ;
718
+                    break;
719
+                case 'write':
720
+                    $ncPermissions += Constants::PERMISSION_CREATE + Constants::PERMISSION_UPDATE;
721
+                    break;
722
+                case 'share':
723
+                    $ncPermissions += Constants::PERMISSION_SHARE;
724
+                    break;
725
+                default:
726
+                    throw new BadRequestException(['permission']);
727
+            }
728
+        }
729
+
730
+        return $ncPermissions;
731
+    }
732
+
733
+    /**
734
+     * update permissions in database
735
+     *
736
+     * @param IShare $share
737
+     * @param int $permissions
738
+     */
739
+    protected function updatePermissionsInDatabase(IShare $share, $permissions) {
740
+        $query = $this->connection->getQueryBuilder();
741
+        $query->update('share')
742
+            ->where($query->expr()->eq('id', $query->createNamedParameter($share->getId())))
743
+            ->set('permissions', $query->createNamedParameter($permissions))
744
+            ->execute();
745
+    }
746
+
747
+
748
+    /**
749
+     * get file
750
+     *
751
+     * @param string $user
752
+     * @param int $fileSource
753
+     * @return array with internal path of the file and a absolute link to it
754
+     */
755
+    private function getFile($user, $fileSource) {
756
+        \OC_Util::setupFS($user);
757
+
758
+        try {
759
+            $file = Filesystem::getPath($fileSource);
760
+        } catch (NotFoundException $e) {
761
+            $file = null;
762
+        }
763
+        $args = Filesystem::is_dir($file) ? ['dir' => $file] : ['dir' => dirname($file), 'scrollto' => $file];
764
+        $link = Util::linkToAbsolute('files', 'index.php', $args);
765
+
766
+        return [$file, $link];
767
+    }
768
+
769
+    /**
770
+     * check if we are the initiator or the owner of a re-share and return the correct UID
771
+     *
772
+     * @param IShare $share
773
+     * @return string
774
+     */
775
+    protected function getCorrectUid(IShare $share) {
776
+        if ($this->userManager->userExists($share->getShareOwner())) {
777
+            return $share->getShareOwner();
778
+        }
779
+
780
+        return $share->getSharedBy();
781
+    }
782
+
783
+
784
+
785
+    /**
786
+     * check if we got the right share
787
+     *
788
+     * @param IShare $share
789
+     * @param string $token
790
+     * @return bool
791
+     * @throws AuthenticationFailedException
792
+     */
793
+    protected function verifyShare(IShare $share, $token) {
794
+        if (
795
+            $share->getShareType() === IShare::TYPE_REMOTE &&
796
+            $share->getToken() === $token
797
+        ) {
798
+            return true;
799
+        }
800
+
801
+        if ($share->getShareType() === IShare::TYPE_CIRCLE) {
802
+            try {
803
+                $knownShare = $this->shareManager->getShareByToken($token);
804
+                if ($knownShare->getId() === $share->getId()) {
805
+                    return true;
806
+                }
807
+            } catch (ShareNotFound $e) {
808
+            }
809
+        }
810
+
811
+        throw new AuthenticationFailedException();
812
+    }
813
+
814
+
815
+
816
+    /**
817
+     * check if server-to-server sharing is enabled
818
+     *
819
+     * @param bool $incoming
820
+     * @return bool
821
+     */
822
+    private function isS2SEnabled($incoming = false) {
823
+        $result = $this->appManager->isEnabledForUser('files_sharing');
824
+
825
+        if ($incoming) {
826
+            $result = $result && $this->federatedShareProvider->isIncomingServer2serverShareEnabled();
827
+        } else {
828
+            $result = $result && $this->federatedShareProvider->isOutgoingServer2serverShareEnabled();
829
+        }
830
+
831
+        return $result;
832
+    }
833
+
834
+
835
+    /**
836
+     * get the supported share types, e.g. "user", "group", etc.
837
+     *
838
+     * @return array
839
+     *
840
+     * @since 14.0.0
841
+     */
842
+    public function getSupportedShareTypes() {
843
+        return ['user', 'group'];
844
+    }
845 845
 }
Please login to merge, or discard this patch.
Spacing   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 		// for backward compatibility make sure that the remote url stored in the
184 184
 		// database ends with a trailing slash
185 185
 		if (substr($remote, -1) !== '/') {
186
-			$remote = $remote . '/';
186
+			$remote = $remote.'/';
187 187
 		}
188 188
 
189 189
 		$token = $share->getShareSecret();
@@ -210,23 +210,23 @@  discard block
 block discarded – undo
210 210
 
211 211
 			// FIXME this should be a method in the user management instead
212 212
 			if ($shareType === IShare::TYPE_USER) {
213
-				$this->logger->debug('shareWith before, ' . $shareWith, ['app' => 'files_sharing']);
213
+				$this->logger->debug('shareWith before, '.$shareWith, ['app' => 'files_sharing']);
214 214
 				Util::emitHook(
215 215
 					'\OCA\Files_Sharing\API\Server2Server',
216 216
 					'preLoginNameUsedAsUserName',
217 217
 					['uid' => &$shareWith]
218 218
 				);
219
-				$this->logger->debug('shareWith after, ' . $shareWith, ['app' => 'files_sharing']);
219
+				$this->logger->debug('shareWith after, '.$shareWith, ['app' => 'files_sharing']);
220 220
 
221 221
 				if (!$this->userManager->userExists($shareWith)) {
222
-					throw new ProviderCouldNotAddShareException('User does not exists', '',Http::STATUS_BAD_REQUEST);
222
+					throw new ProviderCouldNotAddShareException('User does not exists', '', Http::STATUS_BAD_REQUEST);
223 223
 				}
224 224
 
225 225
 				\OC_Util::setupFS($shareWith);
226 226
 			}
227 227
 
228 228
 			if ($shareType === IShare::TYPE_GROUP && !$this->groupManager->groupExists($shareWith)) {
229
-				throw new ProviderCouldNotAddShareException('Group does not exists', '',Http::STATUS_BAD_REQUEST);
229
+				throw new ProviderCouldNotAddShareException('Group does not exists', '', Http::STATUS_BAD_REQUEST);
230 230
 			}
231 231
 
232 232
 			$externalManager = new \OCA\Files_Sharing\External\Manager(
@@ -244,7 +244,7 @@  discard block
 block discarded – undo
244 244
 			);
245 245
 
246 246
 			try {
247
-				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType,false, $shareWith, $remoteId);
247
+				$externalManager->addShare($remote, $token, '', $name, $owner, $shareType, false, $shareWith, $remoteId);
248 248
 				$shareId = \OC::$server->getDatabaseConnection()->lastInsertId('*PREFIX*share_external');
249 249
 
250 250
 				if ($shareType === IShare::TYPE_USER) {
@@ -253,7 +253,7 @@  discard block
 block discarded – undo
253 253
 						->setType('remote_share')
254 254
 						->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
255 255
 						->setAffectedUser($shareWith)
256
-						->setObject('remote_share', (int)$shareId, $name);
256
+						->setObject('remote_share', (int) $shareId, $name);
257 257
 					\OC::$server->getActivityManager()->publish($event);
258 258
 					$this->notifyAboutNewShare($shareWith, $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
259 259
 				} else {
@@ -264,7 +264,7 @@  discard block
 block discarded – undo
264 264
 							->setType('remote_share')
265 265
 							->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_RECEIVED, [$ownerFederatedId, trim($name, '/')])
266 266
 							->setAffectedUser($user->getUID())
267
-							->setObject('remote_share', (int)$shareId, $name);
267
+							->setObject('remote_share', (int) $shareId, $name);
268 268
 						\OC::$server->getActivityManager()->publish($event);
269 269
 						$this->notifyAboutNewShare($user->getUID(), $shareId, $ownerFederatedId, $sharedByFederatedId, $name, $sharedBy, $owner);
270 270
 					}
@@ -276,7 +276,7 @@  discard block
 block discarded – undo
276 276
 					'level' => ILogger::ERROR,
277 277
 					'app' => 'files_sharing'
278 278
 				]);
279
-				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from ' . $remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
279
+				throw new ProviderCouldNotAddShareException('internal server error, was not able to add share from '.$remote, '', HTTP::STATUS_INTERNAL_SERVER_ERROR);
280 280
 			}
281 281
 		}
282 282
 
@@ -351,12 +351,12 @@  discard block
 block discarded – undo
351 351
 
352 352
 		$declineAction = $notification->createAction();
353 353
 		$declineAction->setLabel('decline')
354
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'DELETE');
354
+			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'DELETE');
355 355
 		$notification->addAction($declineAction);
356 356
 
357 357
 		$acceptAction = $notification->createAction();
358 358
 		$acceptAction->setLabel('accept')
359
-			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/' . $shareId)), 'POST');
359
+			->setLink($this->urlGenerator->getAbsoluteURL($this->urlGenerator->linkTo('', 'ocs/v2.php/apps/files_sharing/api/v1/remote_shares/pending/'.$shareId)), 'POST');
360 360
 		$notification->addAction($acceptAction);
361 361
 
362 362
 		$this->notificationManager->notify($notification);
@@ -414,7 +414,7 @@  discard block
 block discarded – undo
414 414
 	 */
415 415
 	protected function executeAcceptShare(IShare $share) {
416 416
 		try {
417
-			$fileId = (int)$share->getNode()->getId();
417
+			$fileId = (int) $share->getNode()->getId();
418 418
 			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
419 419
 		} catch (\Exception $e) {
420 420
 			throw new ShareNotFound();
@@ -490,7 +490,7 @@  discard block
 block discarded – undo
490 490
 		$this->federatedShareProvider->removeShareFromTable($share);
491 491
 
492 492
 		try {
493
-			$fileId = (int)$share->getNode()->getId();
493
+			$fileId = (int) $share->getNode()->getId();
494 494
 			list($file, $link) = $this->getFile($this->getCorrectUid($share), $fileId);
495 495
 		} catch (\Exception $e) {
496 496
 			throw new ShareNotFound();
@@ -582,10 +582,10 @@  discard block
 block discarded – undo
582 582
 			// delete all child in case of a group share
583 583
 			$qb = $this->connection->getQueryBuilder();
584 584
 			$qb->delete('share_external')
585
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int)$share['id'])));
585
+				->where($qb->expr()->eq('parent', $qb->createNamedParameter((int) $share['id'])));
586 586
 			$qb->execute();
587 587
 
588
-			if ((int)$share['share_type'] === IShare::TYPE_USER) {
588
+			if ((int) $share['share_type'] === IShare::TYPE_USER) {
589 589
 				if ($share['accepted']) {
590 590
 					$path = trim($mountpoint, '/');
591 591
 				} else {
@@ -594,7 +594,7 @@  discard block
 block discarded – undo
594 594
 				$notification = $this->notificationManager->createNotification();
595 595
 				$notification->setApp('files_sharing')
596 596
 					->setUser($share['user'])
597
-					->setObject('remote_share', (int)$share['id']);
597
+					->setObject('remote_share', (int) $share['id']);
598 598
 				$this->notificationManager->markProcessed($notification);
599 599
 
600 600
 				$event = $this->activityManager->generateEvent();
@@ -602,7 +602,7 @@  discard block
 block discarded – undo
602 602
 					->setType('remote_share')
603 603
 					->setSubject(RemoteShares::SUBJECT_REMOTE_SHARE_UNSHARED, [$owner->getId(), $path])
604 604
 					->setAffectedUser($user)
605
-					->setObject('remote_share', (int)$share['id'], $path);
605
+					->setObject('remote_share', (int) $share['id'], $path);
606 606
 				\OC::$server->getActivityManager()->publish($event);
607 607
 			}
608 608
 		}
@@ -650,7 +650,7 @@  discard block
 block discarded – undo
650 650
 			$owner = $share->getShareOwner();
651 651
 			$currentServer = $this->addressHandler->generateRemoteURL();
652 652
 			if ($this->addressHandler->compareAddresses($user, $remote, $owner, $currentServer)) {
653
-				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: ' . $id);
653
+				throw new ProviderCouldNotAddShareException('Resharing back to the owner is not allowed: '.$id);
654 654
 			}
655 655
 		} catch (\Exception $e) {
656 656
 			throw new ProviderCouldNotAddShareException($e->getMessage());
@@ -664,10 +664,10 @@  discard block
 block discarded – undo
664 664
 			$share->setSharedBy($share->getSharedWith());
665 665
 			$share->setSharedWith($shareWith);
666 666
 			$result = $this->federatedShareProvider->create($share);
667
-			$this->federatedShareProvider->storeRemoteId((int)$result->getId(), $senderId);
667
+			$this->federatedShareProvider->storeRemoteId((int) $result->getId(), $senderId);
668 668
 			return ['token' => $result->getToken(), 'providerId' => $result->getId()];
669 669
 		} else {
670
-			throw new ProviderCouldNotAddShareException('resharing not allowed for share: ' . $id);
670
+			throw new ProviderCouldNotAddShareException('resharing not allowed for share: '.$id);
671 671
 		}
672 672
 	}
673 673
 
Please login to merge, or discard this patch.
apps/federatedfilesharing/lib/FederatedShareProvider.php 1 patch
Indentation   +1057 added lines, -1057 removed lines patch added patch discarded remove patch
@@ -58,1071 +58,1071 @@
 block discarded – undo
58 58
  * @package OCA\FederatedFileSharing
59 59
  */
60 60
 class FederatedShareProvider implements IShareProvider {
61
-	public const SHARE_TYPE_REMOTE = 6;
62
-
63
-	/** @var IDBConnection */
64
-	private $dbConnection;
65
-
66
-	/** @var AddressHandler */
67
-	private $addressHandler;
68
-
69
-	/** @var Notifications */
70
-	private $notifications;
71
-
72
-	/** @var TokenHandler */
73
-	private $tokenHandler;
74
-
75
-	/** @var IL10N */
76
-	private $l;
77
-
78
-	/** @var ILogger */
79
-	private $logger;
80
-
81
-	/** @var IRootFolder */
82
-	private $rootFolder;
83
-
84
-	/** @var IConfig */
85
-	private $config;
86
-
87
-	/** @var string */
88
-	private $externalShareTable = 'share_external';
89
-
90
-	/** @var IUserManager */
91
-	private $userManager;
92
-
93
-	/** @var ICloudIdManager */
94
-	private $cloudIdManager;
95
-
96
-	/** @var \OCP\GlobalScale\IConfig */
97
-	private $gsConfig;
98
-
99
-	/** @var ICloudFederationProviderManager */
100
-	private $cloudFederationProviderManager;
101
-
102
-	/** @var array list of supported share types */
103
-	private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
104
-
105
-	/**
106
-	 * DefaultShareProvider constructor.
107
-	 *
108
-	 * @param IDBConnection $connection
109
-	 * @param AddressHandler $addressHandler
110
-	 * @param Notifications $notifications
111
-	 * @param TokenHandler $tokenHandler
112
-	 * @param IL10N $l10n
113
-	 * @param ILogger $logger
114
-	 * @param IRootFolder $rootFolder
115
-	 * @param IConfig $config
116
-	 * @param IUserManager $userManager
117
-	 * @param ICloudIdManager $cloudIdManager
118
-	 * @param \OCP\GlobalScale\IConfig $globalScaleConfig
119
-	 * @param ICloudFederationProviderManager $cloudFederationProviderManager
120
-	 */
121
-	public function __construct(
122
-			IDBConnection $connection,
123
-			AddressHandler $addressHandler,
124
-			Notifications $notifications,
125
-			TokenHandler $tokenHandler,
126
-			IL10N $l10n,
127
-			ILogger $logger,
128
-			IRootFolder $rootFolder,
129
-			IConfig $config,
130
-			IUserManager $userManager,
131
-			ICloudIdManager $cloudIdManager,
132
-			\OCP\GlobalScale\IConfig $globalScaleConfig,
133
-			ICloudFederationProviderManager $cloudFederationProviderManager
134
-	) {
135
-		$this->dbConnection = $connection;
136
-		$this->addressHandler = $addressHandler;
137
-		$this->notifications = $notifications;
138
-		$this->tokenHandler = $tokenHandler;
139
-		$this->l = $l10n;
140
-		$this->logger = $logger;
141
-		$this->rootFolder = $rootFolder;
142
-		$this->config = $config;
143
-		$this->userManager = $userManager;
144
-		$this->cloudIdManager = $cloudIdManager;
145
-		$this->gsConfig = $globalScaleConfig;
146
-		$this->cloudFederationProviderManager = $cloudFederationProviderManager;
147
-	}
148
-
149
-	/**
150
-	 * Return the identifier of this provider.
151
-	 *
152
-	 * @return string Containing only [a-zA-Z0-9]
153
-	 */
154
-	public function identifier() {
155
-		return 'ocFederatedSharing';
156
-	}
157
-
158
-	/**
159
-	 * Share a path
160
-	 *
161
-	 * @param IShare $share
162
-	 * @return IShare The share object
163
-	 * @throws ShareNotFound
164
-	 * @throws \Exception
165
-	 */
166
-	public function create(IShare $share) {
167
-		$shareWith = $share->getSharedWith();
168
-		$itemSource = $share->getNodeId();
169
-		$itemType = $share->getNodeType();
170
-		$permissions = $share->getPermissions();
171
-		$sharedBy = $share->getSharedBy();
172
-		$shareType = $share->getShareType();
173
-
174
-		if ($shareType === IShare::TYPE_REMOTE_GROUP &&
175
-			!$this->isOutgoingServer2serverGroupShareEnabled()
176
-		) {
177
-			$message = 'It is not allowed to send federated group shares from this server.';
178
-			$message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
-			throw new \Exception($message_t);
181
-		}
182
-
183
-		/*
61
+    public const SHARE_TYPE_REMOTE = 6;
62
+
63
+    /** @var IDBConnection */
64
+    private $dbConnection;
65
+
66
+    /** @var AddressHandler */
67
+    private $addressHandler;
68
+
69
+    /** @var Notifications */
70
+    private $notifications;
71
+
72
+    /** @var TokenHandler */
73
+    private $tokenHandler;
74
+
75
+    /** @var IL10N */
76
+    private $l;
77
+
78
+    /** @var ILogger */
79
+    private $logger;
80
+
81
+    /** @var IRootFolder */
82
+    private $rootFolder;
83
+
84
+    /** @var IConfig */
85
+    private $config;
86
+
87
+    /** @var string */
88
+    private $externalShareTable = 'share_external';
89
+
90
+    /** @var IUserManager */
91
+    private $userManager;
92
+
93
+    /** @var ICloudIdManager */
94
+    private $cloudIdManager;
95
+
96
+    /** @var \OCP\GlobalScale\IConfig */
97
+    private $gsConfig;
98
+
99
+    /** @var ICloudFederationProviderManager */
100
+    private $cloudFederationProviderManager;
101
+
102
+    /** @var array list of supported share types */
103
+    private $supportedShareType = [IShare::TYPE_REMOTE_GROUP, IShare::TYPE_REMOTE, IShare::TYPE_CIRCLE];
104
+
105
+    /**
106
+     * DefaultShareProvider constructor.
107
+     *
108
+     * @param IDBConnection $connection
109
+     * @param AddressHandler $addressHandler
110
+     * @param Notifications $notifications
111
+     * @param TokenHandler $tokenHandler
112
+     * @param IL10N $l10n
113
+     * @param ILogger $logger
114
+     * @param IRootFolder $rootFolder
115
+     * @param IConfig $config
116
+     * @param IUserManager $userManager
117
+     * @param ICloudIdManager $cloudIdManager
118
+     * @param \OCP\GlobalScale\IConfig $globalScaleConfig
119
+     * @param ICloudFederationProviderManager $cloudFederationProviderManager
120
+     */
121
+    public function __construct(
122
+            IDBConnection $connection,
123
+            AddressHandler $addressHandler,
124
+            Notifications $notifications,
125
+            TokenHandler $tokenHandler,
126
+            IL10N $l10n,
127
+            ILogger $logger,
128
+            IRootFolder $rootFolder,
129
+            IConfig $config,
130
+            IUserManager $userManager,
131
+            ICloudIdManager $cloudIdManager,
132
+            \OCP\GlobalScale\IConfig $globalScaleConfig,
133
+            ICloudFederationProviderManager $cloudFederationProviderManager
134
+    ) {
135
+        $this->dbConnection = $connection;
136
+        $this->addressHandler = $addressHandler;
137
+        $this->notifications = $notifications;
138
+        $this->tokenHandler = $tokenHandler;
139
+        $this->l = $l10n;
140
+        $this->logger = $logger;
141
+        $this->rootFolder = $rootFolder;
142
+        $this->config = $config;
143
+        $this->userManager = $userManager;
144
+        $this->cloudIdManager = $cloudIdManager;
145
+        $this->gsConfig = $globalScaleConfig;
146
+        $this->cloudFederationProviderManager = $cloudFederationProviderManager;
147
+    }
148
+
149
+    /**
150
+     * Return the identifier of this provider.
151
+     *
152
+     * @return string Containing only [a-zA-Z0-9]
153
+     */
154
+    public function identifier() {
155
+        return 'ocFederatedSharing';
156
+    }
157
+
158
+    /**
159
+     * Share a path
160
+     *
161
+     * @param IShare $share
162
+     * @return IShare The share object
163
+     * @throws ShareNotFound
164
+     * @throws \Exception
165
+     */
166
+    public function create(IShare $share) {
167
+        $shareWith = $share->getSharedWith();
168
+        $itemSource = $share->getNodeId();
169
+        $itemType = $share->getNodeType();
170
+        $permissions = $share->getPermissions();
171
+        $sharedBy = $share->getSharedBy();
172
+        $shareType = $share->getShareType();
173
+
174
+        if ($shareType === IShare::TYPE_REMOTE_GROUP &&
175
+            !$this->isOutgoingServer2serverGroupShareEnabled()
176
+        ) {
177
+            $message = 'It is not allowed to send federated group shares from this server.';
178
+            $message_t = $this->l->t('It is not allowed to send federated group shares from this server.');
179
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
180
+            throw new \Exception($message_t);
181
+        }
182
+
183
+        /*
184 184
 		 * Check if file is not already shared with the remote user
185 185
 		 */
186
-		$alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
187
-		$alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
-		if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
-			$message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
-			$message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
191
-			$this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
-			throw new \Exception($message_t);
193
-		}
194
-
195
-
196
-		// don't allow federated shares if source and target server are the same
197
-		$cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
-		$currentServer = $this->addressHandler->generateRemoteURL();
199
-		$currentUser = $sharedBy;
200
-		if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
-			$message = 'Not allowed to create a federated share with the same user.';
202
-			$message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
-			$this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
-			throw new \Exception($message_t);
205
-		}
206
-
207
-
208
-		$share->setSharedWith($cloudId->getId());
209
-
210
-		try {
211
-			$remoteShare = $this->getShareFromExternalShareTable($share);
212
-		} catch (ShareNotFound $e) {
213
-			$remoteShare = null;
214
-		}
215
-
216
-		if ($remoteShare) {
217
-			try {
218
-				$ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
-				$shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
-				$share->setId($shareId);
221
-				list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
-				// remote share was create successfully if we get a valid token as return
223
-				$send = is_string($token) && $token !== '';
224
-			} catch (\Exception $e) {
225
-				// fall back to old re-share behavior if the remote server
226
-				// doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
-				$this->removeShareFromTable($share);
228
-				$shareId = $this->createFederatedShare($share);
229
-			}
230
-			if ($send) {
231
-				$this->updateSuccessfulReshare($shareId, $token);
232
-				$this->storeRemoteId($shareId, $remoteId);
233
-			} else {
234
-				$this->removeShareFromTable($share);
235
-				$message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
-				throw new \Exception($message_t);
237
-			}
238
-		} else {
239
-			$shareId = $this->createFederatedShare($share);
240
-		}
241
-
242
-		$data = $this->getRawShare($shareId);
243
-		return $this->createShareObject($data);
244
-	}
245
-
246
-	/**
247
-	 * create federated share and inform the recipient
248
-	 *
249
-	 * @param IShare $share
250
-	 * @return int
251
-	 * @throws ShareNotFound
252
-	 * @throws \Exception
253
-	 */
254
-	protected function createFederatedShare(IShare $share) {
255
-		$token = $this->tokenHandler->generateToken();
256
-		$shareId = $this->addShareToDB(
257
-			$share->getNodeId(),
258
-			$share->getNodeType(),
259
-			$share->getSharedWith(),
260
-			$share->getSharedBy(),
261
-			$share->getShareOwner(),
262
-			$share->getPermissions(),
263
-			$token,
264
-			$share->getShareType()
265
-		);
266
-
267
-		$failure = false;
268
-
269
-		try {
270
-			$sharedByFederatedId = $share->getSharedBy();
271
-			if ($this->userManager->userExists($sharedByFederatedId)) {
272
-				$cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
273
-				$sharedByFederatedId = $cloudId->getId();
274
-			}
275
-			$ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
276
-			$send = $this->notifications->sendRemoteShare(
277
-				$token,
278
-				$share->getSharedWith(),
279
-				$share->getNode()->getName(),
280
-				$shareId,
281
-				$share->getShareOwner(),
282
-				$ownerCloudId->getId(),
283
-				$share->getSharedBy(),
284
-				$sharedByFederatedId,
285
-				$share->getShareType()
286
-			);
287
-
288
-			if ($send === false) {
289
-				$failure = true;
290
-			}
291
-		} catch (\Exception $e) {
292
-			$this->logger->logException($e, [
293
-				'message' => 'Failed to notify remote server of federated share, removing share.',
294
-				'level' => ILogger::ERROR,
295
-				'app' => 'federatedfilesharing',
296
-			]);
297
-			$failure = true;
298
-		}
299
-
300
-		if ($failure) {
301
-			$this->removeShareFromTableById($shareId);
302
-			$message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
303
-				[$share->getNode()->getName(), $share->getSharedWith()]);
304
-			throw new \Exception($message_t);
305
-		}
306
-
307
-		return $shareId;
308
-	}
309
-
310
-	/**
311
-	 * @param string $shareWith
312
-	 * @param IShare $share
313
-	 * @param string $shareId internal share Id
314
-	 * @return array
315
-	 * @throws \Exception
316
-	 */
317
-	protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
318
-		$remoteShare = $this->getShareFromExternalShareTable($share);
319
-		$token = $remoteShare['share_token'];
320
-		$remoteId = $remoteShare['remote_id'];
321
-		$remote = $remoteShare['remote'];
322
-
323
-		list($token, $remoteId) = $this->notifications->requestReShare(
324
-			$token,
325
-			$remoteId,
326
-			$shareId,
327
-			$remote,
328
-			$shareWith,
329
-			$share->getPermissions(),
330
-			$share->getNode()->getName()
331
-		);
332
-
333
-		return [$token, $remoteId];
334
-	}
335
-
336
-	/**
337
-	 * get federated share from the share_external table but exclude mounted link shares
338
-	 *
339
-	 * @param IShare $share
340
-	 * @return array
341
-	 * @throws ShareNotFound
342
-	 */
343
-	protected function getShareFromExternalShareTable(IShare $share) {
344
-		$query = $this->dbConnection->getQueryBuilder();
345
-		$query->select('*')->from($this->externalShareTable)
346
-			->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
347
-			->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
348
-		$result = $query->execute()->fetchAll();
349
-
350
-		if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
351
-			return $result[0];
352
-		}
353
-
354
-		throw new ShareNotFound('share not found in share_external table');
355
-	}
356
-
357
-	/**
358
-	 * add share to the database and return the ID
359
-	 *
360
-	 * @param int $itemSource
361
-	 * @param string $itemType
362
-	 * @param string $shareWith
363
-	 * @param string $sharedBy
364
-	 * @param string $uidOwner
365
-	 * @param int $permissions
366
-	 * @param string $token
367
-	 * @param int $shareType
368
-	 * @return int
369
-	 */
370
-	private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
371
-		$qb = $this->dbConnection->getQueryBuilder();
372
-		$qb->insert('share')
373
-			->setValue('share_type', $qb->createNamedParameter($shareType))
374
-			->setValue('item_type', $qb->createNamedParameter($itemType))
375
-			->setValue('item_source', $qb->createNamedParameter($itemSource))
376
-			->setValue('file_source', $qb->createNamedParameter($itemSource))
377
-			->setValue('share_with', $qb->createNamedParameter($shareWith))
378
-			->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
379
-			->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
380
-			->setValue('permissions', $qb->createNamedParameter($permissions))
381
-			->setValue('token', $qb->createNamedParameter($token))
382
-			->setValue('stime', $qb->createNamedParameter(time()));
383
-
384
-		/*
186
+        $alreadyShared = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE, $share->getNode(), 1, 0);
187
+        $alreadySharedGroup = $this->getSharedWith($shareWith, IShare::TYPE_REMOTE_GROUP, $share->getNode(), 1, 0);
188
+        if (!empty($alreadyShared) || !empty($alreadySharedGroup)) {
189
+            $message = 'Sharing %1$s failed, because this item is already shared with %2$s';
190
+            $message_t = $this->l->t('Sharing %1$s failed, because this item is already shared with %2$s', [$share->getNode()->getName(), $shareWith]);
191
+            $this->logger->debug(sprintf($message, $share->getNode()->getName(), $shareWith), ['app' => 'Federated File Sharing']);
192
+            throw new \Exception($message_t);
193
+        }
194
+
195
+
196
+        // don't allow federated shares if source and target server are the same
197
+        $cloudId = $this->cloudIdManager->resolveCloudId($shareWith);
198
+        $currentServer = $this->addressHandler->generateRemoteURL();
199
+        $currentUser = $sharedBy;
200
+        if ($this->addressHandler->compareAddresses($cloudId->getUser(), $cloudId->getRemote(), $currentUser, $currentServer)) {
201
+            $message = 'Not allowed to create a federated share with the same user.';
202
+            $message_t = $this->l->t('Not allowed to create a federated share with the same user');
203
+            $this->logger->debug($message, ['app' => 'Federated File Sharing']);
204
+            throw new \Exception($message_t);
205
+        }
206
+
207
+
208
+        $share->setSharedWith($cloudId->getId());
209
+
210
+        try {
211
+            $remoteShare = $this->getShareFromExternalShareTable($share);
212
+        } catch (ShareNotFound $e) {
213
+            $remoteShare = null;
214
+        }
215
+
216
+        if ($remoteShare) {
217
+            try {
218
+                $ownerCloudId = $this->cloudIdManager->getCloudId($remoteShare['owner'], $remoteShare['remote']);
219
+                $shareId = $this->addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $ownerCloudId->getId(), $permissions, 'tmp_token_' . time(), $shareType);
220
+                $share->setId($shareId);
221
+                list($token, $remoteId) = $this->askOwnerToReShare($shareWith, $share, $shareId);
222
+                // remote share was create successfully if we get a valid token as return
223
+                $send = is_string($token) && $token !== '';
224
+            } catch (\Exception $e) {
225
+                // fall back to old re-share behavior if the remote server
226
+                // doesn't support flat re-shares (was introduced with Nextcloud 9.1)
227
+                $this->removeShareFromTable($share);
228
+                $shareId = $this->createFederatedShare($share);
229
+            }
230
+            if ($send) {
231
+                $this->updateSuccessfulReshare($shareId, $token);
232
+                $this->storeRemoteId($shareId, $remoteId);
233
+            } else {
234
+                $this->removeShareFromTable($share);
235
+                $message_t = $this->l->t('File is already shared with %s', [$shareWith]);
236
+                throw new \Exception($message_t);
237
+            }
238
+        } else {
239
+            $shareId = $this->createFederatedShare($share);
240
+        }
241
+
242
+        $data = $this->getRawShare($shareId);
243
+        return $this->createShareObject($data);
244
+    }
245
+
246
+    /**
247
+     * create federated share and inform the recipient
248
+     *
249
+     * @param IShare $share
250
+     * @return int
251
+     * @throws ShareNotFound
252
+     * @throws \Exception
253
+     */
254
+    protected function createFederatedShare(IShare $share) {
255
+        $token = $this->tokenHandler->generateToken();
256
+        $shareId = $this->addShareToDB(
257
+            $share->getNodeId(),
258
+            $share->getNodeType(),
259
+            $share->getSharedWith(),
260
+            $share->getSharedBy(),
261
+            $share->getShareOwner(),
262
+            $share->getPermissions(),
263
+            $token,
264
+            $share->getShareType()
265
+        );
266
+
267
+        $failure = false;
268
+
269
+        try {
270
+            $sharedByFederatedId = $share->getSharedBy();
271
+            if ($this->userManager->userExists($sharedByFederatedId)) {
272
+                $cloudId = $this->cloudIdManager->getCloudId($sharedByFederatedId, $this->addressHandler->generateRemoteURL());
273
+                $sharedByFederatedId = $cloudId->getId();
274
+            }
275
+            $ownerCloudId = $this->cloudIdManager->getCloudId($share->getShareOwner(), $this->addressHandler->generateRemoteURL());
276
+            $send = $this->notifications->sendRemoteShare(
277
+                $token,
278
+                $share->getSharedWith(),
279
+                $share->getNode()->getName(),
280
+                $shareId,
281
+                $share->getShareOwner(),
282
+                $ownerCloudId->getId(),
283
+                $share->getSharedBy(),
284
+                $sharedByFederatedId,
285
+                $share->getShareType()
286
+            );
287
+
288
+            if ($send === false) {
289
+                $failure = true;
290
+            }
291
+        } catch (\Exception $e) {
292
+            $this->logger->logException($e, [
293
+                'message' => 'Failed to notify remote server of federated share, removing share.',
294
+                'level' => ILogger::ERROR,
295
+                'app' => 'federatedfilesharing',
296
+            ]);
297
+            $failure = true;
298
+        }
299
+
300
+        if ($failure) {
301
+            $this->removeShareFromTableById($shareId);
302
+            $message_t = $this->l->t('Sharing %1$s failed, could not find %2$s, maybe the server is currently unreachable or uses a self-signed certificate.',
303
+                [$share->getNode()->getName(), $share->getSharedWith()]);
304
+            throw new \Exception($message_t);
305
+        }
306
+
307
+        return $shareId;
308
+    }
309
+
310
+    /**
311
+     * @param string $shareWith
312
+     * @param IShare $share
313
+     * @param string $shareId internal share Id
314
+     * @return array
315
+     * @throws \Exception
316
+     */
317
+    protected function askOwnerToReShare($shareWith, IShare $share, $shareId) {
318
+        $remoteShare = $this->getShareFromExternalShareTable($share);
319
+        $token = $remoteShare['share_token'];
320
+        $remoteId = $remoteShare['remote_id'];
321
+        $remote = $remoteShare['remote'];
322
+
323
+        list($token, $remoteId) = $this->notifications->requestReShare(
324
+            $token,
325
+            $remoteId,
326
+            $shareId,
327
+            $remote,
328
+            $shareWith,
329
+            $share->getPermissions(),
330
+            $share->getNode()->getName()
331
+        );
332
+
333
+        return [$token, $remoteId];
334
+    }
335
+
336
+    /**
337
+     * get federated share from the share_external table but exclude mounted link shares
338
+     *
339
+     * @param IShare $share
340
+     * @return array
341
+     * @throws ShareNotFound
342
+     */
343
+    protected function getShareFromExternalShareTable(IShare $share) {
344
+        $query = $this->dbConnection->getQueryBuilder();
345
+        $query->select('*')->from($this->externalShareTable)
346
+            ->where($query->expr()->eq('user', $query->createNamedParameter($share->getShareOwner())))
347
+            ->andWhere($query->expr()->eq('mountpoint', $query->createNamedParameter($share->getTarget())));
348
+        $result = $query->execute()->fetchAll();
349
+
350
+        if (isset($result[0]) && (int)$result[0]['remote_id'] > 0) {
351
+            return $result[0];
352
+        }
353
+
354
+        throw new ShareNotFound('share not found in share_external table');
355
+    }
356
+
357
+    /**
358
+     * add share to the database and return the ID
359
+     *
360
+     * @param int $itemSource
361
+     * @param string $itemType
362
+     * @param string $shareWith
363
+     * @param string $sharedBy
364
+     * @param string $uidOwner
365
+     * @param int $permissions
366
+     * @param string $token
367
+     * @param int $shareType
368
+     * @return int
369
+     */
370
+    private function addShareToDB($itemSource, $itemType, $shareWith, $sharedBy, $uidOwner, $permissions, $token, $shareType) {
371
+        $qb = $this->dbConnection->getQueryBuilder();
372
+        $qb->insert('share')
373
+            ->setValue('share_type', $qb->createNamedParameter($shareType))
374
+            ->setValue('item_type', $qb->createNamedParameter($itemType))
375
+            ->setValue('item_source', $qb->createNamedParameter($itemSource))
376
+            ->setValue('file_source', $qb->createNamedParameter($itemSource))
377
+            ->setValue('share_with', $qb->createNamedParameter($shareWith))
378
+            ->setValue('uid_owner', $qb->createNamedParameter($uidOwner))
379
+            ->setValue('uid_initiator', $qb->createNamedParameter($sharedBy))
380
+            ->setValue('permissions', $qb->createNamedParameter($permissions))
381
+            ->setValue('token', $qb->createNamedParameter($token))
382
+            ->setValue('stime', $qb->createNamedParameter(time()));
383
+
384
+        /*
385 385
 		 * Added to fix https://github.com/owncloud/core/issues/22215
386 386
 		 * Can be removed once we get rid of ajax/share.php
387 387
 		 */
388
-		$qb->setValue('file_target', $qb->createNamedParameter(''));
389
-
390
-		$qb->execute();
391
-		$id = $qb->getLastInsertId();
392
-
393
-		return (int)$id;
394
-	}
395
-
396
-	/**
397
-	 * Update a share
398
-	 *
399
-	 * @param IShare $share
400
-	 * @return IShare The share object
401
-	 */
402
-	public function update(IShare $share) {
403
-		/*
388
+        $qb->setValue('file_target', $qb->createNamedParameter(''));
389
+
390
+        $qb->execute();
391
+        $id = $qb->getLastInsertId();
392
+
393
+        return (int)$id;
394
+    }
395
+
396
+    /**
397
+     * Update a share
398
+     *
399
+     * @param IShare $share
400
+     * @return IShare The share object
401
+     */
402
+    public function update(IShare $share) {
403
+        /*
404 404
 		 * We allow updating the permissions of federated shares
405 405
 		 */
406
-		$qb = $this->dbConnection->getQueryBuilder();
407
-		$qb->update('share')
408
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
409
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
410
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
411
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
412
-				->execute();
413
-
414
-		// send the updated permission to the owner/initiator, if they are not the same
415
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
416
-			$this->sendPermissionUpdate($share);
417
-		}
418
-
419
-		return $share;
420
-	}
421
-
422
-	/**
423
-	 * send the updated permission to the owner/initiator, if they are not the same
424
-	 *
425
-	 * @param IShare $share
426
-	 * @throws ShareNotFound
427
-	 * @throws \OC\HintException
428
-	 */
429
-	protected function sendPermissionUpdate(IShare $share) {
430
-		$remoteId = $this->getRemoteId($share);
431
-		// if the local user is the owner we send the permission change to the initiator
432
-		if ($this->userManager->userExists($share->getShareOwner())) {
433
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
434
-		} else { // ... if not we send the permission change to the owner
435
-			list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
436
-		}
437
-		$this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
438
-	}
439
-
440
-
441
-	/**
442
-	 * update successful reShare with the correct token
443
-	 *
444
-	 * @param int $shareId
445
-	 * @param string $token
446
-	 */
447
-	protected function updateSuccessfulReShare($shareId, $token) {
448
-		$query = $this->dbConnection->getQueryBuilder();
449
-		$query->update('share')
450
-			->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
451
-			->set('token', $query->createNamedParameter($token))
452
-			->execute();
453
-	}
454
-
455
-	/**
456
-	 * store remote ID in federated reShare table
457
-	 *
458
-	 * @param $shareId
459
-	 * @param $remoteId
460
-	 */
461
-	public function storeRemoteId($shareId, $remoteId) {
462
-		$query = $this->dbConnection->getQueryBuilder();
463
-		$query->insert('federated_reshares')
464
-			->values(
465
-				[
466
-					'share_id' =>  $query->createNamedParameter($shareId),
467
-					'remote_id' => $query->createNamedParameter($remoteId),
468
-				]
469
-			);
470
-		$query->execute();
471
-	}
472
-
473
-	/**
474
-	 * get share ID on remote server for federated re-shares
475
-	 *
476
-	 * @param IShare $share
477
-	 * @return int
478
-	 * @throws ShareNotFound
479
-	 */
480
-	public function getRemoteId(IShare $share) {
481
-		$query = $this->dbConnection->getQueryBuilder();
482
-		$query->select('remote_id')->from('federated_reshares')
483
-			->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
484
-		$data = $query->execute()->fetch();
485
-
486
-		if (!is_array($data) || !isset($data['remote_id'])) {
487
-			throw new ShareNotFound();
488
-		}
489
-
490
-		return (int)$data['remote_id'];
491
-	}
492
-
493
-	/**
494
-	 * @inheritdoc
495
-	 */
496
-	public function move(IShare $share, $recipient) {
497
-		/*
406
+        $qb = $this->dbConnection->getQueryBuilder();
407
+        $qb->update('share')
408
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
409
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
410
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
411
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
412
+                ->execute();
413
+
414
+        // send the updated permission to the owner/initiator, if they are not the same
415
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
416
+            $this->sendPermissionUpdate($share);
417
+        }
418
+
419
+        return $share;
420
+    }
421
+
422
+    /**
423
+     * send the updated permission to the owner/initiator, if they are not the same
424
+     *
425
+     * @param IShare $share
426
+     * @throws ShareNotFound
427
+     * @throws \OC\HintException
428
+     */
429
+    protected function sendPermissionUpdate(IShare $share) {
430
+        $remoteId = $this->getRemoteId($share);
431
+        // if the local user is the owner we send the permission change to the initiator
432
+        if ($this->userManager->userExists($share->getShareOwner())) {
433
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
434
+        } else { // ... if not we send the permission change to the owner
435
+            list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
436
+        }
437
+        $this->notifications->sendPermissionChange($remote, $remoteId, $share->getToken(), $share->getPermissions());
438
+    }
439
+
440
+
441
+    /**
442
+     * update successful reShare with the correct token
443
+     *
444
+     * @param int $shareId
445
+     * @param string $token
446
+     */
447
+    protected function updateSuccessfulReShare($shareId, $token) {
448
+        $query = $this->dbConnection->getQueryBuilder();
449
+        $query->update('share')
450
+            ->where($query->expr()->eq('id', $query->createNamedParameter($shareId)))
451
+            ->set('token', $query->createNamedParameter($token))
452
+            ->execute();
453
+    }
454
+
455
+    /**
456
+     * store remote ID in federated reShare table
457
+     *
458
+     * @param $shareId
459
+     * @param $remoteId
460
+     */
461
+    public function storeRemoteId($shareId, $remoteId) {
462
+        $query = $this->dbConnection->getQueryBuilder();
463
+        $query->insert('federated_reshares')
464
+            ->values(
465
+                [
466
+                    'share_id' =>  $query->createNamedParameter($shareId),
467
+                    'remote_id' => $query->createNamedParameter($remoteId),
468
+                ]
469
+            );
470
+        $query->execute();
471
+    }
472
+
473
+    /**
474
+     * get share ID on remote server for federated re-shares
475
+     *
476
+     * @param IShare $share
477
+     * @return int
478
+     * @throws ShareNotFound
479
+     */
480
+    public function getRemoteId(IShare $share) {
481
+        $query = $this->dbConnection->getQueryBuilder();
482
+        $query->select('remote_id')->from('federated_reshares')
483
+            ->where($query->expr()->eq('share_id', $query->createNamedParameter((int)$share->getId())));
484
+        $data = $query->execute()->fetch();
485
+
486
+        if (!is_array($data) || !isset($data['remote_id'])) {
487
+            throw new ShareNotFound();
488
+        }
489
+
490
+        return (int)$data['remote_id'];
491
+    }
492
+
493
+    /**
494
+     * @inheritdoc
495
+     */
496
+    public function move(IShare $share, $recipient) {
497
+        /*
498 498
 		 * This function does nothing yet as it is just for outgoing
499 499
 		 * federated shares.
500 500
 		 */
501
-		return $share;
502
-	}
503
-
504
-	/**
505
-	 * Get all children of this share
506
-	 *
507
-	 * @param IShare $parent
508
-	 * @return IShare[]
509
-	 */
510
-	public function getChildren(IShare $parent) {
511
-		$children = [];
512
-
513
-		$qb = $this->dbConnection->getQueryBuilder();
514
-		$qb->select('*')
515
-			->from('share')
516
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
517
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
518
-			->orderBy('id');
519
-
520
-		$cursor = $qb->execute();
521
-		while ($data = $cursor->fetch()) {
522
-			$children[] = $this->createShareObject($data);
523
-		}
524
-		$cursor->closeCursor();
525
-
526
-		return $children;
527
-	}
528
-
529
-	/**
530
-	 * Delete a share (owner unShares the file)
531
-	 *
532
-	 * @param IShare $share
533
-	 * @throws ShareNotFound
534
-	 * @throws \OC\HintException
535
-	 */
536
-	public function delete(IShare $share) {
537
-		list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
538
-
539
-		// if the local user is the owner we can send the unShare request directly...
540
-		if ($this->userManager->userExists($share->getShareOwner())) {
541
-			$this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
542
-			$this->revokeShare($share, true);
543
-		} else { // ... if not we need to correct ID for the unShare request
544
-			$remoteId = $this->getRemoteId($share);
545
-			$this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
546
-			$this->revokeShare($share, false);
547
-		}
548
-
549
-		// only remove the share when all messages are send to not lose information
550
-		// about the share to early
551
-		$this->removeShareFromTable($share);
552
-	}
553
-
554
-	/**
555
-	 * in case of a re-share we need to send the other use (initiator or owner)
556
-	 * a message that the file was unshared
557
-	 *
558
-	 * @param IShare $share
559
-	 * @param bool $isOwner the user can either be the owner or the user who re-sahred it
560
-	 * @throws ShareNotFound
561
-	 * @throws \OC\HintException
562
-	 */
563
-	protected function revokeShare($share, $isOwner) {
564
-		if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
565
-			// If both the owner and the initiator of the share are local users we don't have to notify anybody else
566
-			return;
567
-		}
568
-
569
-		// also send a unShare request to the initiator, if this is a different user than the owner
570
-		if ($share->getShareOwner() !== $share->getSharedBy()) {
571
-			if ($isOwner) {
572
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
573
-			} else {
574
-				list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
575
-			}
576
-			$remoteId = $this->getRemoteId($share);
577
-			$this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
578
-		}
579
-	}
580
-
581
-	/**
582
-	 * remove share from table
583
-	 *
584
-	 * @param IShare $share
585
-	 */
586
-	public function removeShareFromTable(IShare $share) {
587
-		$this->removeShareFromTableById($share->getId());
588
-	}
589
-
590
-	/**
591
-	 * remove share from table
592
-	 *
593
-	 * @param string $shareId
594
-	 */
595
-	private function removeShareFromTableById($shareId) {
596
-		$qb = $this->dbConnection->getQueryBuilder();
597
-		$qb->delete('share')
598
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
599
-			->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
600
-		$qb->execute();
601
-
602
-		$qb->delete('federated_reshares')
603
-			->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
604
-		$qb->execute();
605
-	}
606
-
607
-	/**
608
-	 * @inheritdoc
609
-	 */
610
-	public function deleteFromSelf(IShare $share, $recipient) {
611
-		// nothing to do here. Technically deleteFromSelf in the context of federated
612
-		// shares is a umount of a external storage. This is handled here
613
-		// apps/files_sharing/lib/external/manager.php
614
-		// TODO move this code over to this app
615
-	}
616
-
617
-	public function restore(IShare $share, string $recipient): IShare {
618
-		throw new GenericShareException('not implemented');
619
-	}
620
-
621
-
622
-	public function getSharesInFolder($userId, Folder $node, $reshares) {
623
-		$qb = $this->dbConnection->getQueryBuilder();
624
-		$qb->select('*')
625
-			->from('share', 's')
626
-			->andWhere($qb->expr()->orX(
627
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
628
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
629
-			))
630
-			->andWhere(
631
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
632
-			);
633
-
634
-		/**
635
-		 * Reshares for this user are shares where they are the owner.
636
-		 */
637
-		if ($reshares === false) {
638
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
639
-		} else {
640
-			$qb->andWhere(
641
-				$qb->expr()->orX(
642
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
643
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
644
-				)
645
-			);
646
-		}
647
-
648
-		$qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
649
-		$qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
650
-
651
-		$qb->orderBy('id');
652
-
653
-		$cursor = $qb->execute();
654
-		$shares = [];
655
-		while ($data = $cursor->fetch()) {
656
-			$shares[$data['fileid']][] = $this->createShareObject($data);
657
-		}
658
-		$cursor->closeCursor();
659
-
660
-		return $shares;
661
-	}
662
-
663
-	/**
664
-	 * @inheritdoc
665
-	 */
666
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
667
-		$qb = $this->dbConnection->getQueryBuilder();
668
-		$qb->select('*')
669
-			->from('share');
670
-
671
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
672
-
673
-		/**
674
-		 * Reshares for this user are shares where they are the owner.
675
-		 */
676
-		if ($reshares === false) {
677
-			//Special case for old shares created via the web UI
678
-			$or1 = $qb->expr()->andX(
679
-				$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
680
-				$qb->expr()->isNull('uid_initiator')
681
-			);
682
-
683
-			$qb->andWhere(
684
-				$qb->expr()->orX(
685
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
686
-					$or1
687
-				)
688
-			);
689
-		} else {
690
-			$qb->andWhere(
691
-				$qb->expr()->orX(
692
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
693
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
694
-				)
695
-			);
696
-		}
697
-
698
-		if ($node !== null) {
699
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
700
-		}
701
-
702
-		if ($limit !== -1) {
703
-			$qb->setMaxResults($limit);
704
-		}
705
-
706
-		$qb->setFirstResult($offset);
707
-		$qb->orderBy('id');
708
-
709
-		$cursor = $qb->execute();
710
-		$shares = [];
711
-		while ($data = $cursor->fetch()) {
712
-			$shares[] = $this->createShareObject($data);
713
-		}
714
-		$cursor->closeCursor();
715
-
716
-		return $shares;
717
-	}
718
-
719
-	/**
720
-	 * @inheritdoc
721
-	 */
722
-	public function getShareById($id, $recipientId = null) {
723
-		$qb = $this->dbConnection->getQueryBuilder();
724
-
725
-		$qb->select('*')
726
-			->from('share')
727
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
728
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
729
-
730
-		$cursor = $qb->execute();
731
-		$data = $cursor->fetch();
732
-		$cursor->closeCursor();
733
-
734
-		if ($data === false) {
735
-			throw new ShareNotFound('Can not find share with ID: ' . $id);
736
-		}
737
-
738
-		try {
739
-			$share = $this->createShareObject($data);
740
-		} catch (InvalidShare $e) {
741
-			throw new ShareNotFound();
742
-		}
743
-
744
-		return $share;
745
-	}
746
-
747
-	/**
748
-	 * Get shares for a given path
749
-	 *
750
-	 * @param \OCP\Files\Node $path
751
-	 * @return IShare[]
752
-	 */
753
-	public function getSharesByPath(Node $path) {
754
-		$qb = $this->dbConnection->getQueryBuilder();
755
-
756
-		// get federated user shares
757
-		$cursor = $qb->select('*')
758
-			->from('share')
759
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
760
-			->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
761
-			->execute();
762
-
763
-		$shares = [];
764
-		while ($data = $cursor->fetch()) {
765
-			$shares[] = $this->createShareObject($data);
766
-		}
767
-		$cursor->closeCursor();
768
-
769
-		return $shares;
770
-	}
771
-
772
-	/**
773
-	 * @inheritdoc
774
-	 */
775
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
776
-		/** @var IShare[] $shares */
777
-		$shares = [];
778
-
779
-		//Get shares directly with this user
780
-		$qb = $this->dbConnection->getQueryBuilder();
781
-		$qb->select('*')
782
-			->from('share');
783
-
784
-		// Order by id
785
-		$qb->orderBy('id');
786
-
787
-		// Set limit and offset
788
-		if ($limit !== -1) {
789
-			$qb->setMaxResults($limit);
790
-		}
791
-		$qb->setFirstResult($offset);
792
-
793
-		$qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
794
-		$qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
795
-
796
-		// Filter by node if provided
797
-		if ($node !== null) {
798
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
799
-		}
800
-
801
-		$cursor = $qb->execute();
802
-
803
-		while ($data = $cursor->fetch()) {
804
-			$shares[] = $this->createShareObject($data);
805
-		}
806
-		$cursor->closeCursor();
807
-
808
-
809
-		return $shares;
810
-	}
811
-
812
-	/**
813
-	 * Get a share by token
814
-	 *
815
-	 * @param string $token
816
-	 * @return IShare
817
-	 * @throws ShareNotFound
818
-	 */
819
-	public function getShareByToken($token) {
820
-		$qb = $this->dbConnection->getQueryBuilder();
821
-
822
-		$cursor = $qb->select('*')
823
-			->from('share')
824
-			->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
825
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
826
-			->execute();
827
-
828
-		$data = $cursor->fetch();
829
-
830
-		if ($data === false) {
831
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
832
-		}
833
-
834
-		try {
835
-			$share = $this->createShareObject($data);
836
-		} catch (InvalidShare $e) {
837
-			throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
838
-		}
839
-
840
-		return $share;
841
-	}
842
-
843
-	/**
844
-	 * get database row of a give share
845
-	 *
846
-	 * @param $id
847
-	 * @return array
848
-	 * @throws ShareNotFound
849
-	 */
850
-	private function getRawShare($id) {
851
-
852
-		// Now fetch the inserted share and create a complete share object
853
-		$qb = $this->dbConnection->getQueryBuilder();
854
-		$qb->select('*')
855
-			->from('share')
856
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
857
-
858
-		$cursor = $qb->execute();
859
-		$data = $cursor->fetch();
860
-		$cursor->closeCursor();
861
-
862
-		if ($data === false) {
863
-			throw new ShareNotFound;
864
-		}
865
-
866
-		return $data;
867
-	}
868
-
869
-	/**
870
-	 * Create a share object from an database row
871
-	 *
872
-	 * @param array $data
873
-	 * @return IShare
874
-	 * @throws InvalidShare
875
-	 * @throws ShareNotFound
876
-	 */
877
-	private function createShareObject($data) {
878
-		$share = new Share($this->rootFolder, $this->userManager);
879
-		$share->setId((int)$data['id'])
880
-			->setShareType((int)$data['share_type'])
881
-			->setPermissions((int)$data['permissions'])
882
-			->setTarget($data['file_target'])
883
-			->setMailSend((bool)$data['mail_send'])
884
-			->setToken($data['token']);
885
-
886
-		$shareTime = new \DateTime();
887
-		$shareTime->setTimestamp((int)$data['stime']);
888
-		$share->setShareTime($shareTime);
889
-		$share->setSharedWith($data['share_with']);
890
-
891
-		if ($data['uid_initiator'] !== null) {
892
-			$share->setShareOwner($data['uid_owner']);
893
-			$share->setSharedBy($data['uid_initiator']);
894
-		} else {
895
-			//OLD SHARE
896
-			$share->setSharedBy($data['uid_owner']);
897
-			$path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
898
-
899
-			$owner = $path->getOwner();
900
-			$share->setShareOwner($owner->getUID());
901
-		}
902
-
903
-		$share->setNodeId((int)$data['file_source']);
904
-		$share->setNodeType($data['item_type']);
905
-
906
-		$share->setProviderId($this->identifier());
907
-
908
-		return $share;
909
-	}
910
-
911
-	/**
912
-	 * Get the node with file $id for $user
913
-	 *
914
-	 * @param string $userId
915
-	 * @param int $id
916
-	 * @return \OCP\Files\File|\OCP\Files\Folder
917
-	 * @throws InvalidShare
918
-	 */
919
-	private function getNode($userId, $id) {
920
-		try {
921
-			$userFolder = $this->rootFolder->getUserFolder($userId);
922
-		} catch (NotFoundException $e) {
923
-			throw new InvalidShare();
924
-		}
925
-
926
-		$nodes = $userFolder->getById($id);
927
-
928
-		if (empty($nodes)) {
929
-			throw new InvalidShare();
930
-		}
931
-
932
-		return $nodes[0];
933
-	}
934
-
935
-	/**
936
-	 * A user is deleted from the system
937
-	 * So clean up the relevant shares.
938
-	 *
939
-	 * @param string $uid
940
-	 * @param int $shareType
941
-	 */
942
-	public function userDeleted($uid, $shareType) {
943
-		//TODO: probabaly a good idea to send unshare info to remote servers
944
-
945
-		$qb = $this->dbConnection->getQueryBuilder();
946
-
947
-		$qb->delete('share')
948
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
949
-			->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
950
-			->execute();
951
-	}
952
-
953
-	/**
954
-	 * This provider does not handle groups
955
-	 *
956
-	 * @param string $gid
957
-	 */
958
-	public function groupDeleted($gid) {
959
-		// We don't handle groups here
960
-	}
961
-
962
-	/**
963
-	 * This provider does not handle groups
964
-	 *
965
-	 * @param string $uid
966
-	 * @param string $gid
967
-	 */
968
-	public function userDeletedFromGroup($uid, $gid) {
969
-		// We don't handle groups here
970
-	}
971
-
972
-	/**
973
-	 * check if users from other Nextcloud instances are allowed to mount public links share by this instance
974
-	 *
975
-	 * @return bool
976
-	 */
977
-	public function isOutgoingServer2serverShareEnabled() {
978
-		if ($this->gsConfig->onlyInternalFederation()) {
979
-			return false;
980
-		}
981
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
982
-		return ($result === 'yes');
983
-	}
984
-
985
-	/**
986
-	 * check if users are allowed to mount public links from other Nextclouds
987
-	 *
988
-	 * @return bool
989
-	 */
990
-	public function isIncomingServer2serverShareEnabled() {
991
-		if ($this->gsConfig->onlyInternalFederation()) {
992
-			return false;
993
-		}
994
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
995
-		return ($result === 'yes');
996
-	}
997
-
998
-
999
-	/**
1000
-	 * check if users from other Nextcloud instances are allowed to send federated group shares
1001
-	 *
1002
-	 * @return bool
1003
-	 */
1004
-	public function isOutgoingServer2serverGroupShareEnabled() {
1005
-		if ($this->gsConfig->onlyInternalFederation()) {
1006
-			return false;
1007
-		}
1008
-		$result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1009
-		return ($result === 'yes');
1010
-	}
1011
-
1012
-	/**
1013
-	 * check if users are allowed to receive federated group shares
1014
-	 *
1015
-	 * @return bool
1016
-	 */
1017
-	public function isIncomingServer2serverGroupShareEnabled() {
1018
-		if ($this->gsConfig->onlyInternalFederation()) {
1019
-			return false;
1020
-		}
1021
-		$result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1022
-		return ($result === 'yes');
1023
-	}
1024
-
1025
-	/**
1026
-	 * check if federated group sharing is supported, therefore the OCM API need to be enabled
1027
-	 *
1028
-	 * @return bool
1029
-	 */
1030
-	public function isFederatedGroupSharingSupported() {
1031
-		return $this->cloudFederationProviderManager->isReady();
1032
-	}
1033
-
1034
-	/**
1035
-	 * Check if querying sharees on the lookup server is enabled
1036
-	 *
1037
-	 * @return bool
1038
-	 */
1039
-	public function isLookupServerQueriesEnabled() {
1040
-		// in a global scale setup we should always query the lookup server
1041
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1042
-			return true;
1043
-		}
1044
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1045
-		return ($result === 'yes');
1046
-	}
1047
-
1048
-
1049
-	/**
1050
-	 * Check if it is allowed to publish user specific data to the lookup server
1051
-	 *
1052
-	 * @return bool
1053
-	 */
1054
-	public function isLookupServerUploadEnabled() {
1055
-		// in a global scale setup the admin is responsible to keep the lookup server up-to-date
1056
-		if ($this->gsConfig->isGlobalScaleEnabled()) {
1057
-			return false;
1058
-		}
1059
-		$result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1060
-		return ($result === 'yes');
1061
-	}
1062
-
1063
-	/**
1064
-	 * @inheritdoc
1065
-	 */
1066
-	public function getAccessList($nodes, $currentAccess) {
1067
-		$ids = [];
1068
-		foreach ($nodes as $node) {
1069
-			$ids[] = $node->getId();
1070
-		}
1071
-
1072
-		$qb = $this->dbConnection->getQueryBuilder();
1073
-		$qb->select('share_with', 'token', 'file_source')
1074
-			->from('share')
1075
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1076
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1077
-			->andWhere($qb->expr()->orX(
1078
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1079
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1080
-			));
1081
-		$cursor = $qb->execute();
1082
-
1083
-		if ($currentAccess === false) {
1084
-			$remote = $cursor->fetch() !== false;
1085
-			$cursor->closeCursor();
1086
-
1087
-			return ['remote' => $remote];
1088
-		}
1089
-
1090
-		$remote = [];
1091
-		while ($row = $cursor->fetch()) {
1092
-			$remote[$row['share_with']] = [
1093
-				'node_id' => $row['file_source'],
1094
-				'token' => $row['token'],
1095
-			];
1096
-		}
1097
-		$cursor->closeCursor();
1098
-
1099
-		return ['remote' => $remote];
1100
-	}
1101
-
1102
-	public function getAllShares(): iterable {
1103
-		$qb = $this->dbConnection->getQueryBuilder();
1104
-
1105
-		$qb->select('*')
1106
-			->from('share')
1107
-			->where(
1108
-				$qb->expr()->orX(
1109
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1110
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1111
-				)
1112
-			);
1113
-
1114
-		$cursor = $qb->execute();
1115
-		while ($data = $cursor->fetch()) {
1116
-			try {
1117
-				$share = $this->createShareObject($data);
1118
-			} catch (InvalidShare $e) {
1119
-				continue;
1120
-			} catch (ShareNotFound $e) {
1121
-				continue;
1122
-			}
1123
-
1124
-			yield $share;
1125
-		}
1126
-		$cursor->closeCursor();
1127
-	}
501
+        return $share;
502
+    }
503
+
504
+    /**
505
+     * Get all children of this share
506
+     *
507
+     * @param IShare $parent
508
+     * @return IShare[]
509
+     */
510
+    public function getChildren(IShare $parent) {
511
+        $children = [];
512
+
513
+        $qb = $this->dbConnection->getQueryBuilder();
514
+        $qb->select('*')
515
+            ->from('share')
516
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
517
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
518
+            ->orderBy('id');
519
+
520
+        $cursor = $qb->execute();
521
+        while ($data = $cursor->fetch()) {
522
+            $children[] = $this->createShareObject($data);
523
+        }
524
+        $cursor->closeCursor();
525
+
526
+        return $children;
527
+    }
528
+
529
+    /**
530
+     * Delete a share (owner unShares the file)
531
+     *
532
+     * @param IShare $share
533
+     * @throws ShareNotFound
534
+     * @throws \OC\HintException
535
+     */
536
+    public function delete(IShare $share) {
537
+        list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedWith());
538
+
539
+        // if the local user is the owner we can send the unShare request directly...
540
+        if ($this->userManager->userExists($share->getShareOwner())) {
541
+            $this->notifications->sendRemoteUnShare($remote, $share->getId(), $share->getToken());
542
+            $this->revokeShare($share, true);
543
+        } else { // ... if not we need to correct ID for the unShare request
544
+            $remoteId = $this->getRemoteId($share);
545
+            $this->notifications->sendRemoteUnShare($remote, $remoteId, $share->getToken());
546
+            $this->revokeShare($share, false);
547
+        }
548
+
549
+        // only remove the share when all messages are send to not lose information
550
+        // about the share to early
551
+        $this->removeShareFromTable($share);
552
+    }
553
+
554
+    /**
555
+     * in case of a re-share we need to send the other use (initiator or owner)
556
+     * a message that the file was unshared
557
+     *
558
+     * @param IShare $share
559
+     * @param bool $isOwner the user can either be the owner or the user who re-sahred it
560
+     * @throws ShareNotFound
561
+     * @throws \OC\HintException
562
+     */
563
+    protected function revokeShare($share, $isOwner) {
564
+        if ($this->userManager->userExists($share->getShareOwner() && $this->userManager->userExists($share->getSharedBy()))) {
565
+            // If both the owner and the initiator of the share are local users we don't have to notify anybody else
566
+            return;
567
+        }
568
+
569
+        // also send a unShare request to the initiator, if this is a different user than the owner
570
+        if ($share->getShareOwner() !== $share->getSharedBy()) {
571
+            if ($isOwner) {
572
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getSharedBy());
573
+            } else {
574
+                list(, $remote) = $this->addressHandler->splitUserRemote($share->getShareOwner());
575
+            }
576
+            $remoteId = $this->getRemoteId($share);
577
+            $this->notifications->sendRevokeShare($remote, $remoteId, $share->getToken());
578
+        }
579
+    }
580
+
581
+    /**
582
+     * remove share from table
583
+     *
584
+     * @param IShare $share
585
+     */
586
+    public function removeShareFromTable(IShare $share) {
587
+        $this->removeShareFromTableById($share->getId());
588
+    }
589
+
590
+    /**
591
+     * remove share from table
592
+     *
593
+     * @param string $shareId
594
+     */
595
+    private function removeShareFromTableById($shareId) {
596
+        $qb = $this->dbConnection->getQueryBuilder();
597
+        $qb->delete('share')
598
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($shareId)))
599
+            ->andWhere($qb->expr()->neq('share_type', $qb->createNamedParameter(IShare::TYPE_CIRCLE)));
600
+        $qb->execute();
601
+
602
+        $qb->delete('federated_reshares')
603
+            ->where($qb->expr()->eq('share_id', $qb->createNamedParameter($shareId)));
604
+        $qb->execute();
605
+    }
606
+
607
+    /**
608
+     * @inheritdoc
609
+     */
610
+    public function deleteFromSelf(IShare $share, $recipient) {
611
+        // nothing to do here. Technically deleteFromSelf in the context of federated
612
+        // shares is a umount of a external storage. This is handled here
613
+        // apps/files_sharing/lib/external/manager.php
614
+        // TODO move this code over to this app
615
+    }
616
+
617
+    public function restore(IShare $share, string $recipient): IShare {
618
+        throw new GenericShareException('not implemented');
619
+    }
620
+
621
+
622
+    public function getSharesInFolder($userId, Folder $node, $reshares) {
623
+        $qb = $this->dbConnection->getQueryBuilder();
624
+        $qb->select('*')
625
+            ->from('share', 's')
626
+            ->andWhere($qb->expr()->orX(
627
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
628
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
629
+            ))
630
+            ->andWhere(
631
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE))
632
+            );
633
+
634
+        /**
635
+         * Reshares for this user are shares where they are the owner.
636
+         */
637
+        if ($reshares === false) {
638
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
639
+        } else {
640
+            $qb->andWhere(
641
+                $qb->expr()->orX(
642
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
643
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
644
+                )
645
+            );
646
+        }
647
+
648
+        $qb->innerJoin('s', 'filecache' ,'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
649
+        $qb->andWhere($qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())));
650
+
651
+        $qb->orderBy('id');
652
+
653
+        $cursor = $qb->execute();
654
+        $shares = [];
655
+        while ($data = $cursor->fetch()) {
656
+            $shares[$data['fileid']][] = $this->createShareObject($data);
657
+        }
658
+        $cursor->closeCursor();
659
+
660
+        return $shares;
661
+    }
662
+
663
+    /**
664
+     * @inheritdoc
665
+     */
666
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
667
+        $qb = $this->dbConnection->getQueryBuilder();
668
+        $qb->select('*')
669
+            ->from('share');
670
+
671
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
672
+
673
+        /**
674
+         * Reshares for this user are shares where they are the owner.
675
+         */
676
+        if ($reshares === false) {
677
+            //Special case for old shares created via the web UI
678
+            $or1 = $qb->expr()->andX(
679
+                $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
680
+                $qb->expr()->isNull('uid_initiator')
681
+            );
682
+
683
+            $qb->andWhere(
684
+                $qb->expr()->orX(
685
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)),
686
+                    $or1
687
+                )
688
+            );
689
+        } else {
690
+            $qb->andWhere(
691
+                $qb->expr()->orX(
692
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
693
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
694
+                )
695
+            );
696
+        }
697
+
698
+        if ($node !== null) {
699
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
700
+        }
701
+
702
+        if ($limit !== -1) {
703
+            $qb->setMaxResults($limit);
704
+        }
705
+
706
+        $qb->setFirstResult($offset);
707
+        $qb->orderBy('id');
708
+
709
+        $cursor = $qb->execute();
710
+        $shares = [];
711
+        while ($data = $cursor->fetch()) {
712
+            $shares[] = $this->createShareObject($data);
713
+        }
714
+        $cursor->closeCursor();
715
+
716
+        return $shares;
717
+    }
718
+
719
+    /**
720
+     * @inheritdoc
721
+     */
722
+    public function getShareById($id, $recipientId = null) {
723
+        $qb = $this->dbConnection->getQueryBuilder();
724
+
725
+        $qb->select('*')
726
+            ->from('share')
727
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
728
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
729
+
730
+        $cursor = $qb->execute();
731
+        $data = $cursor->fetch();
732
+        $cursor->closeCursor();
733
+
734
+        if ($data === false) {
735
+            throw new ShareNotFound('Can not find share with ID: ' . $id);
736
+        }
737
+
738
+        try {
739
+            $share = $this->createShareObject($data);
740
+        } catch (InvalidShare $e) {
741
+            throw new ShareNotFound();
742
+        }
743
+
744
+        return $share;
745
+    }
746
+
747
+    /**
748
+     * Get shares for a given path
749
+     *
750
+     * @param \OCP\Files\Node $path
751
+     * @return IShare[]
752
+     */
753
+    public function getSharesByPath(Node $path) {
754
+        $qb = $this->dbConnection->getQueryBuilder();
755
+
756
+        // get federated user shares
757
+        $cursor = $qb->select('*')
758
+            ->from('share')
759
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
760
+            ->andWhere($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
761
+            ->execute();
762
+
763
+        $shares = [];
764
+        while ($data = $cursor->fetch()) {
765
+            $shares[] = $this->createShareObject($data);
766
+        }
767
+        $cursor->closeCursor();
768
+
769
+        return $shares;
770
+    }
771
+
772
+    /**
773
+     * @inheritdoc
774
+     */
775
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
776
+        /** @var IShare[] $shares */
777
+        $shares = [];
778
+
779
+        //Get shares directly with this user
780
+        $qb = $this->dbConnection->getQueryBuilder();
781
+        $qb->select('*')
782
+            ->from('share');
783
+
784
+        // Order by id
785
+        $qb->orderBy('id');
786
+
787
+        // Set limit and offset
788
+        if ($limit !== -1) {
789
+            $qb->setMaxResults($limit);
790
+        }
791
+        $qb->setFirstResult($offset);
792
+
793
+        $qb->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)));
794
+        $qb->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)));
795
+
796
+        // Filter by node if provided
797
+        if ($node !== null) {
798
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
799
+        }
800
+
801
+        $cursor = $qb->execute();
802
+
803
+        while ($data = $cursor->fetch()) {
804
+            $shares[] = $this->createShareObject($data);
805
+        }
806
+        $cursor->closeCursor();
807
+
808
+
809
+        return $shares;
810
+    }
811
+
812
+    /**
813
+     * Get a share by token
814
+     *
815
+     * @param string $token
816
+     * @return IShare
817
+     * @throws ShareNotFound
818
+     */
819
+    public function getShareByToken($token) {
820
+        $qb = $this->dbConnection->getQueryBuilder();
821
+
822
+        $cursor = $qb->select('*')
823
+            ->from('share')
824
+            ->where($qb->expr()->in('share_type', $qb->createNamedParameter($this->supportedShareType, IQueryBuilder::PARAM_INT_ARRAY)))
825
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
826
+            ->execute();
827
+
828
+        $data = $cursor->fetch();
829
+
830
+        if ($data === false) {
831
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
832
+        }
833
+
834
+        try {
835
+            $share = $this->createShareObject($data);
836
+        } catch (InvalidShare $e) {
837
+            throw new ShareNotFound('Share not found', $this->l->t('Could not find share'));
838
+        }
839
+
840
+        return $share;
841
+    }
842
+
843
+    /**
844
+     * get database row of a give share
845
+     *
846
+     * @param $id
847
+     * @return array
848
+     * @throws ShareNotFound
849
+     */
850
+    private function getRawShare($id) {
851
+
852
+        // Now fetch the inserted share and create a complete share object
853
+        $qb = $this->dbConnection->getQueryBuilder();
854
+        $qb->select('*')
855
+            ->from('share')
856
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
857
+
858
+        $cursor = $qb->execute();
859
+        $data = $cursor->fetch();
860
+        $cursor->closeCursor();
861
+
862
+        if ($data === false) {
863
+            throw new ShareNotFound;
864
+        }
865
+
866
+        return $data;
867
+    }
868
+
869
+    /**
870
+     * Create a share object from an database row
871
+     *
872
+     * @param array $data
873
+     * @return IShare
874
+     * @throws InvalidShare
875
+     * @throws ShareNotFound
876
+     */
877
+    private function createShareObject($data) {
878
+        $share = new Share($this->rootFolder, $this->userManager);
879
+        $share->setId((int)$data['id'])
880
+            ->setShareType((int)$data['share_type'])
881
+            ->setPermissions((int)$data['permissions'])
882
+            ->setTarget($data['file_target'])
883
+            ->setMailSend((bool)$data['mail_send'])
884
+            ->setToken($data['token']);
885
+
886
+        $shareTime = new \DateTime();
887
+        $shareTime->setTimestamp((int)$data['stime']);
888
+        $share->setShareTime($shareTime);
889
+        $share->setSharedWith($data['share_with']);
890
+
891
+        if ($data['uid_initiator'] !== null) {
892
+            $share->setShareOwner($data['uid_owner']);
893
+            $share->setSharedBy($data['uid_initiator']);
894
+        } else {
895
+            //OLD SHARE
896
+            $share->setSharedBy($data['uid_owner']);
897
+            $path = $this->getNode($share->getSharedBy(), (int)$data['file_source']);
898
+
899
+            $owner = $path->getOwner();
900
+            $share->setShareOwner($owner->getUID());
901
+        }
902
+
903
+        $share->setNodeId((int)$data['file_source']);
904
+        $share->setNodeType($data['item_type']);
905
+
906
+        $share->setProviderId($this->identifier());
907
+
908
+        return $share;
909
+    }
910
+
911
+    /**
912
+     * Get the node with file $id for $user
913
+     *
914
+     * @param string $userId
915
+     * @param int $id
916
+     * @return \OCP\Files\File|\OCP\Files\Folder
917
+     * @throws InvalidShare
918
+     */
919
+    private function getNode($userId, $id) {
920
+        try {
921
+            $userFolder = $this->rootFolder->getUserFolder($userId);
922
+        } catch (NotFoundException $e) {
923
+            throw new InvalidShare();
924
+        }
925
+
926
+        $nodes = $userFolder->getById($id);
927
+
928
+        if (empty($nodes)) {
929
+            throw new InvalidShare();
930
+        }
931
+
932
+        return $nodes[0];
933
+    }
934
+
935
+    /**
936
+     * A user is deleted from the system
937
+     * So clean up the relevant shares.
938
+     *
939
+     * @param string $uid
940
+     * @param int $shareType
941
+     */
942
+    public function userDeleted($uid, $shareType) {
943
+        //TODO: probabaly a good idea to send unshare info to remote servers
944
+
945
+        $qb = $this->dbConnection->getQueryBuilder();
946
+
947
+        $qb->delete('share')
948
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
949
+            ->andWhere($qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)))
950
+            ->execute();
951
+    }
952
+
953
+    /**
954
+     * This provider does not handle groups
955
+     *
956
+     * @param string $gid
957
+     */
958
+    public function groupDeleted($gid) {
959
+        // We don't handle groups here
960
+    }
961
+
962
+    /**
963
+     * This provider does not handle groups
964
+     *
965
+     * @param string $uid
966
+     * @param string $gid
967
+     */
968
+    public function userDeletedFromGroup($uid, $gid) {
969
+        // We don't handle groups here
970
+    }
971
+
972
+    /**
973
+     * check if users from other Nextcloud instances are allowed to mount public links share by this instance
974
+     *
975
+     * @return bool
976
+     */
977
+    public function isOutgoingServer2serverShareEnabled() {
978
+        if ($this->gsConfig->onlyInternalFederation()) {
979
+            return false;
980
+        }
981
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_share_enabled', 'yes');
982
+        return ($result === 'yes');
983
+    }
984
+
985
+    /**
986
+     * check if users are allowed to mount public links from other Nextclouds
987
+     *
988
+     * @return bool
989
+     */
990
+    public function isIncomingServer2serverShareEnabled() {
991
+        if ($this->gsConfig->onlyInternalFederation()) {
992
+            return false;
993
+        }
994
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_share_enabled', 'yes');
995
+        return ($result === 'yes');
996
+    }
997
+
998
+
999
+    /**
1000
+     * check if users from other Nextcloud instances are allowed to send federated group shares
1001
+     *
1002
+     * @return bool
1003
+     */
1004
+    public function isOutgoingServer2serverGroupShareEnabled() {
1005
+        if ($this->gsConfig->onlyInternalFederation()) {
1006
+            return false;
1007
+        }
1008
+        $result = $this->config->getAppValue('files_sharing', 'outgoing_server2server_group_share_enabled', 'no');
1009
+        return ($result === 'yes');
1010
+    }
1011
+
1012
+    /**
1013
+     * check if users are allowed to receive federated group shares
1014
+     *
1015
+     * @return bool
1016
+     */
1017
+    public function isIncomingServer2serverGroupShareEnabled() {
1018
+        if ($this->gsConfig->onlyInternalFederation()) {
1019
+            return false;
1020
+        }
1021
+        $result = $this->config->getAppValue('files_sharing', 'incoming_server2server_group_share_enabled', 'no');
1022
+        return ($result === 'yes');
1023
+    }
1024
+
1025
+    /**
1026
+     * check if federated group sharing is supported, therefore the OCM API need to be enabled
1027
+     *
1028
+     * @return bool
1029
+     */
1030
+    public function isFederatedGroupSharingSupported() {
1031
+        return $this->cloudFederationProviderManager->isReady();
1032
+    }
1033
+
1034
+    /**
1035
+     * Check if querying sharees on the lookup server is enabled
1036
+     *
1037
+     * @return bool
1038
+     */
1039
+    public function isLookupServerQueriesEnabled() {
1040
+        // in a global scale setup we should always query the lookup server
1041
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1042
+            return true;
1043
+        }
1044
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerEnabled', 'yes');
1045
+        return ($result === 'yes');
1046
+    }
1047
+
1048
+
1049
+    /**
1050
+     * Check if it is allowed to publish user specific data to the lookup server
1051
+     *
1052
+     * @return bool
1053
+     */
1054
+    public function isLookupServerUploadEnabled() {
1055
+        // in a global scale setup the admin is responsible to keep the lookup server up-to-date
1056
+        if ($this->gsConfig->isGlobalScaleEnabled()) {
1057
+            return false;
1058
+        }
1059
+        $result = $this->config->getAppValue('files_sharing', 'lookupServerUploadEnabled', 'yes');
1060
+        return ($result === 'yes');
1061
+    }
1062
+
1063
+    /**
1064
+     * @inheritdoc
1065
+     */
1066
+    public function getAccessList($nodes, $currentAccess) {
1067
+        $ids = [];
1068
+        foreach ($nodes as $node) {
1069
+            $ids[] = $node->getId();
1070
+        }
1071
+
1072
+        $qb = $this->dbConnection->getQueryBuilder();
1073
+        $qb->select('share_with', 'token', 'file_source')
1074
+            ->from('share')
1075
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_REMOTE)))
1076
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1077
+            ->andWhere($qb->expr()->orX(
1078
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1079
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1080
+            ));
1081
+        $cursor = $qb->execute();
1082
+
1083
+        if ($currentAccess === false) {
1084
+            $remote = $cursor->fetch() !== false;
1085
+            $cursor->closeCursor();
1086
+
1087
+            return ['remote' => $remote];
1088
+        }
1089
+
1090
+        $remote = [];
1091
+        while ($row = $cursor->fetch()) {
1092
+            $remote[$row['share_with']] = [
1093
+                'node_id' => $row['file_source'],
1094
+                'token' => $row['token'],
1095
+            ];
1096
+        }
1097
+        $cursor->closeCursor();
1098
+
1099
+        return ['remote' => $remote];
1100
+    }
1101
+
1102
+    public function getAllShares(): iterable {
1103
+        $qb = $this->dbConnection->getQueryBuilder();
1104
+
1105
+        $qb->select('*')
1106
+            ->from('share')
1107
+            ->where(
1108
+                $qb->expr()->orX(
1109
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE)),
1110
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_REMOTE_GROUP))
1111
+                )
1112
+            );
1113
+
1114
+        $cursor = $qb->execute();
1115
+        while ($data = $cursor->fetch()) {
1116
+            try {
1117
+                $share = $this->createShareObject($data);
1118
+            } catch (InvalidShare $e) {
1119
+                continue;
1120
+            } catch (ShareNotFound $e) {
1121
+                continue;
1122
+            }
1123
+
1124
+            yield $share;
1125
+        }
1126
+        $cursor->closeCursor();
1127
+    }
1128 1128
 }
Please login to merge, or discard this patch.