Passed
Push — master ( 21576f...2f7a1f )
by Joas
13:04 queued 12s
created
lib/private/Share20/DefaultShareProvider.php 2 patches
Indentation   +1511 added lines, -1511 removed lines patch added patch discarded remove patch
@@ -63,1551 +63,1551 @@
 block discarded – undo
63 63
  */
64 64
 class DefaultShareProvider implements IShareProvider {
65 65
 
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
-
612
-			// Check if there is a usergroup share
613
-			$qb = $this->dbConn->getQueryBuilder();
614
-			$stmt = $qb->select('id')
615
-				->from('share')
616
-				->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
617
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
618
-				->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
619
-				->andWhere($qb->expr()->orX(
620
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
621
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
622
-				))
623
-				->setMaxResults(1)
624
-				->execute();
625
-
626
-			$data = $stmt->fetch();
627
-			$stmt->closeCursor();
628
-
629
-			$shareAttributes = $this->formatShareAttributes(
630
-				$share->getAttributes()
631
-			);
632
-
633
-			if ($data === false) {
634
-				// No usergroup share yet. Create one.
635
-				$qb = $this->dbConn->getQueryBuilder();
636
-				$qb->insert('share')
637
-					->values([
638
-						'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
639
-						'share_with' => $qb->createNamedParameter($recipient),
640
-						'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
641
-						'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
642
-						'parent' => $qb->createNamedParameter($share->getId()),
643
-						'item_type' => $qb->createNamedParameter($share->getNodeType()),
644
-						'item_source' => $qb->createNamedParameter($share->getNodeId()),
645
-						'file_source' => $qb->createNamedParameter($share->getNodeId()),
646
-						'file_target' => $qb->createNamedParameter($share->getTarget()),
647
-						'permissions' => $qb->createNamedParameter($share->getPermissions()),
648
-						'attributes' => $qb->createNamedParameter($shareAttributes),
649
-						'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
650
-					])->execute();
651
-			} else {
652
-				// Already a usergroup share. Update it.
653
-				$qb = $this->dbConn->getQueryBuilder();
654
-				$qb->update('share')
655
-					->set('file_target', $qb->createNamedParameter($share->getTarget()))
656
-					->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
657
-					->execute();
658
-			}
659
-		}
660
-
661
-		return $share;
662
-	}
663
-
664
-	public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
665
-		$qb = $this->dbConn->getQueryBuilder();
666
-		$qb->select('s.*',
667
-				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
668
-				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
669
-				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum')
670
-			->from('share', 's')
671
-			->andWhere($qb->expr()->orX(
672
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
673
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
674
-			));
675
-
676
-		$qb->andWhere($qb->expr()->orX(
677
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
678
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
679
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
680
-		));
681
-
682
-		/**
683
-		 * Reshares for this user are shares where they are the owner.
684
-		 */
685
-		if ($reshares === false) {
686
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
687
-		} else {
688
-			$qb->andWhere(
689
-				$qb->expr()->orX(
690
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
691
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
692
-				)
693
-			);
694
-		}
695
-
696
-		// todo? maybe get these from the oc_mounts table
697
-		$childMountNodes = array_filter($node->getDirectoryListing(), function (Node $node): bool {
698
-			return $node->getInternalPath() === '';
699
-		});
700
-		$childMountRootIds = array_map(function (Node $node): int {
701
-			return $node->getId();
702
-		}, $childMountNodes);
703
-
704
-		$qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
705
-		if ($shallow) {
706
-			$qb->andWhere(
707
-				$qb->expr()->orX(
708
-					$qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
709
-					$qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
710
-				)
711
-			);
712
-		} else {
713
-			$qb->andWhere(
714
-				$qb->expr()->orX(
715
-					$qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
716
-					$qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
717
-				)
718
-			);
719
-		}
720
-
721
-		$qb->orderBy('id');
722
-
723
-		$shares = [];
724
-
725
-		$chunks = array_chunk($childMountRootIds, 1000);
726
-
727
-		// Force the request to be run when there is 0 mount.
728
-		if (count($chunks) === 0) {
729
-			$chunks = [[]];
730
-		}
731
-
732
-		foreach ($chunks as $chunk) {
733
-			$qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
734
-			$cursor = $qb->executeQuery();
735
-			while ($data = $cursor->fetch()) {
736
-				$shares[$data['fileid']][] = $this->createShare($data);
737
-			}
738
-			$cursor->closeCursor();
739
-		}
740
-
741
-		return $shares;
742
-	}
743
-
744
-	/**
745
-	 * @inheritdoc
746
-	 */
747
-	public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
748
-		$qb = $this->dbConn->getQueryBuilder();
749
-		$qb->select('*')
750
-			->from('share')
751
-			->andWhere($qb->expr()->orX(
752
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
753
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
754
-			));
755
-
756
-		$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
757
-
758
-		/**
759
-		 * Reshares for this user are shares where they are the owner.
760
-		 */
761
-		if ($reshares === false) {
762
-			$qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
763
-		} else {
764
-			if ($node === null) {
765
-				$qb->andWhere(
766
-					$qb->expr()->orX(
767
-						$qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
768
-						$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
769
-					)
770
-				);
771
-			}
772
-		}
773
-
774
-		if ($node !== null) {
775
-			$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
776
-		}
777
-
778
-		if ($limit !== -1) {
779
-			$qb->setMaxResults($limit);
780
-		}
781
-
782
-		$qb->setFirstResult($offset);
783
-		$qb->orderBy('id');
784
-
785
-		$cursor = $qb->execute();
786
-		$shares = [];
787
-		while ($data = $cursor->fetch()) {
788
-			$shares[] = $this->createShare($data);
789
-		}
790
-		$cursor->closeCursor();
791
-
792
-		return $shares;
793
-	}
794
-
795
-	/**
796
-	 * @inheritdoc
797
-	 */
798
-	public function getShareById($id, $recipientId = null) {
799
-		$qb = $this->dbConn->getQueryBuilder();
800
-
801
-		$qb->select('*')
802
-			->from('share')
803
-			->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
804
-			->andWhere(
805
-				$qb->expr()->in(
806
-					'share_type',
807
-					$qb->createNamedParameter([
808
-						IShare::TYPE_USER,
809
-						IShare::TYPE_GROUP,
810
-						IShare::TYPE_LINK,
811
-					], IQueryBuilder::PARAM_INT_ARRAY)
812
-				)
813
-			)
814
-			->andWhere($qb->expr()->orX(
815
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
816
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
817
-			));
818
-
819
-		$cursor = $qb->execute();
820
-		$data = $cursor->fetch();
821
-		$cursor->closeCursor();
822
-
823
-		if ($data === false) {
824
-			throw new ShareNotFound();
825
-		}
826
-
827
-		try {
828
-			$share = $this->createShare($data);
829
-		} catch (InvalidShare $e) {
830
-			throw new ShareNotFound();
831
-		}
832
-
833
-		// If the recipient is set for a group share resolve to that user
834
-		if ($recipientId !== null && $share->getShareType() === IShare::TYPE_GROUP) {
835
-			$share = $this->resolveGroupShares([$share], $recipientId)[0];
836
-		}
837
-
838
-		return $share;
839
-	}
840
-
841
-	/**
842
-	 * Get shares for a given path
843
-	 *
844
-	 * @param \OCP\Files\Node $path
845
-	 * @return \OCP\Share\IShare[]
846
-	 */
847
-	public function getSharesByPath(Node $path) {
848
-		$qb = $this->dbConn->getQueryBuilder();
849
-
850
-		$cursor = $qb->select('*')
851
-			->from('share')
852
-			->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
853
-			->andWhere(
854
-				$qb->expr()->orX(
855
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
856
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
857
-				)
858
-			)
859
-			->andWhere($qb->expr()->orX(
860
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
861
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
862
-			))
863
-			->execute();
864
-
865
-		$shares = [];
866
-		while ($data = $cursor->fetch()) {
867
-			$shares[] = $this->createShare($data);
868
-		}
869
-		$cursor->closeCursor();
870
-
871
-		return $shares;
872
-	}
873
-
874
-	/**
875
-	 * Returns whether the given database result can be interpreted as
876
-	 * a share with accessible file (not trashed, not deleted)
877
-	 */
878
-	private function isAccessibleResult($data) {
879
-		// exclude shares leading to deleted file entries
880
-		if ($data['fileid'] === null || $data['path'] === null) {
881
-			return false;
882
-		}
883
-
884
-		// exclude shares leading to trashbin on home storages
885
-		$pathSections = explode('/', $data['path'], 2);
886
-		// FIXME: would not detect rare md5'd home storage case properly
887
-		if ($pathSections[0] !== 'files'
888
-			&& (strpos($data['storage_string_id'], 'home::') === 0 || strpos($data['storage_string_id'], 'object::user') === 0)) {
889
-			return false;
890
-		}
891
-		return true;
892
-	}
893
-
894
-	/**
895
-	 * @inheritdoc
896
-	 */
897
-	public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
898
-		/** @var Share[] $shares */
899
-		$shares = [];
900
-
901
-		if ($shareType === IShare::TYPE_USER) {
902
-			//Get shares directly with this user
903
-			$qb = $this->dbConn->getQueryBuilder();
904
-			$qb->select('s.*',
905
-				'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
906
-				'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
907
-				'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
908
-			)
909
-				->selectAlias('st.id', 'storage_string_id')
910
-				->from('share', 's')
911
-				->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
912
-				->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
913
-
914
-			// Order by id
915
-			$qb->orderBy('s.id');
916
-
917
-			// Set limit and offset
918
-			if ($limit !== -1) {
919
-				$qb->setMaxResults($limit);
920
-			}
921
-			$qb->setFirstResult($offset);
922
-
923
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
924
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
925
-				->andWhere($qb->expr()->orX(
926
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
927
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
928
-				));
929
-
930
-			// Filter by node if provided
931
-			if ($node !== null) {
932
-				$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
933
-			}
934
-
935
-			$cursor = $qb->execute();
936
-
937
-			while ($data = $cursor->fetch()) {
938
-				if ($data['fileid'] && $data['path'] === null) {
939
-					$data['path'] = (string) $data['path'];
940
-					$data['name'] = (string) $data['name'];
941
-					$data['checksum'] = (string) $data['checksum'];
942
-				}
943
-				if ($this->isAccessibleResult($data)) {
944
-					$shares[] = $this->createShare($data);
945
-				}
946
-			}
947
-			$cursor->closeCursor();
948
-		} elseif ($shareType === IShare::TYPE_GROUP) {
949
-			$user = $this->userManager->get($userId);
950
-			$allGroups = ($user instanceof IUser) ? $this->groupManager->getUserGroupIds($user) : [];
951
-
952
-			/** @var Share[] $shares2 */
953
-			$shares2 = [];
954
-
955
-			$start = 0;
956
-			while (true) {
957
-				$groups = array_slice($allGroups, $start, 1000);
958
-				$start += 1000;
959
-
960
-				if ($groups === []) {
961
-					break;
962
-				}
963
-
964
-				$qb = $this->dbConn->getQueryBuilder();
965
-				$qb->select('s.*',
966
-					'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
967
-					'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
968
-					'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
969
-				)
970
-					->selectAlias('st.id', 'storage_string_id')
971
-					->from('share', 's')
972
-					->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
973
-					->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
974
-					->orderBy('s.id')
975
-					->setFirstResult(0);
976
-
977
-				if ($limit !== -1) {
978
-					$qb->setMaxResults($limit - count($shares));
979
-				}
980
-
981
-				// Filter by node if provided
982
-				if ($node !== null) {
983
-					$qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
984
-				}
985
-
986
-
987
-				$groups = array_filter($groups);
988
-
989
-				$qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
990
-					->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
991
-						$groups,
992
-						IQueryBuilder::PARAM_STR_ARRAY
993
-					)))
994
-					->andWhere($qb->expr()->orX(
995
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
996
-						$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
997
-					));
998
-
999
-				$cursor = $qb->execute();
1000
-				while ($data = $cursor->fetch()) {
1001
-					if ($offset > 0) {
1002
-						$offset--;
1003
-						continue;
1004
-					}
1005
-
1006
-					if ($this->isAccessibleResult($data)) {
1007
-						$shares2[] = $this->createShare($data);
1008
-					}
1009
-				}
1010
-				$cursor->closeCursor();
1011
-			}
1012
-
1013
-			/*
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
+
612
+            // Check if there is a usergroup share
613
+            $qb = $this->dbConn->getQueryBuilder();
614
+            $stmt = $qb->select('id')
615
+                ->from('share')
616
+                ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
617
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($recipient)))
618
+                ->andWhere($qb->expr()->eq('parent', $qb->createNamedParameter($share->getId())))
619
+                ->andWhere($qb->expr()->orX(
620
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
621
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
622
+                ))
623
+                ->setMaxResults(1)
624
+                ->execute();
625
+
626
+            $data = $stmt->fetch();
627
+            $stmt->closeCursor();
628
+
629
+            $shareAttributes = $this->formatShareAttributes(
630
+                $share->getAttributes()
631
+            );
632
+
633
+            if ($data === false) {
634
+                // No usergroup share yet. Create one.
635
+                $qb = $this->dbConn->getQueryBuilder();
636
+                $qb->insert('share')
637
+                    ->values([
638
+                        'share_type' => $qb->createNamedParameter(IShare::TYPE_USERGROUP),
639
+                        'share_with' => $qb->createNamedParameter($recipient),
640
+                        'uid_owner' => $qb->createNamedParameter($share->getShareOwner()),
641
+                        'uid_initiator' => $qb->createNamedParameter($share->getSharedBy()),
642
+                        'parent' => $qb->createNamedParameter($share->getId()),
643
+                        'item_type' => $qb->createNamedParameter($share->getNodeType()),
644
+                        'item_source' => $qb->createNamedParameter($share->getNodeId()),
645
+                        'file_source' => $qb->createNamedParameter($share->getNodeId()),
646
+                        'file_target' => $qb->createNamedParameter($share->getTarget()),
647
+                        'permissions' => $qb->createNamedParameter($share->getPermissions()),
648
+                        'attributes' => $qb->createNamedParameter($shareAttributes),
649
+                        'stime' => $qb->createNamedParameter($share->getShareTime()->getTimestamp()),
650
+                    ])->execute();
651
+            } else {
652
+                // Already a usergroup share. Update it.
653
+                $qb = $this->dbConn->getQueryBuilder();
654
+                $qb->update('share')
655
+                    ->set('file_target', $qb->createNamedParameter($share->getTarget()))
656
+                    ->where($qb->expr()->eq('id', $qb->createNamedParameter($data['id'])))
657
+                    ->execute();
658
+            }
659
+        }
660
+
661
+        return $share;
662
+    }
663
+
664
+    public function getSharesInFolder($userId, Folder $node, $reshares, $shallow = true) {
665
+        $qb = $this->dbConn->getQueryBuilder();
666
+        $qb->select('s.*',
667
+                'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
668
+                'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
669
+                'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum')
670
+            ->from('share', 's')
671
+            ->andWhere($qb->expr()->orX(
672
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
673
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
674
+            ));
675
+
676
+        $qb->andWhere($qb->expr()->orX(
677
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
678
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
679
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
680
+        ));
681
+
682
+        /**
683
+         * Reshares for this user are shares where they are the owner.
684
+         */
685
+        if ($reshares === false) {
686
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
687
+        } else {
688
+            $qb->andWhere(
689
+                $qb->expr()->orX(
690
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
691
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
692
+                )
693
+            );
694
+        }
695
+
696
+        // todo? maybe get these from the oc_mounts table
697
+        $childMountNodes = array_filter($node->getDirectoryListing(), function (Node $node): bool {
698
+            return $node->getInternalPath() === '';
699
+        });
700
+        $childMountRootIds = array_map(function (Node $node): int {
701
+            return $node->getId();
702
+        }, $childMountNodes);
703
+
704
+        $qb->innerJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'));
705
+        if ($shallow) {
706
+            $qb->andWhere(
707
+                $qb->expr()->orX(
708
+                    $qb->expr()->eq('f.parent', $qb->createNamedParameter($node->getId())),
709
+                    $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
710
+                )
711
+            );
712
+        } else {
713
+            $qb->andWhere(
714
+                $qb->expr()->orX(
715
+                    $qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
716
+                    $qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
717
+                )
718
+            );
719
+        }
720
+
721
+        $qb->orderBy('id');
722
+
723
+        $shares = [];
724
+
725
+        $chunks = array_chunk($childMountRootIds, 1000);
726
+
727
+        // Force the request to be run when there is 0 mount.
728
+        if (count($chunks) === 0) {
729
+            $chunks = [[]];
730
+        }
731
+
732
+        foreach ($chunks as $chunk) {
733
+            $qb->setParameter('chunk', $chunk, IQueryBuilder::PARAM_INT_ARRAY);
734
+            $cursor = $qb->executeQuery();
735
+            while ($data = $cursor->fetch()) {
736
+                $shares[$data['fileid']][] = $this->createShare($data);
737
+            }
738
+            $cursor->closeCursor();
739
+        }
740
+
741
+        return $shares;
742
+    }
743
+
744
+    /**
745
+     * @inheritdoc
746
+     */
747
+    public function getSharesBy($userId, $shareType, $node, $reshares, $limit, $offset) {
748
+        $qb = $this->dbConn->getQueryBuilder();
749
+        $qb->select('*')
750
+            ->from('share')
751
+            ->andWhere($qb->expr()->orX(
752
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
753
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
754
+            ));
755
+
756
+        $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter($shareType)));
757
+
758
+        /**
759
+         * Reshares for this user are shares where they are the owner.
760
+         */
761
+        if ($reshares === false) {
762
+            $qb->andWhere($qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId)));
763
+        } else {
764
+            if ($node === null) {
765
+                $qb->andWhere(
766
+                    $qb->expr()->orX(
767
+                        $qb->expr()->eq('uid_owner', $qb->createNamedParameter($userId)),
768
+                        $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($userId))
769
+                    )
770
+                );
771
+            }
772
+        }
773
+
774
+        if ($node !== null) {
775
+            $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
776
+        }
777
+
778
+        if ($limit !== -1) {
779
+            $qb->setMaxResults($limit);
780
+        }
781
+
782
+        $qb->setFirstResult($offset);
783
+        $qb->orderBy('id');
784
+
785
+        $cursor = $qb->execute();
786
+        $shares = [];
787
+        while ($data = $cursor->fetch()) {
788
+            $shares[] = $this->createShare($data);
789
+        }
790
+        $cursor->closeCursor();
791
+
792
+        return $shares;
793
+    }
794
+
795
+    /**
796
+     * @inheritdoc
797
+     */
798
+    public function getShareById($id, $recipientId = null) {
799
+        $qb = $this->dbConn->getQueryBuilder();
800
+
801
+        $qb->select('*')
802
+            ->from('share')
803
+            ->where($qb->expr()->eq('id', $qb->createNamedParameter($id)))
804
+            ->andWhere(
805
+                $qb->expr()->in(
806
+                    'share_type',
807
+                    $qb->createNamedParameter([
808
+                        IShare::TYPE_USER,
809
+                        IShare::TYPE_GROUP,
810
+                        IShare::TYPE_LINK,
811
+                    ], IQueryBuilder::PARAM_INT_ARRAY)
812
+                )
813
+            )
814
+            ->andWhere($qb->expr()->orX(
815
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
816
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
817
+            ));
818
+
819
+        $cursor = $qb->execute();
820
+        $data = $cursor->fetch();
821
+        $cursor->closeCursor();
822
+
823
+        if ($data === false) {
824
+            throw new ShareNotFound();
825
+        }
826
+
827
+        try {
828
+            $share = $this->createShare($data);
829
+        } catch (InvalidShare $e) {
830
+            throw new ShareNotFound();
831
+        }
832
+
833
+        // If the recipient is set for a group share resolve to that user
834
+        if ($recipientId !== null && $share->getShareType() === IShare::TYPE_GROUP) {
835
+            $share = $this->resolveGroupShares([$share], $recipientId)[0];
836
+        }
837
+
838
+        return $share;
839
+    }
840
+
841
+    /**
842
+     * Get shares for a given path
843
+     *
844
+     * @param \OCP\Files\Node $path
845
+     * @return \OCP\Share\IShare[]
846
+     */
847
+    public function getSharesByPath(Node $path) {
848
+        $qb = $this->dbConn->getQueryBuilder();
849
+
850
+        $cursor = $qb->select('*')
851
+            ->from('share')
852
+            ->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($path->getId())))
853
+            ->andWhere(
854
+                $qb->expr()->orX(
855
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
856
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP))
857
+                )
858
+            )
859
+            ->andWhere($qb->expr()->orX(
860
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
861
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
862
+            ))
863
+            ->execute();
864
+
865
+        $shares = [];
866
+        while ($data = $cursor->fetch()) {
867
+            $shares[] = $this->createShare($data);
868
+        }
869
+        $cursor->closeCursor();
870
+
871
+        return $shares;
872
+    }
873
+
874
+    /**
875
+     * Returns whether the given database result can be interpreted as
876
+     * a share with accessible file (not trashed, not deleted)
877
+     */
878
+    private function isAccessibleResult($data) {
879
+        // exclude shares leading to deleted file entries
880
+        if ($data['fileid'] === null || $data['path'] === null) {
881
+            return false;
882
+        }
883
+
884
+        // exclude shares leading to trashbin on home storages
885
+        $pathSections = explode('/', $data['path'], 2);
886
+        // FIXME: would not detect rare md5'd home storage case properly
887
+        if ($pathSections[0] !== 'files'
888
+            && (strpos($data['storage_string_id'], 'home::') === 0 || strpos($data['storage_string_id'], 'object::user') === 0)) {
889
+            return false;
890
+        }
891
+        return true;
892
+    }
893
+
894
+    /**
895
+     * @inheritdoc
896
+     */
897
+    public function getSharedWith($userId, $shareType, $node, $limit, $offset) {
898
+        /** @var Share[] $shares */
899
+        $shares = [];
900
+
901
+        if ($shareType === IShare::TYPE_USER) {
902
+            //Get shares directly with this user
903
+            $qb = $this->dbConn->getQueryBuilder();
904
+            $qb->select('s.*',
905
+                'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
906
+                'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
907
+                'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
908
+            )
909
+                ->selectAlias('st.id', 'storage_string_id')
910
+                ->from('share', 's')
911
+                ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
912
+                ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'));
913
+
914
+            // Order by id
915
+            $qb->orderBy('s.id');
916
+
917
+            // Set limit and offset
918
+            if ($limit !== -1) {
919
+                $qb->setMaxResults($limit);
920
+            }
921
+            $qb->setFirstResult($offset);
922
+
923
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)))
924
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
925
+                ->andWhere($qb->expr()->orX(
926
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
927
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
928
+                ));
929
+
930
+            // Filter by node if provided
931
+            if ($node !== null) {
932
+                $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
933
+            }
934
+
935
+            $cursor = $qb->execute();
936
+
937
+            while ($data = $cursor->fetch()) {
938
+                if ($data['fileid'] && $data['path'] === null) {
939
+                    $data['path'] = (string) $data['path'];
940
+                    $data['name'] = (string) $data['name'];
941
+                    $data['checksum'] = (string) $data['checksum'];
942
+                }
943
+                if ($this->isAccessibleResult($data)) {
944
+                    $shares[] = $this->createShare($data);
945
+                }
946
+            }
947
+            $cursor->closeCursor();
948
+        } elseif ($shareType === IShare::TYPE_GROUP) {
949
+            $user = $this->userManager->get($userId);
950
+            $allGroups = ($user instanceof IUser) ? $this->groupManager->getUserGroupIds($user) : [];
951
+
952
+            /** @var Share[] $shares2 */
953
+            $shares2 = [];
954
+
955
+            $start = 0;
956
+            while (true) {
957
+                $groups = array_slice($allGroups, $start, 1000);
958
+                $start += 1000;
959
+
960
+                if ($groups === []) {
961
+                    break;
962
+                }
963
+
964
+                $qb = $this->dbConn->getQueryBuilder();
965
+                $qb->select('s.*',
966
+                    'f.fileid', 'f.path', 'f.permissions AS f_permissions', 'f.storage', 'f.path_hash',
967
+                    'f.parent AS f_parent', 'f.name', 'f.mimetype', 'f.mimepart', 'f.size', 'f.mtime', 'f.storage_mtime',
968
+                    'f.encrypted', 'f.unencrypted_size', 'f.etag', 'f.checksum'
969
+                )
970
+                    ->selectAlias('st.id', 'storage_string_id')
971
+                    ->from('share', 's')
972
+                    ->leftJoin('s', 'filecache', 'f', $qb->expr()->eq('s.file_source', 'f.fileid'))
973
+                    ->leftJoin('f', 'storages', 'st', $qb->expr()->eq('f.storage', 'st.numeric_id'))
974
+                    ->orderBy('s.id')
975
+                    ->setFirstResult(0);
976
+
977
+                if ($limit !== -1) {
978
+                    $qb->setMaxResults($limit - count($shares));
979
+                }
980
+
981
+                // Filter by node if provided
982
+                if ($node !== null) {
983
+                    $qb->andWhere($qb->expr()->eq('file_source', $qb->createNamedParameter($node->getId())));
984
+                }
985
+
986
+
987
+                $groups = array_filter($groups);
988
+
989
+                $qb->andWhere($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
990
+                    ->andWhere($qb->expr()->in('share_with', $qb->createNamedParameter(
991
+                        $groups,
992
+                        IQueryBuilder::PARAM_STR_ARRAY
993
+                    )))
994
+                    ->andWhere($qb->expr()->orX(
995
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
996
+                        $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
997
+                    ));
998
+
999
+                $cursor = $qb->execute();
1000
+                while ($data = $cursor->fetch()) {
1001
+                    if ($offset > 0) {
1002
+                        $offset--;
1003
+                        continue;
1004
+                    }
1005
+
1006
+                    if ($this->isAccessibleResult($data)) {
1007
+                        $shares2[] = $this->createShare($data);
1008
+                    }
1009
+                }
1010
+                $cursor->closeCursor();
1011
+            }
1012
+
1013
+            /*
1014 1014
 			 * Resolve all group shares to user specific shares
1015 1015
 			 */
1016
-			$shares = $this->resolveGroupShares($shares2, $userId);
1017
-		} else {
1018
-			throw new BackendError('Invalid backend');
1019
-		}
1020
-
1021
-
1022
-		return $shares;
1023
-	}
1024
-
1025
-	/**
1026
-	 * Get a share by token
1027
-	 *
1028
-	 * @param string $token
1029
-	 * @return \OCP\Share\IShare
1030
-	 * @throws ShareNotFound
1031
-	 */
1032
-	public function getShareByToken($token) {
1033
-		$qb = $this->dbConn->getQueryBuilder();
1034
-
1035
-		$cursor = $qb->select('*')
1036
-			->from('share')
1037
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)))
1038
-			->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
1039
-			->andWhere($qb->expr()->orX(
1040
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1041
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1042
-			))
1043
-			->execute();
1044
-
1045
-		$data = $cursor->fetch();
1046
-
1047
-		if ($data === false) {
1048
-			throw new ShareNotFound();
1049
-		}
1050
-
1051
-		try {
1052
-			$share = $this->createShare($data);
1053
-		} catch (InvalidShare $e) {
1054
-			throw new ShareNotFound();
1055
-		}
1056
-
1057
-		return $share;
1058
-	}
1059
-
1060
-	/**
1061
-	 * Create a share object from an database row
1062
-	 *
1063
-	 * @param mixed[] $data
1064
-	 * @return \OCP\Share\IShare
1065
-	 * @throws InvalidShare
1066
-	 */
1067
-	private function createShare($data) {
1068
-		$share = new Share($this->rootFolder, $this->userManager);
1069
-		$share->setId((int)$data['id'])
1070
-			->setShareType((int)$data['share_type'])
1071
-			->setPermissions((int)$data['permissions'])
1072
-			->setTarget($data['file_target'])
1073
-			->setNote((string)$data['note'])
1074
-			->setMailSend((bool)$data['mail_send'])
1075
-			->setStatus((int)$data['accepted'])
1076
-			->setLabel($data['label']);
1077
-
1078
-		$shareTime = new \DateTime();
1079
-		$shareTime->setTimestamp((int)$data['stime']);
1080
-		$share->setShareTime($shareTime);
1081
-
1082
-		if ($share->getShareType() === IShare::TYPE_USER) {
1083
-			$share->setSharedWith($data['share_with']);
1084
-			$user = $this->userManager->get($data['share_with']);
1085
-			if ($user !== null) {
1086
-				$share->setSharedWithDisplayName($user->getDisplayName());
1087
-			}
1088
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1089
-			$share->setSharedWith($data['share_with']);
1090
-			$group = $this->groupManager->get($data['share_with']);
1091
-			if ($group !== null) {
1092
-				$share->setSharedWithDisplayName($group->getDisplayName());
1093
-			}
1094
-		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
1095
-			$share->setPassword($data['password']);
1096
-			$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1097
-			$share->setToken($data['token']);
1098
-		}
1099
-
1100
-		$share = $this->updateShareAttributes($share, $data['attributes']);
1101
-
1102
-		$share->setSharedBy($data['uid_initiator']);
1103
-		$share->setShareOwner($data['uid_owner']);
1104
-
1105
-		$share->setNodeId((int)$data['file_source']);
1106
-		$share->setNodeType($data['item_type']);
1107
-
1108
-		if ($data['expiration'] !== null) {
1109
-			$expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1110
-			$share->setExpirationDate($expiration);
1111
-		}
1112
-
1113
-		if (isset($data['f_permissions'])) {
1114
-			$entryData = $data;
1115
-			$entryData['permissions'] = $entryData['f_permissions'];
1116
-			$entryData['parent'] = $entryData['f_parent'];
1117
-			$share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1118
-				\OC::$server->getMimeTypeLoader()));
1119
-		}
1120
-
1121
-		$share->setProviderId($this->identifier());
1122
-		$share->setHideDownload((int)$data['hide_download'] === 1);
1123
-
1124
-		return $share;
1125
-	}
1126
-
1127
-	/**
1128
-	 * @param Share[] $shares
1129
-	 * @param $userId
1130
-	 * @return Share[] The updates shares if no update is found for a share return the original
1131
-	 */
1132
-	private function resolveGroupShares($shares, $userId) {
1133
-		$result = [];
1134
-
1135
-		$start = 0;
1136
-		while (true) {
1137
-			/** @var Share[] $shareSlice */
1138
-			$shareSlice = array_slice($shares, $start, 100);
1139
-			$start += 100;
1140
-
1141
-			if ($shareSlice === []) {
1142
-				break;
1143
-			}
1144
-
1145
-			/** @var int[] $ids */
1146
-			$ids = [];
1147
-			/** @var Share[] $shareMap */
1148
-			$shareMap = [];
1149
-
1150
-			foreach ($shareSlice as $share) {
1151
-				$ids[] = (int)$share->getId();
1152
-				$shareMap[$share->getId()] = $share;
1153
-			}
1154
-
1155
-			$qb = $this->dbConn->getQueryBuilder();
1156
-
1157
-			$query = $qb->select('*')
1158
-				->from('share')
1159
-				->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1160
-				->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1161
-				->andWhere($qb->expr()->orX(
1162
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1163
-					$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1164
-				));
1165
-
1166
-			$stmt = $query->execute();
1167
-
1168
-			while ($data = $stmt->fetch()) {
1169
-				$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1170
-				$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1171
-				$shareMap[$data['parent']]->setTarget($data['file_target']);
1172
-				$shareMap[$data['parent']]->setParent($data['parent']);
1173
-			}
1174
-
1175
-			$stmt->closeCursor();
1176
-
1177
-			foreach ($shareMap as $share) {
1178
-				$result[] = $share;
1179
-			}
1180
-		}
1181
-
1182
-		return $result;
1183
-	}
1184
-
1185
-	/**
1186
-	 * A user is deleted from the system
1187
-	 * So clean up the relevant shares.
1188
-	 *
1189
-	 * @param string $uid
1190
-	 * @param int $shareType
1191
-	 */
1192
-	public function userDeleted($uid, $shareType) {
1193
-		$qb = $this->dbConn->getQueryBuilder();
1194
-
1195
-		$qb->delete('share');
1196
-
1197
-		if ($shareType === IShare::TYPE_USER) {
1198
-			/*
1016
+            $shares = $this->resolveGroupShares($shares2, $userId);
1017
+        } else {
1018
+            throw new BackendError('Invalid backend');
1019
+        }
1020
+
1021
+
1022
+        return $shares;
1023
+    }
1024
+
1025
+    /**
1026
+     * Get a share by token
1027
+     *
1028
+     * @param string $token
1029
+     * @return \OCP\Share\IShare
1030
+     * @throws ShareNotFound
1031
+     */
1032
+    public function getShareByToken($token) {
1033
+        $qb = $this->dbConn->getQueryBuilder();
1034
+
1035
+        $cursor = $qb->select('*')
1036
+            ->from('share')
1037
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)))
1038
+            ->andWhere($qb->expr()->eq('token', $qb->createNamedParameter($token)))
1039
+            ->andWhere($qb->expr()->orX(
1040
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1041
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1042
+            ))
1043
+            ->execute();
1044
+
1045
+        $data = $cursor->fetch();
1046
+
1047
+        if ($data === false) {
1048
+            throw new ShareNotFound();
1049
+        }
1050
+
1051
+        try {
1052
+            $share = $this->createShare($data);
1053
+        } catch (InvalidShare $e) {
1054
+            throw new ShareNotFound();
1055
+        }
1056
+
1057
+        return $share;
1058
+    }
1059
+
1060
+    /**
1061
+     * Create a share object from an database row
1062
+     *
1063
+     * @param mixed[] $data
1064
+     * @return \OCP\Share\IShare
1065
+     * @throws InvalidShare
1066
+     */
1067
+    private function createShare($data) {
1068
+        $share = new Share($this->rootFolder, $this->userManager);
1069
+        $share->setId((int)$data['id'])
1070
+            ->setShareType((int)$data['share_type'])
1071
+            ->setPermissions((int)$data['permissions'])
1072
+            ->setTarget($data['file_target'])
1073
+            ->setNote((string)$data['note'])
1074
+            ->setMailSend((bool)$data['mail_send'])
1075
+            ->setStatus((int)$data['accepted'])
1076
+            ->setLabel($data['label']);
1077
+
1078
+        $shareTime = new \DateTime();
1079
+        $shareTime->setTimestamp((int)$data['stime']);
1080
+        $share->setShareTime($shareTime);
1081
+
1082
+        if ($share->getShareType() === IShare::TYPE_USER) {
1083
+            $share->setSharedWith($data['share_with']);
1084
+            $user = $this->userManager->get($data['share_with']);
1085
+            if ($user !== null) {
1086
+                $share->setSharedWithDisplayName($user->getDisplayName());
1087
+            }
1088
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1089
+            $share->setSharedWith($data['share_with']);
1090
+            $group = $this->groupManager->get($data['share_with']);
1091
+            if ($group !== null) {
1092
+                $share->setSharedWithDisplayName($group->getDisplayName());
1093
+            }
1094
+        } elseif ($share->getShareType() === IShare::TYPE_LINK) {
1095
+            $share->setPassword($data['password']);
1096
+            $share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1097
+            $share->setToken($data['token']);
1098
+        }
1099
+
1100
+        $share = $this->updateShareAttributes($share, $data['attributes']);
1101
+
1102
+        $share->setSharedBy($data['uid_initiator']);
1103
+        $share->setShareOwner($data['uid_owner']);
1104
+
1105
+        $share->setNodeId((int)$data['file_source']);
1106
+        $share->setNodeType($data['item_type']);
1107
+
1108
+        if ($data['expiration'] !== null) {
1109
+            $expiration = \DateTime::createFromFormat('Y-m-d H:i:s', $data['expiration']);
1110
+            $share->setExpirationDate($expiration);
1111
+        }
1112
+
1113
+        if (isset($data['f_permissions'])) {
1114
+            $entryData = $data;
1115
+            $entryData['permissions'] = $entryData['f_permissions'];
1116
+            $entryData['parent'] = $entryData['f_parent'];
1117
+            $share->setNodeCacheEntry(Cache::cacheEntryFromData($entryData,
1118
+                \OC::$server->getMimeTypeLoader()));
1119
+        }
1120
+
1121
+        $share->setProviderId($this->identifier());
1122
+        $share->setHideDownload((int)$data['hide_download'] === 1);
1123
+
1124
+        return $share;
1125
+    }
1126
+
1127
+    /**
1128
+     * @param Share[] $shares
1129
+     * @param $userId
1130
+     * @return Share[] The updates shares if no update is found for a share return the original
1131
+     */
1132
+    private function resolveGroupShares($shares, $userId) {
1133
+        $result = [];
1134
+
1135
+        $start = 0;
1136
+        while (true) {
1137
+            /** @var Share[] $shareSlice */
1138
+            $shareSlice = array_slice($shares, $start, 100);
1139
+            $start += 100;
1140
+
1141
+            if ($shareSlice === []) {
1142
+                break;
1143
+            }
1144
+
1145
+            /** @var int[] $ids */
1146
+            $ids = [];
1147
+            /** @var Share[] $shareMap */
1148
+            $shareMap = [];
1149
+
1150
+            foreach ($shareSlice as $share) {
1151
+                $ids[] = (int)$share->getId();
1152
+                $shareMap[$share->getId()] = $share;
1153
+            }
1154
+
1155
+            $qb = $this->dbConn->getQueryBuilder();
1156
+
1157
+            $query = $qb->select('*')
1158
+                ->from('share')
1159
+                ->where($qb->expr()->in('parent', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1160
+                ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($userId)))
1161
+                ->andWhere($qb->expr()->orX(
1162
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1163
+                    $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1164
+                ));
1165
+
1166
+            $stmt = $query->execute();
1167
+
1168
+            while ($data = $stmt->fetch()) {
1169
+                $shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1170
+                $shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1171
+                $shareMap[$data['parent']]->setTarget($data['file_target']);
1172
+                $shareMap[$data['parent']]->setParent($data['parent']);
1173
+            }
1174
+
1175
+            $stmt->closeCursor();
1176
+
1177
+            foreach ($shareMap as $share) {
1178
+                $result[] = $share;
1179
+            }
1180
+        }
1181
+
1182
+        return $result;
1183
+    }
1184
+
1185
+    /**
1186
+     * A user is deleted from the system
1187
+     * So clean up the relevant shares.
1188
+     *
1189
+     * @param string $uid
1190
+     * @param int $shareType
1191
+     */
1192
+    public function userDeleted($uid, $shareType) {
1193
+        $qb = $this->dbConn->getQueryBuilder();
1194
+
1195
+        $qb->delete('share');
1196
+
1197
+        if ($shareType === IShare::TYPE_USER) {
1198
+            /*
1199 1199
 			 * Delete all user shares that are owned by this user
1200 1200
 			 * or that are received by this user
1201 1201
 			 */
1202 1202
 
1203
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)));
1203
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)));
1204 1204
 
1205
-			$qb->andWhere(
1206
-				$qb->expr()->orX(
1207
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1208
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1209
-				)
1210
-			);
1211
-		} elseif ($shareType === IShare::TYPE_GROUP) {
1212
-			/*
1205
+            $qb->andWhere(
1206
+                $qb->expr()->orX(
1207
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1208
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1209
+                )
1210
+            );
1211
+        } elseif ($shareType === IShare::TYPE_GROUP) {
1212
+            /*
1213 1213
 			 * Delete all group shares that are owned by this user
1214 1214
 			 * Or special user group shares that are received by this user
1215 1215
 			 */
1216
-			$qb->where(
1217
-				$qb->expr()->andX(
1218
-					$qb->expr()->orX(
1219
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1220
-						$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
1221
-					),
1222
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1223
-				)
1224
-			);
1225
-
1226
-			$qb->orWhere(
1227
-				$qb->expr()->andX(
1228
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)),
1229
-					$qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1230
-				)
1231
-			);
1232
-		} elseif ($shareType === IShare::TYPE_LINK) {
1233
-			/*
1216
+            $qb->where(
1217
+                $qb->expr()->andX(
1218
+                    $qb->expr()->orX(
1219
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1220
+                        $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP))
1221
+                    ),
1222
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid))
1223
+                )
1224
+            );
1225
+
1226
+            $qb->orWhere(
1227
+                $qb->expr()->andX(
1228
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)),
1229
+                    $qb->expr()->eq('share_with', $qb->createNamedParameter($uid))
1230
+                )
1231
+            );
1232
+        } elseif ($shareType === IShare::TYPE_LINK) {
1233
+            /*
1234 1234
 			 * Delete all link shares owned by this user.
1235 1235
 			 * And all link shares initiated by this user (until #22327 is in)
1236 1236
 			 */
1237
-			$qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)));
1238
-
1239
-			$qb->andWhere(
1240
-				$qb->expr()->orX(
1241
-					$qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1242
-					$qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1243
-				)
1244
-			);
1245
-		} else {
1246
-			\OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1247
-			return;
1248
-		}
1249
-
1250
-		$qb->execute();
1251
-	}
1252
-
1253
-	/**
1254
-	 * Delete all shares received by this group. As well as any custom group
1255
-	 * shares for group members.
1256
-	 *
1257
-	 * @param string $gid
1258
-	 */
1259
-	public function groupDeleted($gid) {
1260
-		/*
1237
+            $qb->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK)));
1238
+
1239
+            $qb->andWhere(
1240
+                $qb->expr()->orX(
1241
+                    $qb->expr()->eq('uid_owner', $qb->createNamedParameter($uid)),
1242
+                    $qb->expr()->eq('uid_initiator', $qb->createNamedParameter($uid))
1243
+                )
1244
+            );
1245
+        } else {
1246
+            \OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1247
+            return;
1248
+        }
1249
+
1250
+        $qb->execute();
1251
+    }
1252
+
1253
+    /**
1254
+     * Delete all shares received by this group. As well as any custom group
1255
+     * shares for group members.
1256
+     *
1257
+     * @param string $gid
1258
+     */
1259
+    public function groupDeleted($gid) {
1260
+        /*
1261 1261
 		 * First delete all custom group shares for group members
1262 1262
 		 */
1263
-		$qb = $this->dbConn->getQueryBuilder();
1264
-		$qb->select('id')
1265
-			->from('share')
1266
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1267
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1268
-
1269
-		$cursor = $qb->execute();
1270
-		$ids = [];
1271
-		while ($row = $cursor->fetch()) {
1272
-			$ids[] = (int)$row['id'];
1273
-		}
1274
-		$cursor->closeCursor();
1275
-
1276
-		if (!empty($ids)) {
1277
-			$chunks = array_chunk($ids, 100);
1278
-			foreach ($chunks as $chunk) {
1279
-				$qb->delete('share')
1280
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1281
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1282
-				$qb->execute();
1283
-			}
1284
-		}
1285
-
1286
-		/*
1263
+        $qb = $this->dbConn->getQueryBuilder();
1264
+        $qb->select('id')
1265
+            ->from('share')
1266
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1267
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1268
+
1269
+        $cursor = $qb->execute();
1270
+        $ids = [];
1271
+        while ($row = $cursor->fetch()) {
1272
+            $ids[] = (int)$row['id'];
1273
+        }
1274
+        $cursor->closeCursor();
1275
+
1276
+        if (!empty($ids)) {
1277
+            $chunks = array_chunk($ids, 100);
1278
+            foreach ($chunks as $chunk) {
1279
+                $qb->delete('share')
1280
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1281
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1282
+                $qb->execute();
1283
+            }
1284
+        }
1285
+
1286
+        /*
1287 1287
 		 * Now delete all the group shares
1288 1288
 		 */
1289
-		$qb = $this->dbConn->getQueryBuilder();
1290
-		$qb->delete('share')
1291
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1292
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1293
-		$qb->execute();
1294
-	}
1295
-
1296
-	/**
1297
-	 * Delete custom group shares to this group for this user
1298
-	 *
1299
-	 * @param string $uid
1300
-	 * @param string $gid
1301
-	 */
1302
-	public function userDeletedFromGroup($uid, $gid) {
1303
-		/*
1289
+        $qb = $this->dbConn->getQueryBuilder();
1290
+        $qb->delete('share')
1291
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1292
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1293
+        $qb->execute();
1294
+    }
1295
+
1296
+    /**
1297
+     * Delete custom group shares to this group for this user
1298
+     *
1299
+     * @param string $uid
1300
+     * @param string $gid
1301
+     */
1302
+    public function userDeletedFromGroup($uid, $gid) {
1303
+        /*
1304 1304
 		 * Get all group shares
1305 1305
 		 */
1306
-		$qb = $this->dbConn->getQueryBuilder();
1307
-		$qb->select('id')
1308
-			->from('share')
1309
-			->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1310
-			->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1311
-
1312
-		$cursor = $qb->execute();
1313
-		$ids = [];
1314
-		while ($row = $cursor->fetch()) {
1315
-			$ids[] = (int)$row['id'];
1316
-		}
1317
-		$cursor->closeCursor();
1318
-
1319
-		if (!empty($ids)) {
1320
-			$chunks = array_chunk($ids, 100);
1321
-			foreach ($chunks as $chunk) {
1322
-				/*
1306
+        $qb = $this->dbConn->getQueryBuilder();
1307
+        $qb->select('id')
1308
+            ->from('share')
1309
+            ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)))
1310
+            ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($gid)));
1311
+
1312
+        $cursor = $qb->execute();
1313
+        $ids = [];
1314
+        while ($row = $cursor->fetch()) {
1315
+            $ids[] = (int)$row['id'];
1316
+        }
1317
+        $cursor->closeCursor();
1318
+
1319
+        if (!empty($ids)) {
1320
+            $chunks = array_chunk($ids, 100);
1321
+            foreach ($chunks as $chunk) {
1322
+                /*
1323 1323
 				 * Delete all special shares with this users for the found group shares
1324 1324
 				 */
1325
-				$qb->delete('share')
1326
-					->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1327
-					->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1328
-					->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1329
-				$qb->execute();
1330
-			}
1331
-		}
1332
-	}
1333
-
1334
-	/**
1335
-	 * @inheritdoc
1336
-	 */
1337
-	public function getAccessList($nodes, $currentAccess) {
1338
-		$ids = [];
1339
-		foreach ($nodes as $node) {
1340
-			$ids[] = $node->getId();
1341
-		}
1342
-
1343
-		$qb = $this->dbConn->getQueryBuilder();
1344
-
1345
-		$or = $qb->expr()->orX(
1346
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
1347
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1348
-			$qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
1349
-		);
1350
-
1351
-		if ($currentAccess) {
1352
-			$or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)));
1353
-		}
1354
-
1355
-		$qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1356
-			->from('share')
1357
-			->where(
1358
-				$or
1359
-			)
1360
-			->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1361
-			->andWhere($qb->expr()->orX(
1362
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1363
-				$qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1364
-			));
1365
-		$cursor = $qb->execute();
1366
-
1367
-		$users = [];
1368
-		$link = false;
1369
-		while ($row = $cursor->fetch()) {
1370
-			$type = (int)$row['share_type'];
1371
-			if ($type === IShare::TYPE_USER) {
1372
-				$uid = $row['share_with'];
1373
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1374
-				$users[$uid][$row['id']] = $row;
1375
-			} elseif ($type === IShare::TYPE_GROUP) {
1376
-				$gid = $row['share_with'];
1377
-				$group = $this->groupManager->get($gid);
1378
-
1379
-				if ($group === null) {
1380
-					continue;
1381
-				}
1382
-
1383
-				$userList = $group->getUsers();
1384
-				foreach ($userList as $user) {
1385
-					$uid = $user->getUID();
1386
-					$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1387
-					$users[$uid][$row['id']] = $row;
1388
-				}
1389
-			} elseif ($type === IShare::TYPE_LINK) {
1390
-				$link = true;
1391
-			} elseif ($type === IShare::TYPE_USERGROUP && $currentAccess === true) {
1392
-				$uid = $row['share_with'];
1393
-				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1394
-				$users[$uid][$row['id']] = $row;
1395
-			}
1396
-		}
1397
-		$cursor->closeCursor();
1398
-
1399
-		if ($currentAccess === true) {
1400
-			$users = array_map([$this, 'filterSharesOfUser'], $users);
1401
-			$users = array_filter($users);
1402
-		} else {
1403
-			$users = array_keys($users);
1404
-		}
1405
-
1406
-		return ['users' => $users, 'public' => $link];
1407
-	}
1408
-
1409
-	/**
1410
-	 * For each user the path with the fewest slashes is returned
1411
-	 * @param array $shares
1412
-	 * @return array
1413
-	 */
1414
-	protected function filterSharesOfUser(array $shares) {
1415
-		// Group shares when the user has a share exception
1416
-		foreach ($shares as $id => $share) {
1417
-			$type = (int) $share['share_type'];
1418
-			$permissions = (int) $share['permissions'];
1419
-
1420
-			if ($type === IShare::TYPE_USERGROUP) {
1421
-				unset($shares[$share['parent']]);
1422
-
1423
-				if ($permissions === 0) {
1424
-					unset($shares[$id]);
1425
-				}
1426
-			}
1427
-		}
1428
-
1429
-		$best = [];
1430
-		$bestDepth = 0;
1431
-		foreach ($shares as $id => $share) {
1432
-			$depth = substr_count(($share['file_target'] ?? ''), '/');
1433
-			if (empty($best) || $depth < $bestDepth) {
1434
-				$bestDepth = $depth;
1435
-				$best = [
1436
-					'node_id' => $share['file_source'],
1437
-					'node_path' => $share['file_target'],
1438
-				];
1439
-			}
1440
-		}
1441
-
1442
-		return $best;
1443
-	}
1444
-
1445
-	/**
1446
-	 * propagate notes to the recipients
1447
-	 *
1448
-	 * @param IShare $share
1449
-	 * @throws \OCP\Files\NotFoundException
1450
-	 */
1451
-	private function propagateNote(IShare $share) {
1452
-		if ($share->getShareType() === IShare::TYPE_USER) {
1453
-			$user = $this->userManager->get($share->getSharedWith());
1454
-			$this->sendNote([$user], $share);
1455
-		} elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1456
-			$group = $this->groupManager->get($share->getSharedWith());
1457
-			$groupMembers = $group->getUsers();
1458
-			$this->sendNote($groupMembers, $share);
1459
-		}
1460
-	}
1461
-
1462
-	/**
1463
-	 * send note by mail
1464
-	 *
1465
-	 * @param array $recipients
1466
-	 * @param IShare $share
1467
-	 * @throws \OCP\Files\NotFoundException
1468
-	 */
1469
-	private function sendNote(array $recipients, IShare $share) {
1470
-		$toListByLanguage = [];
1471
-
1472
-		foreach ($recipients as $recipient) {
1473
-			/** @var IUser $recipient */
1474
-			$email = $recipient->getEMailAddress();
1475
-			if ($email) {
1476
-				$language = $this->l10nFactory->getUserLanguage($recipient);
1477
-				if (!isset($toListByLanguage[$language])) {
1478
-					$toListByLanguage[$language] = [];
1479
-				}
1480
-				$toListByLanguage[$language][$email] = $recipient->getDisplayName();
1481
-			}
1482
-		}
1483
-
1484
-		if (empty($toListByLanguage)) {
1485
-			return;
1486
-		}
1487
-
1488
-		foreach ($toListByLanguage as $l10n => $toList) {
1489
-			$filename = $share->getNode()->getName();
1490
-			$initiator = $share->getSharedBy();
1491
-			$note = $share->getNote();
1492
-
1493
-			$l = $this->l10nFactory->get('lib', $l10n);
1494
-
1495
-			$initiatorUser = $this->userManager->get($initiator);
1496
-			$initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1497
-			$initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1498
-			$plainHeading = $l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1499
-			$htmlHeading = $l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1500
-			$message = $this->mailer->createMessage();
1501
-
1502
-			$emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1503
-
1504
-			$emailTemplate->setSubject($l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1505
-			$emailTemplate->addHeader();
1506
-			$emailTemplate->addHeading($htmlHeading, $plainHeading);
1507
-			$emailTemplate->addBodyText(htmlspecialchars($note), $note);
1508
-
1509
-			$link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1510
-			$emailTemplate->addBodyButton(
1511
-				$l->t('Open »%s«', [$filename]),
1512
-				$link
1513
-			);
1514
-
1515
-
1516
-			// The "From" contains the sharers name
1517
-			$instanceName = $this->defaults->getName();
1518
-			$senderName = $l->t(
1519
-				'%1$s via %2$s',
1520
-				[
1521
-					$initiatorDisplayName,
1522
-					$instanceName
1523
-				]
1524
-			);
1525
-			$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1526
-			if ($initiatorEmailAddress !== null) {
1527
-				$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1528
-				$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1529
-			} else {
1530
-				$emailTemplate->addFooter();
1531
-			}
1532
-
1533
-			if (count($toList) === 1) {
1534
-				$message->setTo($toList);
1535
-			} else {
1536
-				$message->setTo([]);
1537
-				$message->setBcc($toList);
1538
-			}
1539
-			$message->useTemplate($emailTemplate);
1540
-			$this->mailer->send($message);
1541
-		}
1542
-	}
1543
-
1544
-	public function getAllShares(): iterable {
1545
-		$qb = $this->dbConn->getQueryBuilder();
1546
-
1547
-		$qb->select('*')
1548
-			->from('share')
1549
-			->where(
1550
-				$qb->expr()->orX(
1551
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1552
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1553
-					$qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1554
-				)
1555
-			);
1556
-
1557
-		$cursor = $qb->execute();
1558
-		while ($data = $cursor->fetch()) {
1559
-			try {
1560
-				$share = $this->createShare($data);
1561
-			} catch (InvalidShare $e) {
1562
-				continue;
1563
-			}
1564
-
1565
-			yield $share;
1566
-		}
1567
-		$cursor->closeCursor();
1568
-	}
1569
-
1570
-	/**
1571
-	 * Load from database format (JSON string) to IAttributes
1572
-	 *
1573
-	 * @return IShare the modified share
1574
-	 */
1575
-	private function updateShareAttributes(IShare $share, ?string $data): IShare {
1576
-		if ($data !== null && $data !== '') {
1577
-			$attributes = new ShareAttributes();
1578
-			$compressedAttributes = \json_decode($data, true);
1579
-			if ($compressedAttributes === false || $compressedAttributes === null) {
1580
-				return $share;
1581
-			}
1582
-			foreach ($compressedAttributes as $compressedAttribute) {
1583
-				$attributes->setAttribute(
1584
-					$compressedAttribute[0],
1585
-					$compressedAttribute[1],
1586
-					$compressedAttribute[2]
1587
-				);
1588
-			}
1589
-			$share->setAttributes($attributes);
1590
-		}
1591
-
1592
-		return $share;
1593
-	}
1594
-
1595
-	/**
1596
-	 * Format IAttributes to database format (JSON string)
1597
-	 */
1598
-	private function formatShareAttributes(?IAttributes $attributes): ?string {
1599
-		if ($attributes === null || empty($attributes->toArray())) {
1600
-			return null;
1601
-		}
1602
-
1603
-		$compressedAttributes = [];
1604
-		foreach ($attributes->toArray() as $attribute) {
1605
-			$compressedAttributes[] = [
1606
-				0 => $attribute['scope'],
1607
-				1 => $attribute['key'],
1608
-				2 => $attribute['enabled']
1609
-			];
1610
-		}
1611
-		return \json_encode($compressedAttributes);
1612
-	}
1325
+                $qb->delete('share')
1326
+                    ->where($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)))
1327
+                    ->andWhere($qb->expr()->eq('share_with', $qb->createNamedParameter($uid)))
1328
+                    ->andWhere($qb->expr()->in('parent', $qb->createNamedParameter($chunk, IQueryBuilder::PARAM_INT_ARRAY)));
1329
+                $qb->execute();
1330
+            }
1331
+        }
1332
+    }
1333
+
1334
+    /**
1335
+     * @inheritdoc
1336
+     */
1337
+    public function getAccessList($nodes, $currentAccess) {
1338
+        $ids = [];
1339
+        foreach ($nodes as $node) {
1340
+            $ids[] = $node->getId();
1341
+        }
1342
+
1343
+        $qb = $this->dbConn->getQueryBuilder();
1344
+
1345
+        $or = $qb->expr()->orX(
1346
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USER)),
1347
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_GROUP)),
1348
+            $qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_LINK))
1349
+        );
1350
+
1351
+        if ($currentAccess) {
1352
+            $or->add($qb->expr()->eq('share_type', $qb->createNamedParameter(IShare::TYPE_USERGROUP)));
1353
+        }
1354
+
1355
+        $qb->select('id', 'parent', 'share_type', 'share_with', 'file_source', 'file_target', 'permissions')
1356
+            ->from('share')
1357
+            ->where(
1358
+                $or
1359
+            )
1360
+            ->andWhere($qb->expr()->in('file_source', $qb->createNamedParameter($ids, IQueryBuilder::PARAM_INT_ARRAY)))
1361
+            ->andWhere($qb->expr()->orX(
1362
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('file')),
1363
+                $qb->expr()->eq('item_type', $qb->createNamedParameter('folder'))
1364
+            ));
1365
+        $cursor = $qb->execute();
1366
+
1367
+        $users = [];
1368
+        $link = false;
1369
+        while ($row = $cursor->fetch()) {
1370
+            $type = (int)$row['share_type'];
1371
+            if ($type === IShare::TYPE_USER) {
1372
+                $uid = $row['share_with'];
1373
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1374
+                $users[$uid][$row['id']] = $row;
1375
+            } elseif ($type === IShare::TYPE_GROUP) {
1376
+                $gid = $row['share_with'];
1377
+                $group = $this->groupManager->get($gid);
1378
+
1379
+                if ($group === null) {
1380
+                    continue;
1381
+                }
1382
+
1383
+                $userList = $group->getUsers();
1384
+                foreach ($userList as $user) {
1385
+                    $uid = $user->getUID();
1386
+                    $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1387
+                    $users[$uid][$row['id']] = $row;
1388
+                }
1389
+            } elseif ($type === IShare::TYPE_LINK) {
1390
+                $link = true;
1391
+            } elseif ($type === IShare::TYPE_USERGROUP && $currentAccess === true) {
1392
+                $uid = $row['share_with'];
1393
+                $users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
1394
+                $users[$uid][$row['id']] = $row;
1395
+            }
1396
+        }
1397
+        $cursor->closeCursor();
1398
+
1399
+        if ($currentAccess === true) {
1400
+            $users = array_map([$this, 'filterSharesOfUser'], $users);
1401
+            $users = array_filter($users);
1402
+        } else {
1403
+            $users = array_keys($users);
1404
+        }
1405
+
1406
+        return ['users' => $users, 'public' => $link];
1407
+    }
1408
+
1409
+    /**
1410
+     * For each user the path with the fewest slashes is returned
1411
+     * @param array $shares
1412
+     * @return array
1413
+     */
1414
+    protected function filterSharesOfUser(array $shares) {
1415
+        // Group shares when the user has a share exception
1416
+        foreach ($shares as $id => $share) {
1417
+            $type = (int) $share['share_type'];
1418
+            $permissions = (int) $share['permissions'];
1419
+
1420
+            if ($type === IShare::TYPE_USERGROUP) {
1421
+                unset($shares[$share['parent']]);
1422
+
1423
+                if ($permissions === 0) {
1424
+                    unset($shares[$id]);
1425
+                }
1426
+            }
1427
+        }
1428
+
1429
+        $best = [];
1430
+        $bestDepth = 0;
1431
+        foreach ($shares as $id => $share) {
1432
+            $depth = substr_count(($share['file_target'] ?? ''), '/');
1433
+            if (empty($best) || $depth < $bestDepth) {
1434
+                $bestDepth = $depth;
1435
+                $best = [
1436
+                    'node_id' => $share['file_source'],
1437
+                    'node_path' => $share['file_target'],
1438
+                ];
1439
+            }
1440
+        }
1441
+
1442
+        return $best;
1443
+    }
1444
+
1445
+    /**
1446
+     * propagate notes to the recipients
1447
+     *
1448
+     * @param IShare $share
1449
+     * @throws \OCP\Files\NotFoundException
1450
+     */
1451
+    private function propagateNote(IShare $share) {
1452
+        if ($share->getShareType() === IShare::TYPE_USER) {
1453
+            $user = $this->userManager->get($share->getSharedWith());
1454
+            $this->sendNote([$user], $share);
1455
+        } elseif ($share->getShareType() === IShare::TYPE_GROUP) {
1456
+            $group = $this->groupManager->get($share->getSharedWith());
1457
+            $groupMembers = $group->getUsers();
1458
+            $this->sendNote($groupMembers, $share);
1459
+        }
1460
+    }
1461
+
1462
+    /**
1463
+     * send note by mail
1464
+     *
1465
+     * @param array $recipients
1466
+     * @param IShare $share
1467
+     * @throws \OCP\Files\NotFoundException
1468
+     */
1469
+    private function sendNote(array $recipients, IShare $share) {
1470
+        $toListByLanguage = [];
1471
+
1472
+        foreach ($recipients as $recipient) {
1473
+            /** @var IUser $recipient */
1474
+            $email = $recipient->getEMailAddress();
1475
+            if ($email) {
1476
+                $language = $this->l10nFactory->getUserLanguage($recipient);
1477
+                if (!isset($toListByLanguage[$language])) {
1478
+                    $toListByLanguage[$language] = [];
1479
+                }
1480
+                $toListByLanguage[$language][$email] = $recipient->getDisplayName();
1481
+            }
1482
+        }
1483
+
1484
+        if (empty($toListByLanguage)) {
1485
+            return;
1486
+        }
1487
+
1488
+        foreach ($toListByLanguage as $l10n => $toList) {
1489
+            $filename = $share->getNode()->getName();
1490
+            $initiator = $share->getSharedBy();
1491
+            $note = $share->getNote();
1492
+
1493
+            $l = $this->l10nFactory->get('lib', $l10n);
1494
+
1495
+            $initiatorUser = $this->userManager->get($initiator);
1496
+            $initiatorDisplayName = ($initiatorUser instanceof IUser) ? $initiatorUser->getDisplayName() : $initiator;
1497
+            $initiatorEmailAddress = ($initiatorUser instanceof IUser) ? $initiatorUser->getEMailAddress() : null;
1498
+            $plainHeading = $l->t('%1$s shared »%2$s« with you and wants to add:', [$initiatorDisplayName, $filename]);
1499
+            $htmlHeading = $l->t('%1$s shared »%2$s« with you and wants to add', [$initiatorDisplayName, $filename]);
1500
+            $message = $this->mailer->createMessage();
1501
+
1502
+            $emailTemplate = $this->mailer->createEMailTemplate('defaultShareProvider.sendNote');
1503
+
1504
+            $emailTemplate->setSubject($l->t('»%s« added a note to a file shared with you', [$initiatorDisplayName]));
1505
+            $emailTemplate->addHeader();
1506
+            $emailTemplate->addHeading($htmlHeading, $plainHeading);
1507
+            $emailTemplate->addBodyText(htmlspecialchars($note), $note);
1508
+
1509
+            $link = $this->urlGenerator->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $share->getNode()->getId()]);
1510
+            $emailTemplate->addBodyButton(
1511
+                $l->t('Open »%s«', [$filename]),
1512
+                $link
1513
+            );
1514
+
1515
+
1516
+            // The "From" contains the sharers name
1517
+            $instanceName = $this->defaults->getName();
1518
+            $senderName = $l->t(
1519
+                '%1$s via %2$s',
1520
+                [
1521
+                    $initiatorDisplayName,
1522
+                    $instanceName
1523
+                ]
1524
+            );
1525
+            $message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1526
+            if ($initiatorEmailAddress !== null) {
1527
+                $message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1528
+                $emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1529
+            } else {
1530
+                $emailTemplate->addFooter();
1531
+            }
1532
+
1533
+            if (count($toList) === 1) {
1534
+                $message->setTo($toList);
1535
+            } else {
1536
+                $message->setTo([]);
1537
+                $message->setBcc($toList);
1538
+            }
1539
+            $message->useTemplate($emailTemplate);
1540
+            $this->mailer->send($message);
1541
+        }
1542
+    }
1543
+
1544
+    public function getAllShares(): iterable {
1545
+        $qb = $this->dbConn->getQueryBuilder();
1546
+
1547
+        $qb->select('*')
1548
+            ->from('share')
1549
+            ->where(
1550
+                $qb->expr()->orX(
1551
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_USER)),
1552
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_GROUP)),
1553
+                    $qb->expr()->eq('share_type', $qb->createNamedParameter(\OCP\Share\IShare::TYPE_LINK))
1554
+                )
1555
+            );
1556
+
1557
+        $cursor = $qb->execute();
1558
+        while ($data = $cursor->fetch()) {
1559
+            try {
1560
+                $share = $this->createShare($data);
1561
+            } catch (InvalidShare $e) {
1562
+                continue;
1563
+            }
1564
+
1565
+            yield $share;
1566
+        }
1567
+        $cursor->closeCursor();
1568
+    }
1569
+
1570
+    /**
1571
+     * Load from database format (JSON string) to IAttributes
1572
+     *
1573
+     * @return IShare the modified share
1574
+     */
1575
+    private function updateShareAttributes(IShare $share, ?string $data): IShare {
1576
+        if ($data !== null && $data !== '') {
1577
+            $attributes = new ShareAttributes();
1578
+            $compressedAttributes = \json_decode($data, true);
1579
+            if ($compressedAttributes === false || $compressedAttributes === null) {
1580
+                return $share;
1581
+            }
1582
+            foreach ($compressedAttributes as $compressedAttribute) {
1583
+                $attributes->setAttribute(
1584
+                    $compressedAttribute[0],
1585
+                    $compressedAttribute[1],
1586
+                    $compressedAttribute[2]
1587
+                );
1588
+            }
1589
+            $share->setAttributes($attributes);
1590
+        }
1591
+
1592
+        return $share;
1593
+    }
1594
+
1595
+    /**
1596
+     * Format IAttributes to database format (JSON string)
1597
+     */
1598
+    private function formatShareAttributes(?IAttributes $attributes): ?string {
1599
+        if ($attributes === null || empty($attributes->toArray())) {
1600
+            return null;
1601
+        }
1602
+
1603
+        $compressedAttributes = [];
1604
+        foreach ($attributes->toArray() as $attribute) {
1605
+            $compressedAttributes[] = [
1606
+                0 => $attribute['scope'],
1607
+                1 => $attribute['key'],
1608
+                2 => $attribute['enabled']
1609
+            ];
1610
+        }
1611
+        return \json_encode($compressedAttributes);
1612
+    }
1613 1613
 }
Please login to merge, or discard this patch.
Spacing   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -358,7 +358,7 @@  discard block
 block discarded – undo
358 358
 			$user = $this->userManager->get($recipient);
359 359
 
360 360
 			if (is_null($group)) {
361
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
361
+				throw new ProviderException('Group "'.$share->getSharedWith().'" does not exist');
362 362
 			}
363 363
 
364 364
 			if (!$group->inGroup($user)) {
@@ -484,7 +484,7 @@  discard block
 block discarded – undo
484 484
 			$user = $this->userManager->get($recipient);
485 485
 
486 486
 			if (is_null($group)) {
487
-				throw new ProviderException('Group "' . $share->getSharedWith() . '" does not exist');
487
+				throw new ProviderException('Group "'.$share->getSharedWith().'" does not exist');
488 488
 			}
489 489
 
490 490
 			if (!$group->inGroup($user)) {
@@ -694,10 +694,10 @@  discard block
 block discarded – undo
694 694
 		}
695 695
 
696 696
 		// todo? maybe get these from the oc_mounts table
697
-		$childMountNodes = array_filter($node->getDirectoryListing(), function (Node $node): bool {
697
+		$childMountNodes = array_filter($node->getDirectoryListing(), function(Node $node): bool {
698 698
 			return $node->getInternalPath() === '';
699 699
 		});
700
-		$childMountRootIds = array_map(function (Node $node): int {
700
+		$childMountRootIds = array_map(function(Node $node): int {
701 701
 			return $node->getId();
702 702
 		}, $childMountNodes);
703 703
 
@@ -712,7 +712,7 @@  discard block
 block discarded – undo
712 712
 		} else {
713 713
 			$qb->andWhere(
714 714
 				$qb->expr()->orX(
715
-					$qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()) . '/%')),
715
+					$qb->expr()->like('f.path', $qb->createNamedParameter($this->dbConn->escapeLikeParameter($node->getInternalPath()).'/%')),
716 716
 					$qb->expr()->in('f.fileid', $qb->createParameter('chunk'))
717 717
 				)
718 718
 			);
@@ -1066,17 +1066,17 @@  discard block
 block discarded – undo
1066 1066
 	 */
1067 1067
 	private function createShare($data) {
1068 1068
 		$share = new Share($this->rootFolder, $this->userManager);
1069
-		$share->setId((int)$data['id'])
1070
-			->setShareType((int)$data['share_type'])
1071
-			->setPermissions((int)$data['permissions'])
1069
+		$share->setId((int) $data['id'])
1070
+			->setShareType((int) $data['share_type'])
1071
+			->setPermissions((int) $data['permissions'])
1072 1072
 			->setTarget($data['file_target'])
1073
-			->setNote((string)$data['note'])
1074
-			->setMailSend((bool)$data['mail_send'])
1075
-			->setStatus((int)$data['accepted'])
1073
+			->setNote((string) $data['note'])
1074
+			->setMailSend((bool) $data['mail_send'])
1075
+			->setStatus((int) $data['accepted'])
1076 1076
 			->setLabel($data['label']);
1077 1077
 
1078 1078
 		$shareTime = new \DateTime();
1079
-		$shareTime->setTimestamp((int)$data['stime']);
1079
+		$shareTime->setTimestamp((int) $data['stime']);
1080 1080
 		$share->setShareTime($shareTime);
1081 1081
 
1082 1082
 		if ($share->getShareType() === IShare::TYPE_USER) {
@@ -1093,7 +1093,7 @@  discard block
 block discarded – undo
1093 1093
 			}
1094 1094
 		} elseif ($share->getShareType() === IShare::TYPE_LINK) {
1095 1095
 			$share->setPassword($data['password']);
1096
-			$share->setSendPasswordByTalk((bool)$data['password_by_talk']);
1096
+			$share->setSendPasswordByTalk((bool) $data['password_by_talk']);
1097 1097
 			$share->setToken($data['token']);
1098 1098
 		}
1099 1099
 
@@ -1102,7 +1102,7 @@  discard block
 block discarded – undo
1102 1102
 		$share->setSharedBy($data['uid_initiator']);
1103 1103
 		$share->setShareOwner($data['uid_owner']);
1104 1104
 
1105
-		$share->setNodeId((int)$data['file_source']);
1105
+		$share->setNodeId((int) $data['file_source']);
1106 1106
 		$share->setNodeType($data['item_type']);
1107 1107
 
1108 1108
 		if ($data['expiration'] !== null) {
@@ -1119,7 +1119,7 @@  discard block
 block discarded – undo
1119 1119
 		}
1120 1120
 
1121 1121
 		$share->setProviderId($this->identifier());
1122
-		$share->setHideDownload((int)$data['hide_download'] === 1);
1122
+		$share->setHideDownload((int) $data['hide_download'] === 1);
1123 1123
 
1124 1124
 		return $share;
1125 1125
 	}
@@ -1148,7 +1148,7 @@  discard block
 block discarded – undo
1148 1148
 			$shareMap = [];
1149 1149
 
1150 1150
 			foreach ($shareSlice as $share) {
1151
-				$ids[] = (int)$share->getId();
1151
+				$ids[] = (int) $share->getId();
1152 1152
 				$shareMap[$share->getId()] = $share;
1153 1153
 			}
1154 1154
 
@@ -1166,8 +1166,8 @@  discard block
 block discarded – undo
1166 1166
 			$stmt = $query->execute();
1167 1167
 
1168 1168
 			while ($data = $stmt->fetch()) {
1169
-				$shareMap[$data['parent']]->setPermissions((int)$data['permissions']);
1170
-				$shareMap[$data['parent']]->setStatus((int)$data['accepted']);
1169
+				$shareMap[$data['parent']]->setPermissions((int) $data['permissions']);
1170
+				$shareMap[$data['parent']]->setStatus((int) $data['accepted']);
1171 1171
 				$shareMap[$data['parent']]->setTarget($data['file_target']);
1172 1172
 				$shareMap[$data['parent']]->setParent($data['parent']);
1173 1173
 			}
@@ -1243,7 +1243,7 @@  discard block
 block discarded – undo
1243 1243
 				)
1244 1244
 			);
1245 1245
 		} else {
1246
-			\OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: ' . $shareType));
1246
+			\OC::$server->getLogger()->logException(new \InvalidArgumentException('Default share provider tried to delete all shares for type: '.$shareType));
1247 1247
 			return;
1248 1248
 		}
1249 1249
 
@@ -1269,7 +1269,7 @@  discard block
 block discarded – undo
1269 1269
 		$cursor = $qb->execute();
1270 1270
 		$ids = [];
1271 1271
 		while ($row = $cursor->fetch()) {
1272
-			$ids[] = (int)$row['id'];
1272
+			$ids[] = (int) $row['id'];
1273 1273
 		}
1274 1274
 		$cursor->closeCursor();
1275 1275
 
@@ -1312,7 +1312,7 @@  discard block
 block discarded – undo
1312 1312
 		$cursor = $qb->execute();
1313 1313
 		$ids = [];
1314 1314
 		while ($row = $cursor->fetch()) {
1315
-			$ids[] = (int)$row['id'];
1315
+			$ids[] = (int) $row['id'];
1316 1316
 		}
1317 1317
 		$cursor->closeCursor();
1318 1318
 
@@ -1367,7 +1367,7 @@  discard block
 block discarded – undo
1367 1367
 		$users = [];
1368 1368
 		$link = false;
1369 1369
 		while ($row = $cursor->fetch()) {
1370
-			$type = (int)$row['share_type'];
1370
+			$type = (int) $row['share_type'];
1371 1371
 			if ($type === IShare::TYPE_USER) {
1372 1372
 				$uid = $row['share_with'];
1373 1373
 				$users[$uid] = isset($users[$uid]) ? $users[$uid] : [];
@@ -1525,7 +1525,7 @@  discard block
 block discarded – undo
1525 1525
 			$message->setFrom([\OCP\Util::getDefaultEmailAddress($instanceName) => $senderName]);
1526 1526
 			if ($initiatorEmailAddress !== null) {
1527 1527
 				$message->setReplyTo([$initiatorEmailAddress => $initiatorDisplayName]);
1528
-				$emailTemplate->addFooter($instanceName . ' - ' . $this->defaults->getSlogan());
1528
+				$emailTemplate->addFooter($instanceName.' - '.$this->defaults->getSlogan());
1529 1529
 			} else {
1530 1530
 				$emailTemplate->addFooter();
1531 1531
 			}
Please login to merge, or discard this patch.