Passed
Push — master ( 2eda49...488dde )
by Blizzz
17:26 queued 13s
created
lib/private/Share20/DefaultShareProvider.php 1 patch
Indentation   +1515 added lines, -1515 removed lines patch added patch discarded remove patch
@@ -63,1555 +63,1555 @@
 block discarded – undo
63 63
  * @package OC\Share20
64 64
  */
65 65
 class DefaultShareProvider implements IShareProvider {
66
-	// Special share type for user modified group shares
67
-	public const SHARE_TYPE_USERGROUP = 2;
68
-
69
-	/** @var IDBConnection */
70
-	private $dbConn;
71
-
72
-	/** @var IUserManager */
73
-	private $userManager;
74
-
75
-	/** @var IGroupManager */
76
-	private $groupManager;
77
-
78
-	/** @var IRootFolder */
79
-	private $rootFolder;
80
-
81
-	/** @var IMailer */
82
-	private $mailer;
83
-
84
-	/** @var Defaults */
85
-	private $defaults;
86
-
87
-	/** @var IFactory */
88
-	private $l10nFactory;
89
-
90
-	/** @var IURLGenerator */
91
-	private $urlGenerator;
92
-
93
-	/** @var IConfig */
94
-	private $config;
95
-
96
-	public function __construct(
97
-			IDBConnection $connection,
98
-			IUserManager $userManager,
99
-			IGroupManager $groupManager,
100
-			IRootFolder $rootFolder,
101
-			IMailer $mailer,
102
-			Defaults $defaults,
103
-			IFactory $l10nFactory,
104
-			IURLGenerator $urlGenerator,
105
-			IConfig $config) {
106
-		$this->dbConn = $connection;
107
-		$this->userManager = $userManager;
108
-		$this->groupManager = $groupManager;
109
-		$this->rootFolder = $rootFolder;
110
-		$this->mailer = $mailer;
111
-		$this->defaults = $defaults;
112
-		$this->l10nFactory = $l10nFactory;
113
-		$this->urlGenerator = $urlGenerator;
114
-		$this->config = $config;
115
-	}
116
-
117
-	/**
118
-	 * Return the identifier of this provider.
119
-	 *
120
-	 * @return string Containing only [a-zA-Z0-9]
121
-	 */
122
-	public function identifier() {
123
-		return 'ocinternal';
124
-	}
125
-
126
-	/**
127
-	 * Share a path
128
-	 *
129
-	 * @param \OCP\Share\IShare $share
130
-	 * @return \OCP\Share\IShare The share object
131
-	 * @throws ShareNotFound
132
-	 * @throws \Exception
133
-	 */
134
-	public function create(\OCP\Share\IShare $share) {
135
-		$qb = $this->dbConn->getQueryBuilder();
136
-
137
-		$qb->insert('share');
138
-		$qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
139
-
140
-		if ($share->getShareType() === IShare::TYPE_USER) {
141
-			//Set the UID of the user we share with
142
-			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
143
-			$qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
144
-
145
-			//If an expiration date is set store it
146
-			if ($share->getExpirationDate() !== null) {
147
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
148
-			}
149
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
150
-			//Set the GID of the group we share with
151
-			$qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
152
-
153
-			//If an expiration date is set store it
154
-			if ($share->getExpirationDate() !== null) {
155
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
156
-			}
157
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
158
-			//set label for public link
159
-			$qb->setValue('label', $qb->createNamedParameter($share->getLabel()));
160
-			//Set the token of the share
161
-			$qb->setValue('token', $qb->createNamedParameter($share->getToken()));
162
-
163
-			//If a password is set store it
164
-			if ($share->getPassword() !== null) {
165
-				$qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
166
-			}
167
-
168
-			$qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL));
169
-
170
-			//If an expiration date is set store it
171
-			if ($share->getExpirationDate() !== null) {
172
-				$qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
173
-			}
174
-
175
-			if (method_exists($share, 'getParent')) {
176
-				$qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
177
-			}
178
-
179
-			$qb->setValue('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0, IQueryBuilder::PARAM_INT));
180
-		} else {
181
-			throw new \Exception('invalid share type!');
182
-		}
183
-
184
-		// Set what is shares
185
-		$qb->setValue('item_type', $qb->createParameter('itemType'));
186
-		if ($share->getNode() instanceof \OCP\Files\File) {
187
-			$qb->setParameter('itemType', 'file');
188
-		} else {
189
-			$qb->setParameter('itemType', 'folder');
190
-		}
191
-
192
-		// Set the file id
193
-		$qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
194
-		$qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
195
-
196
-		// set the permissions
197
-		$qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
198
-
199
-		// set share attributes
200
-		$shareAttributes = $this->formatShareAttributes(
201
-			$share->getAttributes()
202
-		);
203
-		$qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
204
-
205
-		// Set who created this share
206
-		$qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
207
-
208
-		// Set who is the owner of this file/folder (and this the owner of the share)
209
-		$qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
210
-
211
-		// Set the file target
212
-		$qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
213
-
214
-		if ($share->getNote() !== '') {
215
-			$qb->setValue('note', $qb->createNamedParameter($share->getNote()));
216
-		}
217
-
218
-		// Set the time this share was created
219
-		$qb->setValue('stime', $qb->createNamedParameter(time()));
220
-
221
-		// insert the data and fetch the id of the share
222
-		$this->dbConn->beginTransaction();
223
-		$qb->execute();
224
-		$id = $this->dbConn->lastInsertId('*PREFIX*share');
225
-
226
-		// Now fetch the inserted share and create a complete share object
227
-		$qb = $this->dbConn->getQueryBuilder();
228
-		$qb->select('*')
229
-			->from('share')
230
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
231
-
232
-		$cursor = $qb->execute();
233
-		$data = $cursor->fetch();
234
-		$this->dbConn->commit();
235
-		$cursor->closeCursor();
236
-
237
-		if ($data === false) {
238
-			throw new ShareNotFound('Newly created share could not be found');
239
-		}
240
-
241
-		$mailSendValue = $share->getMailSend();
242
-		$data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
243
-
244
-		$share = $this->createShare($data);
245
-		return $share;
246
-	}
247
-
248
-	/**
249
-	 * Update a share
250
-	 *
251
-	 * @param \OCP\Share\IShare $share
252
-	 * @return \OCP\Share\IShare The share object
253
-	 * @throws ShareNotFound
254
-	 * @throws \OCP\Files\InvalidPathException
255
-	 * @throws \OCP\Files\NotFoundException
256
-	 */
257
-	public function update(\OCP\Share\IShare $share) {
258
-		$originalShare = $this->getShareById($share->getId());
259
-
260
-		$shareAttributes = $this->formatShareAttributes($share->getAttributes());
261
-
262
-		if ($share->getShareType() === IShare::TYPE_USER) {
263
-			/*
66
+    // Special share type for user modified group shares
67
+    public const SHARE_TYPE_USERGROUP = 2;
68
+
69
+    /** @var IDBConnection */
70
+    private $dbConn;
71
+
72
+    /** @var IUserManager */
73
+    private $userManager;
74
+
75
+    /** @var IGroupManager */
76
+    private $groupManager;
77
+
78
+    /** @var IRootFolder */
79
+    private $rootFolder;
80
+
81
+    /** @var IMailer */
82
+    private $mailer;
83
+
84
+    /** @var Defaults */
85
+    private $defaults;
86
+
87
+    /** @var IFactory */
88
+    private $l10nFactory;
89
+
90
+    /** @var IURLGenerator */
91
+    private $urlGenerator;
92
+
93
+    /** @var IConfig */
94
+    private $config;
95
+
96
+    public function __construct(
97
+            IDBConnection $connection,
98
+            IUserManager $userManager,
99
+            IGroupManager $groupManager,
100
+            IRootFolder $rootFolder,
101
+            IMailer $mailer,
102
+            Defaults $defaults,
103
+            IFactory $l10nFactory,
104
+            IURLGenerator $urlGenerator,
105
+            IConfig $config) {
106
+        $this->dbConn = $connection;
107
+        $this->userManager = $userManager;
108
+        $this->groupManager = $groupManager;
109
+        $this->rootFolder = $rootFolder;
110
+        $this->mailer = $mailer;
111
+        $this->defaults = $defaults;
112
+        $this->l10nFactory = $l10nFactory;
113
+        $this->urlGenerator = $urlGenerator;
114
+        $this->config = $config;
115
+    }
116
+
117
+    /**
118
+     * Return the identifier of this provider.
119
+     *
120
+     * @return string Containing only [a-zA-Z0-9]
121
+     */
122
+    public function identifier() {
123
+        return 'ocinternal';
124
+    }
125
+
126
+    /**
127
+     * Share a path
128
+     *
129
+     * @param \OCP\Share\IShare $share
130
+     * @return \OCP\Share\IShare The share object
131
+     * @throws ShareNotFound
132
+     * @throws \Exception
133
+     */
134
+    public function create(\OCP\Share\IShare $share) {
135
+        $qb = $this->dbConn->getQueryBuilder();
136
+
137
+        $qb->insert('share');
138
+        $qb->setValue('share_type', $qb->createNamedParameter($share->getShareType()));
139
+
140
+        if ($share->getShareType() === IShare::TYPE_USER) {
141
+            //Set the UID of the user we share with
142
+            $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
143
+            $qb->setValue('accepted', $qb->createNamedParameter(IShare::STATUS_PENDING));
144
+
145
+            //If an expiration date is set store it
146
+            if ($share->getExpirationDate() !== null) {
147
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
148
+            }
149
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
150
+            //Set the GID of the group we share with
151
+            $qb->setValue('share_with', $qb->createNamedParameter($share->getSharedWith()));
152
+
153
+            //If an expiration date is set store it
154
+            if ($share->getExpirationDate() !== null) {
155
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
156
+            }
157
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
158
+            //set label for public link
159
+            $qb->setValue('label', $qb->createNamedParameter($share->getLabel()));
160
+            //Set the token of the share
161
+            $qb->setValue('token', $qb->createNamedParameter($share->getToken()));
162
+
163
+            //If a password is set store it
164
+            if ($share->getPassword() !== null) {
165
+                $qb->setValue('password', $qb->createNamedParameter($share->getPassword()));
166
+            }
167
+
168
+            $qb->setValue('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL));
169
+
170
+            //If an expiration date is set store it
171
+            if ($share->getExpirationDate() !== null) {
172
+                $qb->setValue('expiration', $qb->createNamedParameter($share->getExpirationDate(), 'datetime'));
173
+            }
174
+
175
+            if (method_exists($share, 'getParent')) {
176
+                $qb->setValue('parent', $qb->createNamedParameter($share->getParent()));
177
+            }
178
+
179
+            $qb->setValue('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0, IQueryBuilder::PARAM_INT));
180
+        } else {
181
+            throw new \Exception('invalid share type!');
182
+        }
183
+
184
+        // Set what is shares
185
+        $qb->setValue('item_type', $qb->createParameter('itemType'));
186
+        if ($share->getNode() instanceof \OCP\Files\File) {
187
+            $qb->setParameter('itemType', 'file');
188
+        } else {
189
+            $qb->setParameter('itemType', 'folder');
190
+        }
191
+
192
+        // Set the file id
193
+        $qb->setValue('item_source', $qb->createNamedParameter($share->getNode()->getId()));
194
+        $qb->setValue('file_source', $qb->createNamedParameter($share->getNode()->getId()));
195
+
196
+        // set the permissions
197
+        $qb->setValue('permissions', $qb->createNamedParameter($share->getPermissions()));
198
+
199
+        // set share attributes
200
+        $shareAttributes = $this->formatShareAttributes(
201
+            $share->getAttributes()
202
+        );
203
+        $qb->setValue('attributes', $qb->createNamedParameter($shareAttributes));
204
+
205
+        // Set who created this share
206
+        $qb->setValue('uid_initiator', $qb->createNamedParameter($share->getSharedBy()));
207
+
208
+        // Set who is the owner of this file/folder (and this the owner of the share)
209
+        $qb->setValue('uid_owner', $qb->createNamedParameter($share->getShareOwner()));
210
+
211
+        // Set the file target
212
+        $qb->setValue('file_target', $qb->createNamedParameter($share->getTarget()));
213
+
214
+        if ($share->getNote() !== '') {
215
+            $qb->setValue('note', $qb->createNamedParameter($share->getNote()));
216
+        }
217
+
218
+        // Set the time this share was created
219
+        $qb->setValue('stime', $qb->createNamedParameter(time()));
220
+
221
+        // insert the data and fetch the id of the share
222
+        $this->dbConn->beginTransaction();
223
+        $qb->execute();
224
+        $id = $this->dbConn->lastInsertId('*PREFIX*share');
225
+
226
+        // Now fetch the inserted share and create a complete share object
227
+        $qb = $this->dbConn->getQueryBuilder();
228
+        $qb->select('*')
229
+            ->from('share')
230
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)));
231
+
232
+        $cursor = $qb->execute();
233
+        $data = $cursor->fetch();
234
+        $this->dbConn->commit();
235
+        $cursor->closeCursor();
236
+
237
+        if ($data === false) {
238
+            throw new ShareNotFound('Newly created share could not be found');
239
+        }
240
+
241
+        $mailSendValue = $share->getMailSend();
242
+        $data['mail_send'] = ($mailSendValue === null) ? true : $mailSendValue;
243
+
244
+        $share = $this->createShare($data);
245
+        return $share;
246
+    }
247
+
248
+    /**
249
+     * Update a share
250
+     *
251
+     * @param \OCP\Share\IShare $share
252
+     * @return \OCP\Share\IShare The share object
253
+     * @throws ShareNotFound
254
+     * @throws \OCP\Files\InvalidPathException
255
+     * @throws \OCP\Files\NotFoundException
256
+     */
257
+    public function update(\OCP\Share\IShare $share) {
258
+        $originalShare = $this->getShareById($share->getId());
259
+
260
+        $shareAttributes = $this->formatShareAttributes($share->getAttributes());
261
+
262
+        if ($share->getShareType() === IShare::TYPE_USER) {
263
+            /*
264 264
 			 * We allow updating the recipient on user shares.
265 265
 			 */
266
-			$qb = $this->dbConn->getQueryBuilder();
267
-			$qb->update('share')
268
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
269
-				->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
270
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
271
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
272
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
273
-				->set('attributes', $qb->createNamedParameter($shareAttributes))
274
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
275
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
276
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
277
-				->set('note', $qb->createNamedParameter($share->getNote()))
278
-				->set('accepted', $qb->createNamedParameter($share->getStatus()))
279
-				->execute();
280
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
281
-			$qb = $this->dbConn->getQueryBuilder();
282
-			$qb->update('share')
283
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
284
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
285
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
286
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
287
-				->set('attributes', $qb->createNamedParameter($shareAttributes))
288
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
289
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
290
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
291
-				->set('note', $qb->createNamedParameter($share->getNote()))
292
-				->execute();
293
-
294
-			/*
266
+            $qb = $this->dbConn->getQueryBuilder();
267
+            $qb->update('share')
268
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
269
+                ->set('share_with', $qb->createNamedParameter($share->getSharedWith()))
270
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
271
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
272
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
273
+                ->set('attributes', $qb->createNamedParameter($shareAttributes))
274
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
275
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
276
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
277
+                ->set('note', $qb->createNamedParameter($share->getNote()))
278
+                ->set('accepted', $qb->createNamedParameter($share->getStatus()))
279
+                ->execute();
280
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
281
+            $qb = $this->dbConn->getQueryBuilder();
282
+            $qb->update('share')
283
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
284
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
285
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
286
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
287
+                ->set('attributes', $qb->createNamedParameter($shareAttributes))
288
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
289
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
290
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
291
+                ->set('note', $qb->createNamedParameter($share->getNote()))
292
+                ->execute();
293
+
294
+            /*
295 295
 			 * Update all user defined group shares
296 296
 			 */
297
-			$qb = $this->dbConn->getQueryBuilder();
298
-			$qb->update('share')
299
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
300
-				->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
301
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
302
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
303
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
304
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
305
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
306
-				->set('note', $qb->createNamedParameter($share->getNote()))
307
-				->execute();
308
-
309
-			/*
297
+            $qb = $this->dbConn->getQueryBuilder();
298
+            $qb->update('share')
299
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
300
+                ->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
301
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
302
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
303
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
304
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
305
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
306
+                ->set('note', $qb->createNamedParameter($share->getNote()))
307
+                ->execute();
308
+
309
+            /*
310 310
 			 * Now update the permissions for all children that have not set it to 0
311 311
 			 */
312
-			$qb = $this->dbConn->getQueryBuilder();
313
-			$qb->update('share')
314
-				->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
315
-				->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
316
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
317
-				->set('attributes', $qb->createNamedParameter($shareAttributes))
318
-				->execute();
319
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
320
-			$qb = $this->dbConn->getQueryBuilder();
321
-			$qb->update('share')
322
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
323
-				->set('password', $qb->createNamedParameter($share->getPassword()))
324
-				->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
325
-				->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
326
-				->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
327
-				->set('permissions', $qb->createNamedParameter($share->getPermissions()))
328
-				->set('attributes', $qb->createNamedParameter($shareAttributes))
329
-				->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
330
-				->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
331
-				->set('token', $qb->createNamedParameter($share->getToken()))
332
-				->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
333
-				->set('note', $qb->createNamedParameter($share->getNote()))
334
-				->set('label', $qb->createNamedParameter($share->getLabel()))
335
-				->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
336
-				->execute();
337
-		}
338
-
339
-		if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
340
-			$this->propagateNote($share);
341
-		}
342
-
343
-
344
-		return $share;
345
-	}
346
-
347
-	/**
348
-	 * Accept a share.
349
-	 *
350
-	 * @param IShare $share
351
-	 * @param string $recipient
352
-	 * @return IShare The share object
353
-	 * @since 9.0.0
354
-	 */
355
-	public function acceptShare(IShare $share, string $recipient): IShare {
356
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
357
-			$group = $this->groupManager->get($share->getSharedWith());
358
-			$user = $this->userManager->get($recipient);
359
-
360
-			if (is_null($group)) {
361
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
362
-			}
363
-
364
-			if (!$group->inGroup($user)) {
365
-				throw new ProviderException('Recipient not in receiving group');
366
-			}
367
-
368
-			// Try to fetch user specific share
369
-			$qb = $this->dbConn->getQueryBuilder();
370
-			$stmt = $qb->select('*')
371
-				->from('share')
372
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
373
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
374
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
375
-				->andWhere($qb->expr()->orX(
376
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
377
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
378
-				))
379
-				->execute();
380
-
381
-			$data = $stmt->fetch();
382
-			$stmt->closeCursor();
383
-
384
-			/*
312
+            $qb = $this->dbConn->getQueryBuilder();
313
+            $qb->update('share')
314
+                ->where($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
315
+                ->andWhere($qb->expr()->neq('permissions', $qb->createNamedParameter(0)))
316
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
317
+                ->set('attributes', $qb->createNamedParameter($shareAttributes))
318
+                ->execute();
319
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
320
+            $qb = $this->dbConn->getQueryBuilder();
321
+            $qb->update('share')
322
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
323
+                ->set('password', $qb->createNamedParameter($share->getPassword()))
324
+                ->set('password_by_talk', $qb->createNamedParameter($share->getSendPasswordByTalk(), IQueryBuilder::PARAM_BOOL))
325
+                ->set('uid_owner', $qb->createNamedParameter($share->getShareOwner()))
326
+                ->set('uid_initiator', $qb->createNamedParameter($share->getSharedBy()))
327
+                ->set('permissions', $qb->createNamedParameter($share->getPermissions()))
328
+                ->set('attributes', $qb->createNamedParameter($shareAttributes))
329
+                ->set('item_source', $qb->createNamedParameter($share->getNode()->getId()))
330
+                ->set('file_source', $qb->createNamedParameter($share->getNode()->getId()))
331
+                ->set('token', $qb->createNamedParameter($share->getToken()))
332
+                ->set('expiration', $qb->createNamedParameter($share->getExpirationDate(), IQueryBuilder::PARAM_DATE))
333
+                ->set('note', $qb->createNamedParameter($share->getNote()))
334
+                ->set('label', $qb->createNamedParameter($share->getLabel()))
335
+                ->set('hide_download', $qb->createNamedParameter($share->getHideDownload() ? 1 : 0), IQueryBuilder::PARAM_INT)
336
+                ->execute();
337
+        }
338
+
339
+        if ($originalShare->getNote() !== $share->getNote() && $share->getNote() !== '') {
340
+            $this->propagateNote($share);
341
+        }
342
+
343
+
344
+        return $share;
345
+    }
346
+
347
+    /**
348
+     * Accept a share.
349
+     *
350
+     * @param IShare $share
351
+     * @param string $recipient
352
+     * @return IShare The share object
353
+     * @since 9.0.0
354
+     */
355
+    public function acceptShare(IShare $share, string $recipient): IShare {
356
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
357
+            $group = $this->groupManager->get($share->getSharedWith());
358
+            $user = $this->userManager->get($recipient);
359
+
360
+            if (is_null($group)) {
361
+                throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
362
+            }
363
+
364
+            if (!$group->inGroup($user)) {
365
+                throw new ProviderException('Recipient not in receiving group');
366
+            }
367
+
368
+            // Try to fetch user specific share
369
+            $qb = $this->dbConn->getQueryBuilder();
370
+            $stmt = $qb->select('*')
371
+                ->from('share')
372
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
373
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
374
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
375
+                ->andWhere($qb->expr()->orX(
376
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
377
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
378
+                ))
379
+                ->execute();
380
+
381
+            $data = $stmt->fetch();
382
+            $stmt->closeCursor();
383
+
384
+            /*
385 385
 			 * Check if there already is a user specific group share.
386 386
 			 * If there is update it (if required).
387 387
 			 */
388
-			if ($data === false) {
389
-				$id = $this->createUserSpecificGroupShare($share, $recipient);
390
-			} else {
391
-				$id = $data['id'];
392
-			}
393
-		} elseif ($share->getShareType() === IShare::TYPE_USER) {
394
-			if ($share->getSharedWith() !== $recipient) {
395
-				throw new ProviderException('Recipient does not match');
396
-			}
397
-
398
-			$id = $share->getId();
399
-		} else {
400
-			throw new ProviderException('Invalid shareType');
401
-		}
402
-
403
-		$qb = $this->dbConn->getQueryBuilder();
404
-		$qb->update('share')
405
-			->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
406
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
407
-			->execute();
408
-
409
-		return $share;
410
-	}
411
-
412
-	/**
413
-	 * Get all children of this share
414
-	 * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
415
-	 *
416
-	 * @param \OCP\Share\IShare $parent
417
-	 * @return \OCP\Share\IShare[]
418
-	 */
419
-	public function getChildren(\OCP\Share\IShare $parent) {
420
-		$children = [];
421
-
422
-		$qb = $this->dbConn->getQueryBuilder();
423
-		$qb->select('*')
424
-			->from('share')
425
-			->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
426
-			->andWhere(
427
-				$qb->expr()->in(
428
-					'share_type',
429
-					$qb->createNamedParameter([
430
-						IShare::TYPE_USER,
431
-						IShare::TYPE_GROUP,
432
-						IShare::TYPE_LINK,
433
-					], IQueryBuilder::PARAM_INT_ARRAY)
434
-				)
435
-			)
436
-			->andWhere($qb->expr()->orX(
437
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
438
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
439
-			))
440
-			->orderBy('id');
441
-
442
-		$cursor = $qb->execute();
443
-		while ($data = $cursor->fetch()) {
444
-			$children[] = $this->createShare($data);
445
-		}
446
-		$cursor->closeCursor();
447
-
448
-		return $children;
449
-	}
450
-
451
-	/**
452
-	 * Delete a share
453
-	 *
454
-	 * @param \OCP\Share\IShare $share
455
-	 */
456
-	public function delete(\OCP\Share\IShare $share) {
457
-		$qb = $this->dbConn->getQueryBuilder();
458
-		$qb->delete('share')
459
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
460
-
461
-		/*
388
+            if ($data === false) {
389
+                $id = $this->createUserSpecificGroupShare($share, $recipient);
390
+            } else {
391
+                $id = $data['id'];
392
+            }
393
+        } elseif ($share->getShareType() === IShare::TYPE_USER) {
394
+            if ($share->getSharedWith() !== $recipient) {
395
+                throw new ProviderException('Recipient does not match');
396
+            }
397
+
398
+            $id = $share->getId();
399
+        } else {
400
+            throw new ProviderException('Invalid shareType');
401
+        }
402
+
403
+        $qb = $this->dbConn->getQueryBuilder();
404
+        $qb->update('share')
405
+            ->set('accepted', $qb->createNamedParameter(IShare::STATUS_ACCEPTED))
406
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
407
+            ->execute();
408
+
409
+        return $share;
410
+    }
411
+
412
+    /**
413
+     * Get all children of this share
414
+     * FIXME: remove once https://github.com/owncloud/core/pull/21660 is in
415
+     *
416
+     * @param \OCP\Share\IShare $parent
417
+     * @return \OCP\Share\IShare[]
418
+     */
419
+    public function getChildren(\OCP\Share\IShare $parent) {
420
+        $children = [];
421
+
422
+        $qb = $this->dbConn->getQueryBuilder();
423
+        $qb->select('*')
424
+            ->from('share')
425
+            ->where($qb->expr()->eq('parent', $qb->createNamedParameter($parent->getId())))
426
+            ->andWhere(
427
+                $qb->expr()->in(
428
+                    'share_type',
429
+                    $qb->createNamedParameter([
430
+                        IShare::TYPE_USER,
431
+                        IShare::TYPE_GROUP,
432
+                        IShare::TYPE_LINK,
433
+                    ], IQueryBuilder::PARAM_INT_ARRAY)
434
+                )
435
+            )
436
+            ->andWhere($qb->expr()->orX(
437
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
438
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
439
+            ))
440
+            ->orderBy('id');
441
+
442
+        $cursor = $qb->execute();
443
+        while ($data = $cursor->fetch()) {
444
+            $children[] = $this->createShare($data);
445
+        }
446
+        $cursor->closeCursor();
447
+
448
+        return $children;
449
+    }
450
+
451
+    /**
452
+     * Delete a share
453
+     *
454
+     * @param \OCP\Share\IShare $share
455
+     */
456
+    public function delete(\OCP\Share\IShare $share) {
457
+        $qb = $this->dbConn->getQueryBuilder();
458
+        $qb->delete('share')
459
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())));
460
+
461
+        /*
462 462
 		 * If the share is a group share delete all possible
463 463
 		 * user defined groups shares.
464 464
 		 */
465
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
466
-			$qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
467
-		}
468
-
469
-		$qb->execute();
470
-	}
471
-
472
-	/**
473
-	 * Unshare a share from the recipient. If this is a group share
474
-	 * this means we need a special entry in the share db.
475
-	 *
476
-	 * @param IShare $share
477
-	 * @param string $recipient UserId of recipient
478
-	 * @throws BackendError
479
-	 * @throws ProviderException
480
-	 */
481
-	public function deleteFromSelf(IShare $share, $recipient) {
482
-		if ($share->getShareType() === IShare::TYPE_GROUP) {
483
-			$group = $this->groupManager->get($share->getSharedWith());
484
-			$user = $this->userManager->get($recipient);
485
-
486
-			if (is_null($group)) {
487
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
488
-			}
489
-
490
-			if (!$group->inGroup($user)) {
491
-				// nothing left to do
492
-				return;
493
-			}
494
-
495
-			// Try to fetch user specific share
496
-			$qb = $this->dbConn->getQueryBuilder();
497
-			$stmt = $qb->select('*')
498
-				->from('share')
499
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
500
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
501
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
502
-				->andWhere($qb->expr()->orX(
503
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
504
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
505
-				))
506
-				->execute();
507
-
508
-			$data = $stmt->fetch();
509
-
510
-			/*
465
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
466
+            $qb->orWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())));
467
+        }
468
+
469
+        $qb->execute();
470
+    }
471
+
472
+    /**
473
+     * Unshare a share from the recipient. If this is a group share
474
+     * this means we need a special entry in the share db.
475
+     *
476
+     * @param IShare $share
477
+     * @param string $recipient UserId of recipient
478
+     * @throws BackendError
479
+     * @throws ProviderException
480
+     */
481
+    public function deleteFromSelf(IShare $share, $recipient) {
482
+        if ($share->getShareType() === IShare::TYPE_GROUP) {
483
+            $group = $this->groupManager->get($share->getSharedWith());
484
+            $user = $this->userManager->get($recipient);
485
+
486
+            if (is_null($group)) {
487
+                throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
488
+            }
489
+
490
+            if (!$group->inGroup($user)) {
491
+                // nothing left to do
492
+                return;
493
+            }
494
+
495
+            // Try to fetch user specific share
496
+            $qb = $this->dbConn->getQueryBuilder();
497
+            $stmt = $qb->select('*')
498
+                ->from('share')
499
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
500
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
501
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
502
+                ->andWhere($qb->expr()->orX(
503
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
504
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
505
+                ))
506
+                ->execute();
507
+
508
+            $data = $stmt->fetch();
509
+
510
+            /*
511 511
 			 * Check if there already is a user specific group share.
512 512
 			 * If there is update it (if required).
513 513
 			 */
514
-			if ($data === false) {
515
-				$id = $this->createUserSpecificGroupShare($share, $recipient);
516
-				$permissions = $share->getPermissions();
517
-			} else {
518
-				$permissions = $data['permissions'];
519
-				$id = $data['id'];
520
-			}
521
-
522
-			if ($permissions !== 0) {
523
-				// Update existing usergroup share
524
-				$qb = $this->dbConn->getQueryBuilder();
525
-				$qb->update('share')
526
-					->set('permissions', $qb->createNamedParameter(0))
527
-					->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
528
-					->execute();
529
-			}
530
-		} elseif ($share->getShareType() === IShare::TYPE_USER) {
531
-			if ($share->getSharedWith() !== $recipient) {
532
-				throw new ProviderException('Recipient does not match');
533
-			}
534
-
535
-			// We can just delete user and link shares
536
-			$this->delete($share);
537
-		} else {
538
-			throw new ProviderException('Invalid shareType');
539
-		}
540
-	}
541
-
542
-	protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
543
-		$type = $share->getNodeType();
544
-
545
-		$qb = $this->dbConn->getQueryBuilder();
546
-		$qb->insert('share')
547
-			->values([
548
-				'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
549
-				'share_with' => $qb->createNamedParameter($recipient),
550
-				'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
551
-				'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
552
-				'parent' => $qb->createNamedParameter($share->getId()),
553
-				'item_type' => $qb->createNamedParameter($type),
554
-				'item_source' => $qb->createNamedParameter($share->getNodeId()),
555
-				'file_source' => $qb->createNamedParameter($share->getNodeId()),
556
-				'file_target' => $qb->createNamedParameter($share->getTarget()),
557
-				'permissions' => $qb->createNamedParameter($share->getPermissions()),
558
-				'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
559
-			])->execute();
560
-
561
-		return $qb->getLastInsertId();
562
-	}
563
-
564
-	/**
565
-	 * @inheritdoc
566
-	 *
567
-	 * For now this only works for group shares
568
-	 * If this gets implemented for normal shares we have to extend it
569
-	 */
570
-	public function restore(IShare $share, string $recipient): IShare {
571
-		$qb = $this->dbConn->getQueryBuilder();
572
-		$qb->select('permissions')
573
-			->from('share')
574
-			->where(
575
-				$qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
576
-			);
577
-		$cursor = $qb->execute();
578
-		$data = $cursor->fetch();
579
-		$cursor->closeCursor();
580
-
581
-		$originalPermission = $data['permissions'];
582
-
583
-		$qb = $this->dbConn->getQueryBuilder();
584
-		$qb->update('share')
585
-			->set('permissions', $qb->createNamedParameter($originalPermission))
586
-			->where(
587
-				$qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
588
-			)->andWhere(
589
-				$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
590
-			)->andWhere(
591
-				$qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
592
-			);
593
-
594
-		$qb->execute();
595
-
596
-		return $this->getShareById($share->getId(), $recipient);
597
-	}
598
-
599
-	/**
600
-	 * @inheritdoc
601
-	 */
602
-	public function move(\OCP\Share\IShare $share, $recipient) {
603
-		if ($share->getShareType() === IShare::TYPE_USER) {
604
-			// Just update the target
605
-			$qb = $this->dbConn->getQueryBuilder();
606
-			$qb->update('share')
607
-				->set('file_target', $qb->createNamedParameter($share->getTarget()))
608
-				->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
609
-				->execute();
610
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
611
-			// Check if there is a usergroup share
612
-			$qb = $this->dbConn->getQueryBuilder();
613
-			$stmt = $qb->select('id')
614
-				->from('share')
615
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
616
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
617
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
618
-				->andWhere($qb->expr()->orX(
619
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
620
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
621
-				))
622
-				->setMaxResults(1)
623
-				->execute();
624
-
625
-			$data = $stmt->fetch();
626
-			$stmt->closeCursor();
627
-
628
-			$shareAttributes = $this->formatShareAttributes(
629
-				$share->getAttributes()
630
-			);
631
-
632
-			if ($data === false) {
633
-				// No usergroup share yet. Create one.
634
-				$qb = $this->dbConn->getQueryBuilder();
635
-				$qb->insert('share')
636
-					->values([
637
-						'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
638
-						'share_with' => $qb->createNamedParameter($recipient),
639
-						'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
640
-						'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
641
-						'parent' => $qb->createNamedParameter($share->getId()),
642
-						'item_type' => $qb->createNamedParameter($share->getNodeType()),
643
-						'item_source' => $qb->createNamedParameter($share->getNodeId()),
644
-						'file_source' => $qb->createNamedParameter($share->getNodeId()),
645
-						'file_target' => $qb->createNamedParameter($share->getTarget()),
646
-						'permissions' => $qb->createNamedParameter($share->getPermissions()),
647
-						'attributes' => $qb->createNamedParameter($shareAttributes),
648
-						'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
649
-					])->execute();
650
-			} else {
651
-				// Already a usergroup share. Update it.
652
-				$qb = $this->dbConn->getQueryBuilder();
653
-				$qb->update('share')
654
-					->set('file_target', $qb->createNamedParameter($share->getTarget()))
655
-					->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
656
-					->execute();
657
-			}
658
-		}
659
-
660
-		return $share;
661
-	}
662
-
663
-	public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
664
-		$qb = $this->dbConn->getQueryBuilder();
665
-		$qb->select('s.*',
666
-			'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
667
-			'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
668
-			'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum')
669
-			->from('share', 's')
670
-			->andWhere($qb->expr()->orX(
671
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
672
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
673
-			));
674
-
675
-		$qb->andWhere($qb->expr()->orX(
676
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
677
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
678
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
679
-		));
680
-
681
-		/**
682
-		 * Reshares for this user are shares where they are the owner.
683
-		 */
684
-		if ($reshares === false) {
685
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
686
-		} else {
687
-			$qb->andWhere(
688
-				$qb->expr()->orX(
689
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
690
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
691
-				)
692
-			);
693
-		}
694
-
695
-		// todo? maybe get these from the oc_mounts table
696
-		$childMountNodes = array_filter($node->getDirectoryListing(), function (Node $node): bool {
697
-			return $node->getInternalPath() === '';
698
-		});
699
-		$childMountRootIds = array_map(function (Node $node): int {
700
-			return $node->getId();
701
-		}, $childMountNodes);
702
-
703
-		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
704
-		if ($shallow) {
705
-			$qb->andWhere(
706
-				$qb->expr()->orX(
707
-					$qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
708
-					$qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
709
-				)
710
-			);
711
-		} else {
712
-			$qb->andWhere(
713
-				$qb->expr()->orX(
714
-					$qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
715
-					$qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
716
-				)
717
-			);
718
-		}
719
-
720
-		$qb->orderBy('id');
721
-
722
-		$shares = [];
723
-
724
-		$chunks = array_chunk($childMountRootIds, 1000);
725
-
726
-		// Force the request to be run when there is 0 mount.
727
-		if (count($chunks) === 0) {
728
-			$chunks = [[]];
729
-		}
730
-
731
-		foreach ($chunks as $chunk) {
732
-			$qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
733
-			$cursor = $qb->executeQuery();
734
-			while ($data = $cursor->fetch()) {
735
-				$shares[$data['fileid']][] = $this->createShare($data);
736
-			}
737
-			$cursor->closeCursor();
738
-		}
739
-
740
-		return $shares;
741
-	}
742
-
743
-	/**
744
-	 * @inheritdoc
745
-	 */
746
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
747
-		$qb = $this->dbConn->getQueryBuilder();
748
-		$qb->select('*')
749
-			->from('share')
750
-			->andWhere($qb->expr()->orX(
751
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
752
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
753
-			));
754
-
755
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
756
-
757
-		/**
758
-		 * Reshares for this user are shares where they are the owner.
759
-		 */
760
-		if ($reshares === false) {
761
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
762
-		} else {
763
-			if ($node === null) {
764
-				$qb->andWhere(
765
-					$qb->expr()->orX(
766
-						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
767
-						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
768
-					)
769
-				);
770
-			}
771
-		}
772
-
773
-		if ($node !== null) {
774
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
775
-		}
776
-
777
-		if ($limit !== -1) {
778
-			$qb->setMaxResults($limit);
779
-		}
780
-
781
-		$qb->setFirstResult($offset);
782
-		$qb->orderBy('id');
783
-
784
-		$cursor = $qb->execute();
785
-		$shares = [];
786
-		while ($data = $cursor->fetch()) {
787
-			$shares[] = $this->createShare($data);
788
-		}
789
-		$cursor->closeCursor();
790
-
791
-		return $shares;
792
-	}
793
-
794
-	/**
795
-	 * @inheritdoc
796
-	 */
797
-	public function getShareById($id, $recipientId = null) {
798
-		$qb = $this->dbConn->getQueryBuilder();
799
-
800
-		$qb->select('*')
801
-			->from('share')
802
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
803
-			->andWhere(
804
-				$qb->expr()->in(
805
-					'share_type',
806
-					$qb->createNamedParameter([
807
-						IShare::TYPE_USER,
808
-						IShare::TYPE_GROUP,
809
-						IShare::TYPE_LINK,
810
-					], IQueryBuilder::PARAM_INT_ARRAY)
811
-				)
812
-			)
813
-			->andWhere($qb->expr()->orX(
814
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
815
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
816
-			));
817
-
818
-		$cursor = $qb->execute();
819
-		$data = $cursor->fetch();
820
-		$cursor->closeCursor();
821
-
822
-		if ($data === false) {
823
-			throw new ShareNotFound();
824
-		}
825
-
826
-		try {
827
-			$share = $this->createShare($data);
828
-		} catch (InvalidShare $e) {
829
-			throw new ShareNotFound();
830
-		}
831
-
832
-		// If the recipient is set for a group share resolve to that user
833
-		if ($recipientId !== null && $share->getShareType() === IShare::TYPE_GROUP) {
834
-			$share = $this->resolveGroupShares([$share], $recipientId)[0];
835
-		}
836
-
837
-		return $share;
838
-	}
839
-
840
-	/**
841
-	 * Get shares for a given path
842
-	 *
843
-	 * @param \OCP\Files\Node $path
844
-	 * @return \OCP\Share\IShare[]
845
-	 */
846
-	public function getSharesByPath(Node $path) {
847
-		$qb = $this->dbConn->getQueryBuilder();
848
-
849
-		$cursor = $qb->select('*')
850
-			->from('share')
851
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
852
-			->andWhere(
853
-				$qb->expr()->orX(
854
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
855
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
856
-				)
857
-			)
858
-			->andWhere($qb->expr()->orX(
859
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
860
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
861
-			))
862
-			->execute();
863
-
864
-		$shares = [];
865
-		while ($data = $cursor->fetch()) {
866
-			$shares[] = $this->createShare($data);
867
-		}
868
-		$cursor->closeCursor();
869
-
870
-		return $shares;
871
-	}
872
-
873
-	/**
874
-	 * Returns whether the given database result can be interpreted as
875
-	 * a share with accessible file (not trashed, not deleted)
876
-	 */
877
-	private function isAccessibleResult($data) {
878
-		// exclude shares leading to deleted file entries
879
-		if ($data['fileid'] === null || $data['path'] === null) {
880
-			return false;
881
-		}
882
-
883
-		// exclude shares leading to trashbin on home storages
884
-		$pathSections = explode('/', $data['path'], 2);
885
-		// FIXME: would not detect rare md5'd home storage case properly
886
-		if ($pathSections[0] !== 'files'
887
-			&& (strpos($data['storage_string_id'], 'home::') === 0 || strpos($data['storage_string_id'], 'object::user') === 0)) {
888
-			return false;
889
-		} elseif ($pathSections[0] === '__groupfolders'
890
-			&& str_starts_with($pathSections[1], 'trash/')
891
-		) {
892
-			// exclude shares leading to trashbin on group folders storages
893
-			return false;
894
-		}
895
-		return true;
896
-	}
897
-
898
-	/**
899
-	 * @inheritdoc
900
-	 */
901
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
902
-		/** @var Share[] $shares */
903
-		$shares = [];
904
-
905
-		if ($shareType === IShare::TYPE_USER) {
906
-			//Get shares directly with this user
907
-			$qb = $this->dbConn->getQueryBuilder();
908
-			$qb->select('s.*',
909
-				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
910
-				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
911
-				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
912
-			)
913
-				->selectAlias('st.id', 'storage_string_id')
914
-				->from('share', 's')
915
-				->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
916
-				->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
917
-
918
-			// Order by id
919
-			$qb->orderBy('s.id');
920
-
921
-			// Set limit and offset
922
-			if ($limit !== -1) {
923
-				$qb->setMaxResults($limit);
924
-			}
925
-			$qb->setFirstResult($offset);
926
-
927
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
928
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
929
-				->andWhere($qb->expr()->orX(
930
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
931
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
932
-				));
933
-
934
-			// Filter by node if provided
935
-			if ($node !== null) {
936
-				$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
937
-			}
938
-
939
-			$cursor = $qb->execute();
940
-
941
-			while ($data = $cursor->fetch()) {
942
-				if ($data['fileid'] && $data['path'] === null) {
943
-					$data['path'] = (string) $data['path'];
944
-					$data['name'] = (string) $data['name'];
945
-					$data['checksum'] = (string) $data['checksum'];
946
-				}
947
-				if ($this->isAccessibleResult($data)) {
948
-					$shares[] = $this->createShare($data);
949
-				}
950
-			}
951
-			$cursor->closeCursor();
952
-		} elseif ($shareType === IShare::TYPE_GROUP) {
953
-			$user = $this->userManager->get($userId);
954
-			$allGroups = ($user instanceof IUser) ? $this->groupManager->getUserGroupIds($user) : [];
955
-
956
-			/** @var Share[] $shares2 */
957
-			$shares2 = [];
958
-
959
-			$start = 0;
960
-			while (true) {
961
-				$groups = array_slice($allGroups, $start, 1000);
962
-				$start += 1000;
963
-
964
-				if ($groups === []) {
965
-					break;
966
-				}
967
-
968
-				$qb = $this->dbConn->getQueryBuilder();
969
-				$qb->select('s.*',
970
-					'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
971
-					'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
972
-					'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
973
-				)
974
-					->selectAlias('st.id', 'storage_string_id')
975
-					->from('share', 's')
976
-					->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
977
-					->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
978
-					->orderBy('s.id')
979
-					->setFirstResult(0);
980
-
981
-				if ($limit !== -1) {
982
-					$qb->setMaxResults($limit - count($shares));
983
-				}
984
-
985
-				// Filter by node if provided
986
-				if ($node !== null) {
987
-					$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
988
-				}
989
-
990
-
991
-				$groups = array_filter($groups);
992
-
993
-				$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
994
-					->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
995
-						$groups,
996
-						IQueryBuilder::PARAM_STR_ARRAY
997
-					)))
998
-					->andWhere($qb->expr()->orX(
999
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1000
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1001
-					));
1002
-
1003
-				$cursor = $qb->execute();
1004
-				while ($data = $cursor->fetch()) {
1005
-					if ($offset > 0) {
1006
-						$offset--;
1007
-						continue;
1008
-					}
1009
-
1010
-					if ($this->isAccessibleResult($data)) {
1011
-						$shares2[] = $this->createShare($data);
1012
-					}
1013
-				}
1014
-				$cursor->closeCursor();
1015
-			}
1016
-
1017
-			/*
514
+            if ($data === false) {
515
+                $id = $this->createUserSpecificGroupShare($share, $recipient);
516
+                $permissions = $share->getPermissions();
517
+            } else {
518
+                $permissions = $data['permissions'];
519
+                $id = $data['id'];
520
+            }
521
+
522
+            if ($permissions !== 0) {
523
+                // Update existing usergroup share
524
+                $qb = $this->dbConn->getQueryBuilder();
525
+                $qb->update('share')
526
+                    ->set('permissions', $qb->createNamedParameter(0))
527
+                    ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
528
+                    ->execute();
529
+            }
530
+        } elseif ($share->getShareType() === IShare::TYPE_USER) {
531
+            if ($share->getSharedWith() !== $recipient) {
532
+                throw new ProviderException('Recipient does not match');
533
+            }
534
+
535
+            // We can just delete user and link shares
536
+            $this->delete($share);
537
+        } else {
538
+            throw new ProviderException('Invalid shareType');
539
+        }
540
+    }
541
+
542
+    protected function createUserSpecificGroupShare(IShare $share, string $recipient): int {
543
+        $type = $share->getNodeType();
544
+
545
+        $qb = $this->dbConn->getQueryBuilder();
546
+        $qb->insert('share')
547
+            ->values([
548
+                'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
549
+                'share_with' => $qb->createNamedParameter($recipient),
550
+                'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
551
+                'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
552
+                'parent' => $qb->createNamedParameter($share->getId()),
553
+                'item_type' => $qb->createNamedParameter($type),
554
+                'item_source' => $qb->createNamedParameter($share->getNodeId()),
555
+                'file_source' => $qb->createNamedParameter($share->getNodeId()),
556
+                'file_target' => $qb->createNamedParameter($share->getTarget()),
557
+                'permissions' => $qb->createNamedParameter($share->getPermissions()),
558
+                'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
559
+            ])->execute();
560
+
561
+        return $qb->getLastInsertId();
562
+    }
563
+
564
+    /**
565
+     * @inheritdoc
566
+     *
567
+     * For now this only works for group shares
568
+     * If this gets implemented for normal shares we have to extend it
569
+     */
570
+    public function restore(IShare $share, string $recipient): IShare {
571
+        $qb = $this->dbConn->getQueryBuilder();
572
+        $qb->select('permissions')
573
+            ->from('share')
574
+            ->where(
575
+                $qb->expr()->eq('id', $qb->createNamedParameter($share->getId()))
576
+            );
577
+        $cursor = $qb->execute();
578
+        $data = $cursor->fetch();
579
+        $cursor->closeCursor();
580
+
581
+        $originalPermission = $data['permissions'];
582
+
583
+        $qb = $this->dbConn->getQueryBuilder();
584
+        $qb->update('share')
585
+            ->set('permissions', $qb->createNamedParameter($originalPermission))
586
+            ->where(
587
+                $qb->expr()->eq('parent', $qb->createNamedParameter($share->getParent()))
588
+            )->andWhere(
589
+                $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
590
+            )->andWhere(
591
+                $qb->expr()->eq('share_with', $qb->createNamedParameter($recipient))
592
+            );
593
+
594
+        $qb->execute();
595
+
596
+        return $this->getShareById($share->getId(), $recipient);
597
+    }
598
+
599
+    /**
600
+     * @inheritdoc
601
+     */
602
+    public function move(\OCP\Share\IShare $share, $recipient) {
603
+        if ($share->getShareType() === IShare::TYPE_USER) {
604
+            // Just update the target
605
+            $qb = $this->dbConn->getQueryBuilder();
606
+            $qb->update('share')
607
+                ->set('file_target', $qb->createNamedParameter($share->getTarget()))
608
+                ->where($qb->expr()->eq('id', $qb->createNamedParameter($share->getId())))
609
+                ->execute();
610
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
611
+            // Check if there is a usergroup share
612
+            $qb = $this->dbConn->getQueryBuilder();
613
+            $stmt = $qb->select('id')
614
+                ->from('share')
615
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
616
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
617
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
618
+                ->andWhere($qb->expr()->orX(
619
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
620
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
621
+                ))
622
+                ->setMaxResults(1)
623
+                ->execute();
624
+
625
+            $data = $stmt->fetch();
626
+            $stmt->closeCursor();
627
+
628
+            $shareAttributes = $this->formatShareAttributes(
629
+                $share->getAttributes()
630
+            );
631
+
632
+            if ($data === false) {
633
+                // No usergroup share yet. Create one.
634
+                $qb = $this->dbConn->getQueryBuilder();
635
+                $qb->insert('share')
636
+                    ->values([
637
+                        'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
638
+                        'share_with' => $qb->createNamedParameter($recipient),
639
+                        'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
640
+                        'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
641
+                        'parent' => $qb->createNamedParameter($share->getId()),
642
+                        'item_type' => $qb->createNamedParameter($share->getNodeType()),
643
+                        'item_source' => $qb->createNamedParameter($share->getNodeId()),
644
+                        'file_source' => $qb->createNamedParameter($share->getNodeId()),
645
+                        'file_target' => $qb->createNamedParameter($share->getTarget()),
646
+                        'permissions' => $qb->createNamedParameter($share->getPermissions()),
647
+                        'attributes' => $qb->createNamedParameter($shareAttributes),
648
+                        'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
649
+                    ])->execute();
650
+            } else {
651
+                // Already a usergroup share. Update it.
652
+                $qb = $this->dbConn->getQueryBuilder();
653
+                $qb->update('share')
654
+                    ->set('file_target', $qb->createNamedParameter($share->getTarget()))
655
+                    ->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
656
+                    ->execute();
657
+            }
658
+        }
659
+
660
+        return $share;
661
+    }
662
+
663
+    public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
664
+        $qb = $this->dbConn->getQueryBuilder();
665
+        $qb->select('s.*',
666
+            'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
667
+            'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
668
+            'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum')
669
+            ->from('share', 's')
670
+            ->andWhere($qb->expr()->orX(
671
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
672
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
673
+            ));
674
+
675
+        $qb->andWhere($qb->expr()->orX(
676
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
677
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
678
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
679
+        ));
680
+
681
+        /**
682
+         * Reshares for this user are shares where they are the owner.
683
+         */
684
+        if ($reshares === false) {
685
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
686
+        } else {
687
+            $qb->andWhere(
688
+                $qb->expr()->orX(
689
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
690
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
691
+                )
692
+            );
693
+        }
694
+
695
+        // todo? maybe get these from the oc_mounts table
696
+        $childMountNodes = array_filter($node->getDirectoryListing(), function (Node $node): bool {
697
+            return $node->getInternalPath() === '';
698
+        });
699
+        $childMountRootIds = array_map(function (Node $node): int {
700
+            return $node->getId();
701
+        }, $childMountNodes);
702
+
703
+        $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
704
+        if ($shallow) {
705
+            $qb->andWhere(
706
+                $qb->expr()->orX(
707
+                    $qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
708
+                    $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
709
+                )
710
+            );
711
+        } else {
712
+            $qb->andWhere(
713
+                $qb->expr()->orX(
714
+                    $qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
715
+                    $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
716
+                )
717
+            );
718
+        }
719
+
720
+        $qb->orderBy('id');
721
+
722
+        $shares = [];
723
+
724
+        $chunks = array_chunk($childMountRootIds, 1000);
725
+
726
+        // Force the request to be run when there is 0 mount.
727
+        if (count($chunks) === 0) {
728
+            $chunks = [[]];
729
+        }
730
+
731
+        foreach ($chunks as $chunk) {
732
+            $qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
733
+            $cursor = $qb->executeQuery();
734
+            while ($data = $cursor->fetch()) {
735
+                $shares[$data['fileid']][] = $this->createShare($data);
736
+            }
737
+            $cursor->closeCursor();
738
+        }
739
+
740
+        return $shares;
741
+    }
742
+
743
+    /**
744
+     * @inheritdoc
745
+     */
746
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
747
+        $qb = $this->dbConn->getQueryBuilder();
748
+        $qb->select('*')
749
+            ->from('share')
750
+            ->andWhere($qb->expr()->orX(
751
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
752
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
753
+            ));
754
+
755
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
756
+
757
+        /**
758
+         * Reshares for this user are shares where they are the owner.
759
+         */
760
+        if ($reshares === false) {
761
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
762
+        } else {
763
+            if ($node === null) {
764
+                $qb->andWhere(
765
+                    $qb->expr()->orX(
766
+                        $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
767
+                        $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
768
+                    )
769
+                );
770
+            }
771
+        }
772
+
773
+        if ($node !== null) {
774
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
775
+        }
776
+
777
+        if ($limit !== -1) {
778
+            $qb->setMaxResults($limit);
779
+        }
780
+
781
+        $qb->setFirstResult($offset);
782
+        $qb->orderBy('id');
783
+
784
+        $cursor = $qb->execute();
785
+        $shares = [];
786
+        while ($data = $cursor->fetch()) {
787
+            $shares[] = $this->createShare($data);
788
+        }
789
+        $cursor->closeCursor();
790
+
791
+        return $shares;
792
+    }
793
+
794
+    /**
795
+     * @inheritdoc
796
+     */
797
+    public function getShareById($id, $recipientId = null) {
798
+        $qb = $this->dbConn->getQueryBuilder();
799
+
800
+        $qb->select('*')
801
+            ->from('share')
802
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
803
+            ->andWhere(
804
+                $qb->expr()->in(
805
+                    'share_type',
806
+                    $qb->createNamedParameter([
807
+                        IShare::TYPE_USER,
808
+                        IShare::TYPE_GROUP,
809
+                        IShare::TYPE_LINK,
810
+                    ], IQueryBuilder::PARAM_INT_ARRAY)
811
+                )
812
+            )
813
+            ->andWhere($qb->expr()->orX(
814
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
815
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
816
+            ));
817
+
818
+        $cursor = $qb->execute();
819
+        $data = $cursor->fetch();
820
+        $cursor->closeCursor();
821
+
822
+        if ($data === false) {
823
+            throw new ShareNotFound();
824
+        }
825
+
826
+        try {
827
+            $share = $this->createShare($data);
828
+        } catch (InvalidShare $e) {
829
+            throw new ShareNotFound();
830
+        }
831
+
832
+        // If the recipient is set for a group share resolve to that user
833
+        if ($recipientId !== null && $share->getShareType() === IShare::TYPE_GROUP) {
834
+            $share = $this->resolveGroupShares([$share], $recipientId)[0];
835
+        }
836
+
837
+        return $share;
838
+    }
839
+
840
+    /**
841
+     * Get shares for a given path
842
+     *
843
+     * @param \OCP\Files\Node $path
844
+     * @return \OCP\Share\IShare[]
845
+     */
846
+    public function getSharesByPath(Node $path) {
847
+        $qb = $this->dbConn->getQueryBuilder();
848
+
849
+        $cursor = $qb->select('*')
850
+            ->from('share')
851
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
852
+            ->andWhere(
853
+                $qb->expr()->orX(
854
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
855
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
856
+                )
857
+            )
858
+            ->andWhere($qb->expr()->orX(
859
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
860
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
861
+            ))
862
+            ->execute();
863
+
864
+        $shares = [];
865
+        while ($data = $cursor->fetch()) {
866
+            $shares[] = $this->createShare($data);
867
+        }
868
+        $cursor->closeCursor();
869
+
870
+        return $shares;
871
+    }
872
+
873
+    /**
874
+     * Returns whether the given database result can be interpreted as
875
+     * a share with accessible file (not trashed, not deleted)
876
+     */
877
+    private function isAccessibleResult($data) {
878
+        // exclude shares leading to deleted file entries
879
+        if ($data['fileid'] === null || $data['path'] === null) {
880
+            return false;
881
+        }
882
+
883
+        // exclude shares leading to trashbin on home storages
884
+        $pathSections = explode('/', $data['path'], 2);
885
+        // FIXME: would not detect rare md5'd home storage case properly
886
+        if ($pathSections[0] !== 'files'
887
+            && (strpos($data['storage_string_id'], 'home::') === 0 || strpos($data['storage_string_id'], 'object::user') === 0)) {
888
+            return false;
889
+        } elseif ($pathSections[0] === '__groupfolders'
890
+            && str_starts_with($pathSections[1], 'trash/')
891
+        ) {
892
+            // exclude shares leading to trashbin on group folders storages
893
+            return false;
894
+        }
895
+        return true;
896
+    }
897
+
898
+    /**
899
+     * @inheritdoc
900
+     */
901
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
902
+        /** @var Share[] $shares */
903
+        $shares = [];
904
+
905
+        if ($shareType === IShare::TYPE_USER) {
906
+            //Get shares directly with this user
907
+            $qb = $this->dbConn->getQueryBuilder();
908
+            $qb->select('s.*',
909
+                'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
910
+                'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
911
+                'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
912
+            )
913
+                ->selectAlias('st.id', 'storage_string_id')
914
+                ->from('share', 's')
915
+                ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
916
+                ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
917
+
918
+            // Order by id
919
+            $qb->orderBy('s.id');
920
+
921
+            // Set limit and offset
922
+            if ($limit !== -1) {
923
+                $qb->setMaxResults($limit);
924
+            }
925
+            $qb->setFirstResult($offset);
926
+
927
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
928
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
929
+                ->andWhere($qb->expr()->orX(
930
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
931
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
932
+                ));
933
+
934
+            // Filter by node if provided
935
+            if ($node !== null) {
936
+                $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
937
+            }
938
+
939
+            $cursor = $qb->execute();
940
+
941
+            while ($data = $cursor->fetch()) {
942
+                if ($data['fileid'] && $data['path'] === null) {
943
+                    $data['path'] = (string) $data['path'];
944
+                    $data['name'] = (string) $data['name'];
945
+                    $data['checksum'] = (string) $data['checksum'];
946
+                }
947
+                if ($this->isAccessibleResult($data)) {
948
+                    $shares[] = $this->createShare($data);
949
+                }
950
+            }
951
+            $cursor->closeCursor();
952
+        } elseif ($shareType === IShare::TYPE_GROUP) {
953
+            $user = $this->userManager->get($userId);
954
+            $allGroups = ($user instanceof IUser) ? $this->groupManager->getUserGroupIds($user) : [];
955
+
956
+            /** @var Share[] $shares2 */
957
+            $shares2 = [];
958
+
959
+            $start = 0;
960
+            while (true) {
961
+                $groups = array_slice($allGroups, $start, 1000);
962
+                $start += 1000;
963
+
964
+                if ($groups === []) {
965
+                    break;
966
+                }
967
+
968
+                $qb = $this->dbConn->getQueryBuilder();
969
+                $qb->select('s.*',
970
+                    'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
971
+                    'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
972
+                    'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
973
+                )
974
+                    ->selectAlias('st.id', 'storage_string_id')
975
+                    ->from('share', 's')
976
+                    ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
977
+                    ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
978
+                    ->orderBy('s.id')
979
+                    ->setFirstResult(0);
980
+
981
+                if ($limit !== -1) {
982
+                    $qb->setMaxResults($limit - count($shares));
983
+                }
984
+
985
+                // Filter by node if provided
986
+                if ($node !== null) {
987
+                    $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
988
+                }
989
+
990
+
991
+                $groups = array_filter($groups);
992
+
993
+                $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
994
+                    ->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
995
+                        $groups,
996
+                        IQueryBuilder::PARAM_STR_ARRAY
997
+                    )))
998
+                    ->andWhere($qb->expr()->orX(
999
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1000
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1001
+                    ));
1002
+
1003
+                $cursor = $qb->execute();
1004
+                while ($data = $cursor->fetch()) {
1005
+                    if ($offset > 0) {
1006
+                        $offset--;
1007
+                        continue;
1008
+                    }
1009
+
1010
+                    if ($this->isAccessibleResult($data)) {
1011
+                        $shares2[] = $this->createShare($data);
1012
+                    }
1013
+                }
1014
+                $cursor->closeCursor();
1015
+            }
1016
+
1017
+            /*
1018 1018
 			 * Resolve all group shares to user specific shares
1019 1019
 			 */
1020
-			$shares = $this->resolveGroupShares($shares2, $userId);
1021
-		} else {
1022
-			throw new BackendError('Invalid backend');
1023
-		}
1024
-
1025
-
1026
-		return $shares;
1027
-	}
1028
-
1029
-	/**
1030
-	 * Get a share by token
1031
-	 *
1032
-	 * @param string $token
1033
-	 * @return \OCP\Share\IShare
1034
-	 * @throws ShareNotFound
1035
-	 */
1036
-	public function getShareByToken($token) {
1037
-		$qb = $this->dbConn->getQueryBuilder();
1038
-
1039
-		$cursor = $qb->select('*')
1040
-			->from('share')
1041
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)))
1042
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
1043
-			->andWhere($qb->expr()->orX(
1044
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1045
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1046
-			))
1047
-			->execute();
1048
-
1049
-		$data = $cursor->fetch();
1050
-
1051
-		if ($data === false) {
1052
-			throw new ShareNotFound();
1053
-		}
1054
-
1055
-		try {
1056
-			$share = $this->createShare($data);
1057
-		} catch (InvalidShare $e) {
1058
-			throw new ShareNotFound();
1059
-		}
1060
-
1061
-		return $share;
1062
-	}
1063
-
1064
-	/**
1065
-	 * Create a share object from an database row
1066
-	 *
1067
-	 * @param mixed[] $data
1068
-	 * @return \OCP\Share\IShare
1069
-	 * @throws InvalidShare
1070
-	 */
1071
-	private function createShare($data) {
1072
-		$share = new Share($this->rootFolder, $this->userManager);
1073
-		$share->setId((int)$data['id'])
1074
-			->setShareType((int)$data['share_type'])
1075
-			->setPermissions((int)$data['permissions'])
1076
-			->setTarget($data['file_target'])
1077
-			->setNote((string)$data['note'])
1078
-			->setMailSend((bool)$data['mail_send'])
1079
-			->setStatus((int)$data['accepted'])
1080
-			->setLabel($data['label']);
1081
-
1082
-		$shareTime = new \DateTime();
1083
-		$shareTime->setTimestamp((int)$data['stime']);
1084
-		$share->setShareTime($shareTime);
1085
-
1086
-		if ($share->getShareType() === IShare::TYPE_USER) {
1087
-			$share->setSharedWith($data['share_with']);
1088
-			$user = $this->userManager->get($data['share_with']);
1089
-			if ($user !== null) {
1090
-				$share->setSharedWithDisplayName($user->getDisplayName());
1091
-			}
1092
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1093
-			$share->setSharedWith($data['share_with']);
1094
-			$group = $this->groupManager->get($data['share_with']);
1095
-			if ($group !== null) {
1096
-				$share->setSharedWithDisplayName($group->getDisplayName());
1097
-			}
1098
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
1099
-			$share->setPassword($data['password']);
1100
-			$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1101
-			$share->setToken($data['token']);
1102
-		}
1103
-
1104
-		$share = $this->updateShareAttributes($share, $data['attributes']);
1105
-
1106
-		$share->setSharedBy($data['uid_initiator']);
1107
-		$share->setShareOwner($data['uid_owner']);
1108
-
1109
-		$share->setNodeId((int)$data['file_source']);
1110
-		$share->setNodeType($data['item_type']);
1111
-
1112
-		if ($data['expiration'] !== null) {
1113
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1114
-			$share->setExpirationDate($expiration);
1115
-		}
1116
-
1117
-		if (isset($data['f_permissions'])) {
1118
-			$entryData = $data;
1119
-			$entryData['permissions'] = $entryData['f_permissions'];
1120
-			$entryData['parent'] = $entryData['f_parent'];
1121
-			$share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1122
-				\OC::$server->getMimeTypeLoader()));
1123
-		}
1124
-
1125
-		$share->setProviderId($this->identifier());
1126
-		$share->setHideDownload((int)$data['hide_download'] === 1);
1127
-
1128
-		return $share;
1129
-	}
1130
-
1131
-	/**
1132
-	 * @param Share[] $shares
1133
-	 * @param $userId
1134
-	 * @return Share[] The updates shares if no update is found for a share return the original
1135
-	 */
1136
-	private function resolveGroupShares($shares, $userId) {
1137
-		$result = [];
1138
-
1139
-		$start = 0;
1140
-		while (true) {
1141
-			/** @var Share[] $shareSlice */
1142
-			$shareSlice = array_slice($shares, $start, 100);
1143
-			$start += 100;
1144
-
1145
-			if ($shareSlice === []) {
1146
-				break;
1147
-			}
1148
-
1149
-			/** @var int[] $ids */
1150
-			$ids = [];
1151
-			/** @var Share[] $shareMap */
1152
-			$shareMap = [];
1153
-
1154
-			foreach ($shareSlice as $share) {
1155
-				$ids[] = (int)$share->getId();
1156
-				$shareMap[$share->getId()] = $share;
1157
-			}
1158
-
1159
-			$qb = $this->dbConn->getQueryBuilder();
1160
-
1161
-			$query = $qb->select('*')
1162
-				->from('share')
1163
-				->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1164
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1165
-				->andWhere($qb->expr()->orX(
1166
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1167
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1168
-				));
1169
-
1170
-			$stmt = $query->execute();
1171
-
1172
-			while ($data = $stmt->fetch()) {
1173
-				$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1174
-				$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1175
-				$shareMap[$data['parent']]->setTarget($data['file_target']);
1176
-				$shareMap[$data['parent']]->setParent($data['parent']);
1177
-			}
1178
-
1179
-			$stmt->closeCursor();
1180
-
1181
-			foreach ($shareMap as $share) {
1182
-				$result[] = $share;
1183
-			}
1184
-		}
1185
-
1186
-		return $result;
1187
-	}
1188
-
1189
-	/**
1190
-	 * A user is deleted from the system
1191
-	 * So clean up the relevant shares.
1192
-	 *
1193
-	 * @param string $uid
1194
-	 * @param int $shareType
1195
-	 */
1196
-	public function userDeleted($uid, $shareType) {
1197
-		$qb = $this->dbConn->getQueryBuilder();
1198
-
1199
-		$qb->delete('share');
1200
-
1201
-		if ($shareType === IShare::TYPE_USER) {
1202
-			/*
1020
+            $shares = $this->resolveGroupShares($shares2, $userId);
1021
+        } else {
1022
+            throw new BackendError('Invalid backend');
1023
+        }
1024
+
1025
+
1026
+        return $shares;
1027
+    }
1028
+
1029
+    /**
1030
+     * Get a share by token
1031
+     *
1032
+     * @param string $token
1033
+     * @return \OCP\Share\IShare
1034
+     * @throws ShareNotFound
1035
+     */
1036
+    public function getShareByToken($token) {
1037
+        $qb = $this->dbConn->getQueryBuilder();
1038
+
1039
+        $cursor = $qb->select('*')
1040
+            ->from('share')
1041
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)))
1042
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
1043
+            ->andWhere($qb->expr()->orX(
1044
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1045
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1046
+            ))
1047
+            ->execute();
1048
+
1049
+        $data = $cursor->fetch();
1050
+
1051
+        if ($data === false) {
1052
+            throw new ShareNotFound();
1053
+        }
1054
+
1055
+        try {
1056
+            $share = $this->createShare($data);
1057
+        } catch (InvalidShare $e) {
1058
+            throw new ShareNotFound();
1059
+        }
1060
+
1061
+        return $share;
1062
+    }
1063
+
1064
+    /**
1065
+     * Create a share object from an database row
1066
+     *
1067
+     * @param mixed[] $data
1068
+     * @return \OCP\Share\IShare
1069
+     * @throws InvalidShare
1070
+     */
1071
+    private function createShare($data) {
1072
+        $share = new Share($this->rootFolder, $this->userManager);
1073
+        $share->setId((int)$data['id'])
1074
+            ->setShareType((int)$data['share_type'])
1075
+            ->setPermissions((int)$data['permissions'])
1076
+            ->setTarget($data['file_target'])
1077
+            ->setNote((string)$data['note'])
1078
+            ->setMailSend((bool)$data['mail_send'])
1079
+            ->setStatus((int)$data['accepted'])
1080
+            ->setLabel($data['label']);
1081
+
1082
+        $shareTime = new \DateTime();
1083
+        $shareTime->setTimestamp((int)$data['stime']);
1084
+        $share->setShareTime($shareTime);
1085
+
1086
+        if ($share->getShareType() === IShare::TYPE_USER) {
1087
+            $share->setSharedWith($data['share_with']);
1088
+            $user = $this->userManager->get($data['share_with']);
1089
+            if ($user !== null) {
1090
+                $share->setSharedWithDisplayName($user->getDisplayName());
1091
+            }
1092
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1093
+            $share->setSharedWith($data['share_with']);
1094
+            $group = $this->groupManager->get($data['share_with']);
1095
+            if ($group !== null) {
1096
+                $share->setSharedWithDisplayName($group->getDisplayName());
1097
+            }
1098
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
1099
+            $share->setPassword($data['password']);
1100
+            $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1101
+            $share->setToken($data['token']);
1102
+        }
1103
+
1104
+        $share = $this->updateShareAttributes($share, $data['attributes']);
1105
+
1106
+        $share->setSharedBy($data['uid_initiator']);
1107
+        $share->setShareOwner($data['uid_owner']);
1108
+
1109
+        $share->setNodeId((int)$data['file_source']);
1110
+        $share->setNodeType($data['item_type']);
1111
+
1112
+        if ($data['expiration'] !== null) {
1113
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1114
+            $share->setExpirationDate($expiration);
1115
+        }
1116
+
1117
+        if (isset($data['f_permissions'])) {
1118
+            $entryData = $data;
1119
+            $entryData['permissions'] = $entryData['f_permissions'];
1120
+            $entryData['parent'] = $entryData['f_parent'];
1121
+            $share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1122
+                \OC::$server->getMimeTypeLoader()));
1123
+        }
1124
+
1125
+        $share->setProviderId($this->identifier());
1126
+        $share->setHideDownload((int)$data['hide_download'] === 1);
1127
+
1128
+        return $share;
1129
+    }
1130
+
1131
+    /**
1132
+     * @param Share[] $shares
1133
+     * @param $userId
1134
+     * @return Share[] The updates shares if no update is found for a share return the original
1135
+     */
1136
+    private function resolveGroupShares($shares, $userId) {
1137
+        $result = [];
1138
+
1139
+        $start = 0;
1140
+        while (true) {
1141
+            /** @var Share[] $shareSlice */
1142
+            $shareSlice = array_slice($shares, $start, 100);
1143
+            $start += 100;
1144
+
1145
+            if ($shareSlice === []) {
1146
+                break;
1147
+            }
1148
+
1149
+            /** @var int[] $ids */
1150
+            $ids = [];
1151
+            /** @var Share[] $shareMap */
1152
+            $shareMap = [];
1153
+
1154
+            foreach ($shareSlice as $share) {
1155
+                $ids[] = (int)$share->getId();
1156
+                $shareMap[$share->getId()] = $share;
1157
+            }
1158
+
1159
+            $qb = $this->dbConn->getQueryBuilder();
1160
+
1161
+            $query = $qb->select('*')
1162
+                ->from('share')
1163
+                ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1164
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1165
+                ->andWhere($qb->expr()->orX(
1166
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1167
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1168
+                ));
1169
+
1170
+            $stmt = $query->execute();
1171
+
1172
+            while ($data = $stmt->fetch()) {
1173
+                $shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1174
+                $shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1175
+                $shareMap[$data['parent']]->setTarget($data['file_target']);
1176
+                $shareMap[$data['parent']]->setParent($data['parent']);
1177
+            }
1178
+
1179
+            $stmt->closeCursor();
1180
+
1181
+            foreach ($shareMap as $share) {
1182
+                $result[] = $share;
1183
+            }
1184
+        }
1185
+
1186
+        return $result;
1187
+    }
1188
+
1189
+    /**
1190
+     * A user is deleted from the system
1191
+     * So clean up the relevant shares.
1192
+     *
1193
+     * @param string $uid
1194
+     * @param int $shareType
1195
+     */
1196
+    public function userDeleted($uid, $shareType) {
1197
+        $qb = $this->dbConn->getQueryBuilder();
1198
+
1199
+        $qb->delete('share');
1200
+
1201
+        if ($shareType === IShare::TYPE_USER) {
1202
+            /*
1203 1203
 			 * Delete all user shares that are owned by this user
1204 1204
 			 * or that are received by this user
1205 1205
 			 */
1206 1206
 
1207
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)));
1207
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)));
1208 1208
 
1209
-			$qb->andWhere(
1210
-				$qb->expr()->orX(
1211
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1212
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1213
-				)
1214
-			);
1215
-		} elseif ($shareType === IShare::TYPE_GROUP) {
1216
-			/*
1209
+            $qb->andWhere(
1210
+                $qb->expr()->orX(
1211
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1212
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1213
+                )
1214
+            );
1215
+        } elseif ($shareType === IShare::TYPE_GROUP) {
1216
+            /*
1217 1217
 			 * Delete all group shares that are owned by this user
1218 1218
 			 * Or special user group shares that are received by this user
1219 1219
 			 */
1220
-			$qb->where(
1221
-				$qb->expr()->andX(
1222
-					$qb->expr()->orX(
1223
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1224
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
1225
-					),
1226
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1227
-				)
1228
-			);
1229
-
1230
-			$qb->orWhere(
1231
-				$qb->expr()->andX(
1232
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)),
1233
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1234
-				)
1235
-			);
1236
-		} elseif ($shareType === IShare::TYPE_LINK) {
1237
-			/*
1220
+            $qb->where(
1221
+                $qb->expr()->andX(
1222
+                    $qb->expr()->orX(
1223
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1224
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
1225
+                    ),
1226
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1227
+                )
1228
+            );
1229
+
1230
+            $qb->orWhere(
1231
+                $qb->expr()->andX(
1232
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)),
1233
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1234
+                )
1235
+            );
1236
+        } elseif ($shareType === IShare::TYPE_LINK) {
1237
+            /*
1238 1238
 			 * Delete all link shares owned by this user.
1239 1239
 			 * And all link shares initiated by this user (until #22327 is in)
1240 1240
 			 */
1241
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)));
1242
-
1243
-			$qb->andWhere(
1244
-				$qb->expr()->orX(
1245
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1246
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1247
-				)
1248
-			);
1249
-		} else {
1250
-			\OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1251
-			return;
1252
-		}
1253
-
1254
-		$qb->execute();
1255
-	}
1256
-
1257
-	/**
1258
-	 * Delete all shares received by this group. As well as any custom group
1259
-	 * shares for group members.
1260
-	 *
1261
-	 * @param string $gid
1262
-	 */
1263
-	public function groupDeleted($gid) {
1264
-		/*
1241
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)));
1242
+
1243
+            $qb->andWhere(
1244
+                $qb->expr()->orX(
1245
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1246
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1247
+                )
1248
+            );
1249
+        } else {
1250
+            \OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1251
+            return;
1252
+        }
1253
+
1254
+        $qb->execute();
1255
+    }
1256
+
1257
+    /**
1258
+     * Delete all shares received by this group. As well as any custom group
1259
+     * shares for group members.
1260
+     *
1261
+     * @param string $gid
1262
+     */
1263
+    public function groupDeleted($gid) {
1264
+        /*
1265 1265
 		 * First delete all custom group shares for group members
1266 1266
 		 */
1267
-		$qb = $this->dbConn->getQueryBuilder();
1268
-		$qb->select('id')
1269
-			->from('share')
1270
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1271
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1272
-
1273
-		$cursor = $qb->execute();
1274
-		$ids = [];
1275
-		while ($row = $cursor->fetch()) {
1276
-			$ids[] = (int)$row['id'];
1277
-		}
1278
-		$cursor->closeCursor();
1279
-
1280
-		if (!empty($ids)) {
1281
-			$chunks = array_chunk($ids, 100);
1282
-			foreach ($chunks as $chunk) {
1283
-				$qb->delete('share')
1284
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1285
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1286
-				$qb->execute();
1287
-			}
1288
-		}
1289
-
1290
-		/*
1267
+        $qb = $this->dbConn->getQueryBuilder();
1268
+        $qb->select('id')
1269
+            ->from('share')
1270
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1271
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1272
+
1273
+        $cursor = $qb->execute();
1274
+        $ids = [];
1275
+        while ($row = $cursor->fetch()) {
1276
+            $ids[] = (int)$row['id'];
1277
+        }
1278
+        $cursor->closeCursor();
1279
+
1280
+        if (!empty($ids)) {
1281
+            $chunks = array_chunk($ids, 100);
1282
+            foreach ($chunks as $chunk) {
1283
+                $qb->delete('share')
1284
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1285
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1286
+                $qb->execute();
1287
+            }
1288
+        }
1289
+
1290
+        /*
1291 1291
 		 * Now delete all the group shares
1292 1292
 		 */
1293
-		$qb = $this->dbConn->getQueryBuilder();
1294
-		$qb->delete('share')
1295
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1296
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1297
-		$qb->execute();
1298
-	}
1299
-
1300
-	/**
1301
-	 * Delete custom group shares to this group for this user
1302
-	 *
1303
-	 * @param string $uid
1304
-	 * @param string $gid
1305
-	 */
1306
-	public function userDeletedFromGroup($uid, $gid) {
1307
-		/*
1293
+        $qb = $this->dbConn->getQueryBuilder();
1294
+        $qb->delete('share')
1295
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1296
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1297
+        $qb->execute();
1298
+    }
1299
+
1300
+    /**
1301
+     * Delete custom group shares to this group for this user
1302
+     *
1303
+     * @param string $uid
1304
+     * @param string $gid
1305
+     */
1306
+    public function userDeletedFromGroup($uid, $gid) {
1307
+        /*
1308 1308
 		 * Get all group shares
1309 1309
 		 */
1310
-		$qb = $this->dbConn->getQueryBuilder();
1311
-		$qb->select('id')
1312
-			->from('share')
1313
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1314
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1315
-
1316
-		$cursor = $qb->execute();
1317
-		$ids = [];
1318
-		while ($row = $cursor->fetch()) {
1319
-			$ids[] = (int)$row['id'];
1320
-		}
1321
-		$cursor->closeCursor();
1322
-
1323
-		if (!empty($ids)) {
1324
-			$chunks = array_chunk($ids, 100);
1325
-			foreach ($chunks as $chunk) {
1326
-				/*
1310
+        $qb = $this->dbConn->getQueryBuilder();
1311
+        $qb->select('id')
1312
+            ->from('share')
1313
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1314
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1315
+
1316
+        $cursor = $qb->execute();
1317
+        $ids = [];
1318
+        while ($row = $cursor->fetch()) {
1319
+            $ids[] = (int)$row['id'];
1320
+        }
1321
+        $cursor->closeCursor();
1322
+
1323
+        if (!empty($ids)) {
1324
+            $chunks = array_chunk($ids, 100);
1325
+            foreach ($chunks as $chunk) {
1326
+                /*
1327 1327
 				 * Delete all special shares with this users for the found group shares
1328 1328
 				 */
1329
-				$qb->delete('share')
1330
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1331
-					->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1332
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1333
-				$qb->execute();
1334
-			}
1335
-		}
1336
-	}
1337
-
1338
-	/**
1339
-	 * @inheritdoc
1340
-	 */
1341
-	public function getAccessList($nodes, $currentAccess) {
1342
-		$ids = [];
1343
-		foreach ($nodes as $node) {
1344
-			$ids[] = $node->getId();
1345
-		}
1346
-
1347
-		$qb = $this->dbConn->getQueryBuilder();
1348
-
1349
-		$or = $qb->expr()->orX(
1350
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
1351
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1352
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
1353
-		);
1354
-
1355
-		if ($currentAccess) {
1356
-			$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)));
1357
-		}
1358
-
1359
-		$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1360
-			->from('share')
1361
-			->where(
1362
-				$or
1363
-			)
1364
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1365
-			->andWhere($qb->expr()->orX(
1366
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1367
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1368
-			));
1369
-		$cursor = $qb->execute();
1370
-
1371
-		$users = [];
1372
-		$link = false;
1373
-		while ($row = $cursor->fetch()) {
1374
-			$type = (int)$row['share_type'];
1375
-			if ($type === IShare::TYPE_USER) {
1376
-				$uid = $row['share_with'];
1377
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1378
-				$users[$uid][$row['id']] = $row;
1379
-			} elseif ($type === IShare::TYPE_GROUP) {
1380
-				$gid = $row['share_with'];
1381
-				$group = $this->groupManager->get($gid);
1382
-
1383
-				if ($group === null) {
1384
-					continue;
1385
-				}
1386
-
1387
-				$userList = $group->getUsers();
1388
-				foreach ($userList as $user) {
1389
-					$uid = $user->getUID();
1390
-					$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1391
-					$users[$uid][$row['id']] = $row;
1392
-				}
1393
-			} elseif ($type === IShare::TYPE_LINK) {
1394
-				$link = true;
1395
-			} elseif ($type === IShare::TYPE_USERGROUP && $currentAccess === true) {
1396
-				$uid = $row['share_with'];
1397
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1398
-				$users[$uid][$row['id']] = $row;
1399
-			}
1400
-		}
1401
-		$cursor->closeCursor();
1402
-
1403
-		if ($currentAccess === true) {
1404
-			$users = array_map([$this, 'filterSharesOfUser'], $users);
1405
-			$users = array_filter($users);
1406
-		} else {
1407
-			$users = array_keys($users);
1408
-		}
1409
-
1410
-		return ['users' => $users, 'public' => $link];
1411
-	}
1412
-
1413
-	/**
1414
-	 * For each user the path with the fewest slashes is returned
1415
-	 * @param array $shares
1416
-	 * @return array
1417
-	 */
1418
-	protected function filterSharesOfUser(array $shares) {
1419
-		// Group shares when the user has a share exception
1420
-		foreach ($shares as $id => $share) {
1421
-			$type = (int) $share['share_type'];
1422
-			$permissions = (int) $share['permissions'];
1423
-
1424
-			if ($type === IShare::TYPE_USERGROUP) {
1425
-				unset($shares[$share['parent']]);
1426
-
1427
-				if ($permissions === 0) {
1428
-					unset($shares[$id]);
1429
-				}
1430
-			}
1431
-		}
1432
-
1433
-		$best = [];
1434
-		$bestDepth = 0;
1435
-		foreach ($shares as $id => $share) {
1436
-			$depth = substr_count(($share['file_target'] ?? ''), '/');
1437
-			if (empty($best) || $depth < $bestDepth) {
1438
-				$bestDepth = $depth;
1439
-				$best = [
1440
-					'node_id' => $share['file_source'],
1441
-					'node_path' => $share['file_target'],
1442
-				];
1443
-			}
1444
-		}
1445
-
1446
-		return $best;
1447
-	}
1448
-
1449
-	/**
1450
-	 * propagate notes to the recipients
1451
-	 *
1452
-	 * @param IShare $share
1453
-	 * @throws \OCP\Files\NotFoundException
1454
-	 */
1455
-	private function propagateNote(IShare $share) {
1456
-		if ($share->getShareType() === IShare::TYPE_USER) {
1457
-			$user = $this->userManager->get($share->getSharedWith());
1458
-			$this->sendNote([$user], $share);
1459
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1460
-			$group = $this->groupManager->get($share->getSharedWith());
1461
-			$groupMembers = $group->getUsers();
1462
-			$this->sendNote($groupMembers, $share);
1463
-		}
1464
-	}
1465
-
1466
-	/**
1467
-	 * send note by mail
1468
-	 *
1469
-	 * @param array $recipients
1470
-	 * @param IShare $share
1471
-	 * @throws \OCP\Files\NotFoundException
1472
-	 */
1473
-	private function sendNote(array $recipients, IShare $share) {
1474
-		$toListByLanguage = [];
1475
-
1476
-		foreach ($recipients as $recipient) {
1477
-			/** @var IUser $recipient */
1478
-			$email = $recipient->getEMailAddress();
1479
-			if ($email) {
1480
-				$language = $this->l10nFactory->getUserLanguage($recipient);
1481
-				if (!isset($toListByLanguage[$language])) {
1482
-					$toListByLanguage[$language] = [];
1483
-				}
1484
-				$toListByLanguage[$language][$email] = $recipient->getDisplayName();
1485
-			}
1486
-		}
1487
-
1488
-		if (empty($toListByLanguage)) {
1489
-			return;
1490
-		}
1491
-
1492
-		foreach ($toListByLanguage as $l10n => $toList) {
1493
-			$filename = $share->getNode()->getName();
1494
-			$initiator = $share->getSharedBy();
1495
-			$note = $share->getNote();
1496
-
1497
-			$l = $this->l10nFactory->get('lib', $l10n);
1498
-
1499
-			$initiatorUser = $this->userManager->get($initiator);
1500
-			$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1501
-			$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1502
-			$plainHeading = $l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1503
-			$htmlHeading = $l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1504
-			$message = $this->mailer->createMessage();
1505
-
1506
-			$emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1507
-
1508
-			$emailTemplate->setSubject($l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1509
-			$emailTemplate->addHeader();
1510
-			$emailTemplate->addHeading($htmlHeading, $plainHeading);
1511
-			$emailTemplate->addBodyText(htmlspecialchars($note), $note);
1512
-
1513
-			$link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1514
-			$emailTemplate->addBodyButton(
1515
-				$l->t('Open »%s«', [$filename]),
1516
-				$link
1517
-			);
1518
-
1519
-
1520
-			// The "From" contains the sharers name
1521
-			$instanceName = $this->defaults->getName();
1522
-			$senderName = $l->t(
1523
-				'%1$s via %2$s',
1524
-				[
1525
-					$initiatorDisplayName,
1526
-					$instanceName
1527
-				]
1528
-			);
1529
-			$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1530
-			if ($initiatorEmailAddress !== null) {
1531
-				$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1532
-				$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1533
-			} else {
1534
-				$emailTemplate->addFooter();
1535
-			}
1536
-
1537
-			if (count($toList) === 1) {
1538
-				$message->setTo($toList);
1539
-			} else {
1540
-				$message->setTo([]);
1541
-				$message->setBcc($toList);
1542
-			}
1543
-			$message->useTemplate($emailTemplate);
1544
-			$this->mailer->send($message);
1545
-		}
1546
-	}
1547
-
1548
-	public function getAllShares(): iterable {
1549
-		$qb = $this->dbConn->getQueryBuilder();
1550
-
1551
-		$qb->select('*')
1552
-			->from('share')
1553
-			->where(
1554
-				$qb->expr()->orX(
1555
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1556
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1557
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1558
-				)
1559
-			);
1560
-
1561
-		$cursor = $qb->execute();
1562
-		while ($data = $cursor->fetch()) {
1563
-			try {
1564
-				$share = $this->createShare($data);
1565
-			} catch (InvalidShare $e) {
1566
-				continue;
1567
-			}
1568
-
1569
-			yield $share;
1570
-		}
1571
-		$cursor->closeCursor();
1572
-	}
1573
-
1574
-	/**
1575
-	 * Load from database format (JSON string) to IAttributes
1576
-	 *
1577
-	 * @return IShare the modified share
1578
-	 */
1579
-	private function updateShareAttributes(IShare $share, ?string $data): IShare {
1580
-		if ($data !== null && $data !== '') {
1581
-			$attributes = new ShareAttributes();
1582
-			$compressedAttributes = \json_decode($data, true);
1583
-			if ($compressedAttributes === false || $compressedAttributes === null) {
1584
-				return $share;
1585
-			}
1586
-			foreach ($compressedAttributes as $compressedAttribute) {
1587
-				$attributes->setAttribute(
1588
-					$compressedAttribute[0],
1589
-					$compressedAttribute[1],
1590
-					$compressedAttribute[2]
1591
-				);
1592
-			}
1593
-			$share->setAttributes($attributes);
1594
-		}
1595
-
1596
-		return $share;
1597
-	}
1598
-
1599
-	/**
1600
-	 * Format IAttributes to database format (JSON string)
1601
-	 */
1602
-	private function formatShareAttributes(?IAttributes $attributes): ?string {
1603
-		if ($attributes === null || empty($attributes->toArray())) {
1604
-			return null;
1605
-		}
1606
-
1607
-		$compressedAttributes = [];
1608
-		foreach ($attributes->toArray() as $attribute) {
1609
-			$compressedAttributes[] = [
1610
-				0 => $attribute['scope'],
1611
-				1 => $attribute['key'],
1612
-				2 => $attribute['enabled']
1613
-			];
1614
-		}
1615
-		return \json_encode($compressedAttributes);
1616
-	}
1329
+                $qb->delete('share')
1330
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1331
+                    ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1332
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1333
+                $qb->execute();
1334
+            }
1335
+        }
1336
+    }
1337
+
1338
+    /**
1339
+     * @inheritdoc
1340
+     */
1341
+    public function getAccessList($nodes, $currentAccess) {
1342
+        $ids = [];
1343
+        foreach ($nodes as $node) {
1344
+            $ids[] = $node->getId();
1345
+        }
1346
+
1347
+        $qb = $this->dbConn->getQueryBuilder();
1348
+
1349
+        $or = $qb->expr()->orX(
1350
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
1351
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1352
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
1353
+        );
1354
+
1355
+        if ($currentAccess) {
1356
+            $or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)));
1357
+        }
1358
+
1359
+        $qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1360
+            ->from('share')
1361
+            ->where(
1362
+                $or
1363
+            )
1364
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1365
+            ->andWhere($qb->expr()->orX(
1366
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1367
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1368
+            ));
1369
+        $cursor = $qb->execute();
1370
+
1371
+        $users = [];
1372
+        $link = false;
1373
+        while ($row = $cursor->fetch()) {
1374
+            $type = (int)$row['share_type'];
1375
+            if ($type === IShare::TYPE_USER) {
1376
+                $uid = $row['share_with'];
1377
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1378
+                $users[$uid][$row['id']] = $row;
1379
+            } elseif ($type === IShare::TYPE_GROUP) {
1380
+                $gid = $row['share_with'];
1381
+                $group = $this->groupManager->get($gid);
1382
+
1383
+                if ($group === null) {
1384
+                    continue;
1385
+                }
1386
+
1387
+                $userList = $group->getUsers();
1388
+                foreach ($userList as $user) {
1389
+                    $uid = $user->getUID();
1390
+                    $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1391
+                    $users[$uid][$row['id']] = $row;
1392
+                }
1393
+            } elseif ($type === IShare::TYPE_LINK) {
1394
+                $link = true;
1395
+            } elseif ($type === IShare::TYPE_USERGROUP && $currentAccess === true) {
1396
+                $uid = $row['share_with'];
1397
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1398
+                $users[$uid][$row['id']] = $row;
1399
+            }
1400
+        }
1401
+        $cursor->closeCursor();
1402
+
1403
+        if ($currentAccess === true) {
1404
+            $users = array_map([$this, 'filterSharesOfUser'], $users);
1405
+            $users = array_filter($users);
1406
+        } else {
1407
+            $users = array_keys($users);
1408
+        }
1409
+
1410
+        return ['users' => $users, 'public' => $link];
1411
+    }
1412
+
1413
+    /**
1414
+     * For each user the path with the fewest slashes is returned
1415
+     * @param array $shares
1416
+     * @return array
1417
+     */
1418
+    protected function filterSharesOfUser(array $shares) {
1419
+        // Group shares when the user has a share exception
1420
+        foreach ($shares as $id => $share) {
1421
+            $type = (int) $share['share_type'];
1422
+            $permissions = (int) $share['permissions'];
1423
+
1424
+            if ($type === IShare::TYPE_USERGROUP) {
1425
+                unset($shares[$share['parent']]);
1426
+
1427
+                if ($permissions === 0) {
1428
+                    unset($shares[$id]);
1429
+                }
1430
+            }
1431
+        }
1432
+
1433
+        $best = [];
1434
+        $bestDepth = 0;
1435
+        foreach ($shares as $id => $share) {
1436
+            $depth = substr_count(($share['file_target'] ?? ''), '/');
1437
+            if (empty($best) || $depth < $bestDepth) {
1438
+                $bestDepth = $depth;
1439
+                $best = [
1440
+                    'node_id' => $share['file_source'],
1441
+                    'node_path' => $share['file_target'],
1442
+                ];
1443
+            }
1444
+        }
1445
+
1446
+        return $best;
1447
+    }
1448
+
1449
+    /**
1450
+     * propagate notes to the recipients
1451
+     *
1452
+     * @param IShare $share
1453
+     * @throws \OCP\Files\NotFoundException
1454
+     */
1455
+    private function propagateNote(IShare $share) {
1456
+        if ($share->getShareType() === IShare::TYPE_USER) {
1457
+            $user = $this->userManager->get($share->getSharedWith());
1458
+            $this->sendNote([$user], $share);
1459
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1460
+            $group = $this->groupManager->get($share->getSharedWith());
1461
+            $groupMembers = $group->getUsers();
1462
+            $this->sendNote($groupMembers, $share);
1463
+        }
1464
+    }
1465
+
1466
+    /**
1467
+     * send note by mail
1468
+     *
1469
+     * @param array $recipients
1470
+     * @param IShare $share
1471
+     * @throws \OCP\Files\NotFoundException
1472
+     */
1473
+    private function sendNote(array $recipients, IShare $share) {
1474
+        $toListByLanguage = [];
1475
+
1476
+        foreach ($recipients as $recipient) {
1477
+            /** @var IUser $recipient */
1478
+            $email = $recipient->getEMailAddress();
1479
+            if ($email) {
1480
+                $language = $this->l10nFactory->getUserLanguage($recipient);
1481
+                if (!isset($toListByLanguage[$language])) {
1482
+                    $toListByLanguage[$language] = [];
1483
+                }
1484
+                $toListByLanguage[$language][$email] = $recipient->getDisplayName();
1485
+            }
1486
+        }
1487
+
1488
+        if (empty($toListByLanguage)) {
1489
+            return;
1490
+        }
1491
+
1492
+        foreach ($toListByLanguage as $l10n => $toList) {
1493
+            $filename = $share->getNode()->getName();
1494
+            $initiator = $share->getSharedBy();
1495
+            $note = $share->getNote();
1496
+
1497
+            $l = $this->l10nFactory->get('lib', $l10n);
1498
+
1499
+            $initiatorUser = $this->userManager->get($initiator);
1500
+            $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1501
+            $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1502
+            $plainHeading = $l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1503
+            $htmlHeading = $l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1504
+            $message = $this->mailer->createMessage();
1505
+
1506
+            $emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1507
+
1508
+            $emailTemplate->setSubject($l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1509
+            $emailTemplate->addHeader();
1510
+            $emailTemplate->addHeading($htmlHeading, $plainHeading);
1511
+            $emailTemplate->addBodyText(htmlspecialchars($note), $note);
1512
+
1513
+            $link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1514
+            $emailTemplate->addBodyButton(
1515
+                $l->t('Open »%s«', [$filename]),
1516
+                $link
1517
+            );
1518
+
1519
+
1520
+            // The "From" contains the sharers name
1521
+            $instanceName = $this->defaults->getName();
1522
+            $senderName = $l->t(
1523
+                '%1$s via %2$s',
1524
+                [
1525
+                    $initiatorDisplayName,
1526
+                    $instanceName
1527
+                ]
1528
+            );
1529
+            $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1530
+            if ($initiatorEmailAddress !== null) {
1531
+                $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1532
+                $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1533
+            } else {
1534
+                $emailTemplate->addFooter();
1535
+            }
1536
+
1537
+            if (count($toList) === 1) {
1538
+                $message->setTo($toList);
1539
+            } else {
1540
+                $message->setTo([]);
1541
+                $message->setBcc($toList);
1542
+            }
1543
+            $message->useTemplate($emailTemplate);
1544
+            $this->mailer->send($message);
1545
+        }
1546
+    }
1547
+
1548
+    public function getAllShares(): iterable {
1549
+        $qb = $this->dbConn->getQueryBuilder();
1550
+
1551
+        $qb->select('*')
1552
+            ->from('share')
1553
+            ->where(
1554
+                $qb->expr()->orX(
1555
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1556
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1557
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1558
+                )
1559
+            );
1560
+
1561
+        $cursor = $qb->execute();
1562
+        while ($data = $cursor->fetch()) {
1563
+            try {
1564
+                $share = $this->createShare($data);
1565
+            } catch (InvalidShare $e) {
1566
+                continue;
1567
+            }
1568
+
1569
+            yield $share;
1570
+        }
1571
+        $cursor->closeCursor();
1572
+    }
1573
+
1574
+    /**
1575
+     * Load from database format (JSON string) to IAttributes
1576
+     *
1577
+     * @return IShare the modified share
1578
+     */
1579
+    private function updateShareAttributes(IShare $share, ?string $data): IShare {
1580
+        if ($data !== null && $data !== '') {
1581
+            $attributes = new ShareAttributes();
1582
+            $compressedAttributes = \json_decode($data, true);
1583
+            if ($compressedAttributes === false || $compressedAttributes === null) {
1584
+                return $share;
1585
+            }
1586
+            foreach ($compressedAttributes as $compressedAttribute) {
1587
+                $attributes->setAttribute(
1588
+                    $compressedAttribute[0],
1589
+                    $compressedAttribute[1],
1590
+                    $compressedAttribute[2]
1591
+                );
1592
+            }
1593
+            $share->setAttributes($attributes);
1594
+        }
1595
+
1596
+        return $share;
1597
+    }
1598
+
1599
+    /**
1600
+     * Format IAttributes to database format (JSON string)
1601
+     */
1602
+    private function formatShareAttributes(?IAttributes $attributes): ?string {
1603
+        if ($attributes === null || empty($attributes->toArray())) {
1604
+            return null;
1605
+        }
1606
+
1607
+        $compressedAttributes = [];
1608
+        foreach ($attributes->toArray() as $attribute) {
1609
+            $compressedAttributes[] = [
1610
+                0 => $attribute['scope'],
1611
+                1 => $attribute['key'],
1612
+                2 => $attribute['enabled']
1613
+            ];
1614
+        }
1615
+        return \json_encode($compressedAttributes);
1616
+    }
1617 1617
 }
Please login to merge, or discard this patch.