Passed
Push — master ( bbb39c...5026d2 )
by Christoph
27:34 queued 12:27
created
apps/dav/lib/Connector/Sabre/SharesPlugin.php 2 patches
Indentation   +178 added lines, -178 removed lines patch added patch discarded remove patch
@@ -37,182 +37,182 @@
 block discarded – undo
37 37
  * Sabre Plugin to provide share-related properties
38 38
  */
39 39
 class SharesPlugin extends \Sabre\DAV\ServerPlugin {
40
-	public const NS_OWNCLOUD = 'http://owncloud.org/ns';
41
-	public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
42
-	public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
43
-	public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
44
-
45
-	/**
46
-	 * Reference to main server object
47
-	 *
48
-	 * @var \Sabre\DAV\Server
49
-	 */
50
-	private $server;
51
-
52
-	/**
53
-	 * @var \OCP\Share\IManager
54
-	 */
55
-	private $shareManager;
56
-
57
-	/**
58
-	 * @var \Sabre\DAV\Tree
59
-	 */
60
-	private $tree;
61
-
62
-	/**
63
-	 * @var string
64
-	 */
65
-	private $userId;
66
-
67
-	/**
68
-	 * @var \OCP\Files\Folder
69
-	 */
70
-	private $userFolder;
71
-
72
-	/** @var IShare[] */
73
-	private $cachedShares = [];
74
-
75
-	private $cachedFolders = [];
76
-
77
-	/**
78
-	 * @param \Sabre\DAV\Tree $tree tree
79
-	 * @param IUserSession $userSession user session
80
-	 * @param \OCP\Files\Folder $userFolder user home folder
81
-	 * @param \OCP\Share\IManager $shareManager share manager
82
-	 */
83
-	public function __construct(
84
-		\Sabre\DAV\Tree $tree,
85
-		IUserSession $userSession,
86
-		\OCP\Files\Folder $userFolder,
87
-		\OCP\Share\IManager $shareManager
88
-	) {
89
-		$this->tree = $tree;
90
-		$this->shareManager = $shareManager;
91
-		$this->userFolder = $userFolder;
92
-		$this->userId = $userSession->getUser()->getUID();
93
-	}
94
-
95
-	/**
96
-	 * This initializes the plugin.
97
-	 *
98
-	 * This function is called by \Sabre\DAV\Server, after
99
-	 * addPlugin is called.
100
-	 *
101
-	 * This method should set up the required event subscriptions.
102
-	 *
103
-	 * @param \Sabre\DAV\Server $server
104
-	 */
105
-	public function initialize(\Sabre\DAV\Server $server) {
106
-		$server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
107
-		$server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
108
-		$server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
109
-		$server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
110
-
111
-		$this->server = $server;
112
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
113
-	}
114
-
115
-	private function getShare(\OCP\Files\Node $node): array {
116
-		$result = [];
117
-		$requestedShareTypes = [
118
-			IShare::TYPE_USER,
119
-			IShare::TYPE_GROUP,
120
-			IShare::TYPE_LINK,
121
-			IShare::TYPE_REMOTE,
122
-			IShare::TYPE_EMAIL,
123
-			IShare::TYPE_ROOM,
124
-			IShare::TYPE_CIRCLE,
125
-			IShare::TYPE_DECK,
126
-		];
127
-		foreach ($requestedShareTypes as $requestedShareType) {
128
-			$shares = $this->shareManager->getSharesBy(
129
-				$this->userId,
130
-				$requestedShareType,
131
-				$node,
132
-				false,
133
-				-1
134
-			);
135
-			foreach ($shares as $share) {
136
-				$result[] = $share;
137
-			}
138
-		}
139
-		return $result;
140
-	}
141
-
142
-	private function getSharesFolder(\OCP\Files\Folder $node): array {
143
-		return $this->shareManager->getSharesInFolder(
144
-			$this->userId,
145
-			$node,
146
-			true
147
-		);
148
-	}
149
-
150
-	private function getShares(\Sabre\DAV\INode $sabreNode): array {
151
-		if (isset($this->cachedShares[$sabreNode->getId()])) {
152
-			$shares = $this->cachedShares[$sabreNode->getId()];
153
-		} else {
154
-			[$parentPath,] = \Sabre\Uri\split($sabreNode->getPath());
155
-			if ($parentPath === '') {
156
-				$parentPath = '/';
157
-			}
158
-			// if we already cached the folder this file is in we know there are no shares for this file
159
-			if (array_search($parentPath, $this->cachedFolders) === false) {
160
-				$node = $this->userFolder->get($sabreNode->getPath());
161
-				$shares = $this->getShare($node);
162
-				$this->cachedShares[$sabreNode->getId()] = $shares;
163
-			} else {
164
-				return [];
165
-			}
166
-		}
167
-
168
-		return $shares;
169
-	}
170
-
171
-	/**
172
-	 * Adds shares to propfind response
173
-	 *
174
-	 * @param PropFind $propFind propfind object
175
-	 * @param \Sabre\DAV\INode $sabreNode sabre node
176
-	 */
177
-	public function handleGetProperties(
178
-		PropFind $propFind,
179
-		\Sabre\DAV\INode $sabreNode
180
-	) {
181
-		if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
182
-			return;
183
-		}
184
-
185
-		// need prefetch ?
186
-		if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
187
-			&& $propFind->getDepth() !== 0
188
-			&& (
189
-				!is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
190
-				!is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
191
-			)
192
-		) {
193
-			$folderNode = $this->userFolder->get($sabreNode->getPath());
194
-
195
-			$this->cachedFolders[] = $sabreNode->getPath();
196
-			$childShares = $this->getSharesFolder($folderNode);
197
-			foreach ($childShares as $id => $shares) {
198
-				$this->cachedShares[$id] = $shares;
199
-			}
200
-		}
201
-
202
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
203
-			$shares = $this->getShares($sabreNode);
204
-
205
-			$shareTypes = array_unique(array_map(function (IShare $share) {
206
-				return $share->getShareType();
207
-			}, $shares));
208
-
209
-			return new ShareTypeList($shareTypes);
210
-		});
211
-
212
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
213
-			$shares = $this->getShares($sabreNode);
214
-
215
-			return new ShareeList($shares);
216
-		});
217
-	}
40
+    public const NS_OWNCLOUD = 'http://owncloud.org/ns';
41
+    public const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
42
+    public const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
43
+    public const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
44
+
45
+    /**
46
+     * Reference to main server object
47
+     *
48
+     * @var \Sabre\DAV\Server
49
+     */
50
+    private $server;
51
+
52
+    /**
53
+     * @var \OCP\Share\IManager
54
+     */
55
+    private $shareManager;
56
+
57
+    /**
58
+     * @var \Sabre\DAV\Tree
59
+     */
60
+    private $tree;
61
+
62
+    /**
63
+     * @var string
64
+     */
65
+    private $userId;
66
+
67
+    /**
68
+     * @var \OCP\Files\Folder
69
+     */
70
+    private $userFolder;
71
+
72
+    /** @var IShare[] */
73
+    private $cachedShares = [];
74
+
75
+    private $cachedFolders = [];
76
+
77
+    /**
78
+     * @param \Sabre\DAV\Tree $tree tree
79
+     * @param IUserSession $userSession user session
80
+     * @param \OCP\Files\Folder $userFolder user home folder
81
+     * @param \OCP\Share\IManager $shareManager share manager
82
+     */
83
+    public function __construct(
84
+        \Sabre\DAV\Tree $tree,
85
+        IUserSession $userSession,
86
+        \OCP\Files\Folder $userFolder,
87
+        \OCP\Share\IManager $shareManager
88
+    ) {
89
+        $this->tree = $tree;
90
+        $this->shareManager = $shareManager;
91
+        $this->userFolder = $userFolder;
92
+        $this->userId = $userSession->getUser()->getUID();
93
+    }
94
+
95
+    /**
96
+     * This initializes the plugin.
97
+     *
98
+     * This function is called by \Sabre\DAV\Server, after
99
+     * addPlugin is called.
100
+     *
101
+     * This method should set up the required event subscriptions.
102
+     *
103
+     * @param \Sabre\DAV\Server $server
104
+     */
105
+    public function initialize(\Sabre\DAV\Server $server) {
106
+        $server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
107
+        $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
108
+        $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
109
+        $server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
110
+
111
+        $this->server = $server;
112
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
113
+    }
114
+
115
+    private function getShare(\OCP\Files\Node $node): array {
116
+        $result = [];
117
+        $requestedShareTypes = [
118
+            IShare::TYPE_USER,
119
+            IShare::TYPE_GROUP,
120
+            IShare::TYPE_LINK,
121
+            IShare::TYPE_REMOTE,
122
+            IShare::TYPE_EMAIL,
123
+            IShare::TYPE_ROOM,
124
+            IShare::TYPE_CIRCLE,
125
+            IShare::TYPE_DECK,
126
+        ];
127
+        foreach ($requestedShareTypes as $requestedShareType) {
128
+            $shares = $this->shareManager->getSharesBy(
129
+                $this->userId,
130
+                $requestedShareType,
131
+                $node,
132
+                false,
133
+                -1
134
+            );
135
+            foreach ($shares as $share) {
136
+                $result[] = $share;
137
+            }
138
+        }
139
+        return $result;
140
+    }
141
+
142
+    private function getSharesFolder(\OCP\Files\Folder $node): array {
143
+        return $this->shareManager->getSharesInFolder(
144
+            $this->userId,
145
+            $node,
146
+            true
147
+        );
148
+    }
149
+
150
+    private function getShares(\Sabre\DAV\INode $sabreNode): array {
151
+        if (isset($this->cachedShares[$sabreNode->getId()])) {
152
+            $shares = $this->cachedShares[$sabreNode->getId()];
153
+        } else {
154
+            [$parentPath,] = \Sabre\Uri\split($sabreNode->getPath());
155
+            if ($parentPath === '') {
156
+                $parentPath = '/';
157
+            }
158
+            // if we already cached the folder this file is in we know there are no shares for this file
159
+            if (array_search($parentPath, $this->cachedFolders) === false) {
160
+                $node = $this->userFolder->get($sabreNode->getPath());
161
+                $shares = $this->getShare($node);
162
+                $this->cachedShares[$sabreNode->getId()] = $shares;
163
+            } else {
164
+                return [];
165
+            }
166
+        }
167
+
168
+        return $shares;
169
+    }
170
+
171
+    /**
172
+     * Adds shares to propfind response
173
+     *
174
+     * @param PropFind $propFind propfind object
175
+     * @param \Sabre\DAV\INode $sabreNode sabre node
176
+     */
177
+    public function handleGetProperties(
178
+        PropFind $propFind,
179
+        \Sabre\DAV\INode $sabreNode
180
+    ) {
181
+        if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
182
+            return;
183
+        }
184
+
185
+        // need prefetch ?
186
+        if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
187
+            && $propFind->getDepth() !== 0
188
+            && (
189
+                !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
190
+                !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
191
+            )
192
+        ) {
193
+            $folderNode = $this->userFolder->get($sabreNode->getPath());
194
+
195
+            $this->cachedFolders[] = $sabreNode->getPath();
196
+            $childShares = $this->getSharesFolder($folderNode);
197
+            foreach ($childShares as $id => $shares) {
198
+                $this->cachedShares[$id] = $shares;
199
+            }
200
+        }
201
+
202
+        $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
203
+            $shares = $this->getShares($sabreNode);
204
+
205
+            $shareTypes = array_unique(array_map(function (IShare $share) {
206
+                return $share->getShareType();
207
+            }, $shares));
208
+
209
+            return new ShareTypeList($shareTypes);
210
+        });
211
+
212
+        $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
213
+            $shares = $this->getShares($sabreNode);
214
+
215
+            return new ShareeList($shares);
216
+        });
217
+    }
218 218
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 		if (isset($this->cachedShares[$sabreNode->getId()])) {
152 152
 			$shares = $this->cachedShares[$sabreNode->getId()];
153 153
 		} else {
154
-			[$parentPath,] = \Sabre\Uri\split($sabreNode->getPath());
154
+			[$parentPath, ] = \Sabre\Uri\split($sabreNode->getPath());
155 155
 			if ($parentPath === '') {
156 156
 				$parentPath = '/';
157 157
 			}
@@ -199,17 +199,17 @@  discard block
 block discarded – undo
199 199
 			}
200 200
 		}
201 201
 
202
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
202
+		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function() use ($sabreNode) {
203 203
 			$shares = $this->getShares($sabreNode);
204 204
 
205
-			$shareTypes = array_unique(array_map(function (IShare $share) {
205
+			$shareTypes = array_unique(array_map(function(IShare $share) {
206 206
 				return $share->getShareType();
207 207
 			}, $shares));
208 208
 
209 209
 			return new ShareTypeList($shareTypes);
210 210
 		});
211 211
 
212
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
212
+		$propFind->handle(self::SHAREES_PROPERTYNAME, function() use ($sabreNode) {
213 213
 			$shares = $this->getShares($sabreNode);
214 214
 
215 215
 			return new ShareeList($shares);
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Principal.php 1 patch
Indentation   +496 added lines, -496 removed lines patch added patch discarded remove patch
@@ -55,500 +55,500 @@
 block discarded – undo
55 55
 
56 56
 class Principal implements BackendInterface {
57 57
 
58
-	/** @var IUserManager */
59
-	private $userManager;
60
-
61
-	/** @var IGroupManager */
62
-	private $groupManager;
63
-
64
-	/** @var IShareManager */
65
-	private $shareManager;
66
-
67
-	/** @var IUserSession */
68
-	private $userSession;
69
-
70
-	/** @var IAppManager */
71
-	private $appManager;
72
-
73
-	/** @var string */
74
-	private $principalPrefix;
75
-
76
-	/** @var bool */
77
-	private $hasGroups;
78
-
79
-	/** @var bool */
80
-	private $hasCircles;
81
-
82
-	/** @var ProxyMapper */
83
-	private $proxyMapper;
84
-
85
-	/** @var IConfig */
86
-	private $config;
87
-
88
-	/**
89
-	 * Principal constructor.
90
-	 *
91
-	 * @param IUserManager $userManager
92
-	 * @param IGroupManager $groupManager
93
-	 * @param IShareManager $shareManager
94
-	 * @param IUserSession $userSession
95
-	 * @param IAppManager $appManager
96
-	 * @param ProxyMapper $proxyMapper
97
-	 * @param IConfig $config
98
-	 * @param string $principalPrefix
99
-	 */
100
-	public function __construct(IUserManager $userManager,
101
-								IGroupManager $groupManager,
102
-								IShareManager $shareManager,
103
-								IUserSession $userSession,
104
-								IAppManager $appManager,
105
-								ProxyMapper $proxyMapper,
106
-								IConfig $config,
107
-								string $principalPrefix = 'principals/users/') {
108
-		$this->userManager = $userManager;
109
-		$this->groupManager = $groupManager;
110
-		$this->shareManager = $shareManager;
111
-		$this->userSession = $userSession;
112
-		$this->appManager = $appManager;
113
-		$this->principalPrefix = trim($principalPrefix, '/');
114
-		$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
115
-		$this->proxyMapper = $proxyMapper;
116
-		$this->config = $config;
117
-	}
118
-
119
-	use PrincipalProxyTrait {
120
-		getGroupMembership as protected traitGetGroupMembership;
121
-	}
122
-
123
-	/**
124
-	 * Returns a list of principals based on a prefix.
125
-	 *
126
-	 * This prefix will often contain something like 'principals'. You are only
127
-	 * expected to return principals that are in this base path.
128
-	 *
129
-	 * You are expected to return at least a 'uri' for every user, you can
130
-	 * return any additional properties if you wish so. Common properties are:
131
-	 *   {DAV:}displayname
132
-	 *
133
-	 * @param string $prefixPath
134
-	 * @return string[]
135
-	 */
136
-	public function getPrincipalsByPrefix($prefixPath) {
137
-		$principals = [];
138
-
139
-		if ($prefixPath === $this->principalPrefix) {
140
-			foreach ($this->userManager->search('') as $user) {
141
-				$principals[] = $this->userToPrincipal($user);
142
-			}
143
-		}
144
-
145
-		return $principals;
146
-	}
147
-
148
-	/**
149
-	 * Returns a specific principal, specified by it's path.
150
-	 * The returned structure should be the exact same as from
151
-	 * getPrincipalsByPrefix.
152
-	 *
153
-	 * @param string $path
154
-	 * @return array
155
-	 */
156
-	public function getPrincipalByPath($path) {
157
-		[$prefix, $name] = \Sabre\Uri\split($path);
158
-		$decodedName = urldecode($name);
159
-
160
-		if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
161
-			[$prefix2, $name2] = \Sabre\Uri\split($prefix);
162
-
163
-			if ($prefix2 === $this->principalPrefix) {
164
-				$user = $this->userManager->get($name2);
165
-
166
-				if ($user !== null) {
167
-					return [
168
-						'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
169
-					];
170
-				}
171
-				return null;
172
-			}
173
-		}
174
-
175
-		if ($prefix === $this->principalPrefix) {
176
-			// Depending on where it is called, it may happen that this function
177
-			// is called either with a urlencoded version of the name or with a non-urlencoded one.
178
-			// The urldecode function replaces %## and +, both of which are forbidden in usernames.
179
-			// Hence there can be no ambiguity here and it is safe to call urldecode on all usernames
180
-			$user = $this->userManager->get($decodedName);
181
-
182
-			if ($user !== null) {
183
-				return $this->userToPrincipal($user);
184
-			}
185
-		} elseif ($prefix === 'principals/circles') {
186
-			if ($this->userSession->getUser() !== null) {
187
-				// At the time of writing - 2021-01-19 — a mixed state is possible.
188
-				// The second condition can be removed when this is fixed.
189
-				return $this->circleToPrincipal($decodedName)
190
-					?: $this->circleToPrincipal($name);
191
-			}
192
-		} elseif ($prefix === 'principals/groups') {
193
-			// At the time of writing - 2021-01-19 — a mixed state is possible.
194
-			// The second condition can be removed when this is fixed.
195
-			$group = $this->groupManager->get($decodedName)
196
-				?: $this->groupManager->get($name);
197
-			if ($group instanceof IGroup) {
198
-				return [
199
-					'uri' => 'principals/groups/' . $name,
200
-					'{DAV:}displayname' => $group->getDisplayName(),
201
-				];
202
-			}
203
-		}
204
-		return null;
205
-	}
206
-
207
-	/**
208
-	 * Returns the list of groups a principal is a member of
209
-	 *
210
-	 * @param string $principal
211
-	 * @param bool $needGroups
212
-	 * @return array
213
-	 * @throws Exception
214
-	 */
215
-	public function getGroupMembership($principal, $needGroups = false) {
216
-		[$prefix, $name] = \Sabre\Uri\split($principal);
217
-
218
-		if ($prefix !== $this->principalPrefix) {
219
-			return [];
220
-		}
221
-
222
-		$user = $this->userManager->get($name);
223
-		if (!$user) {
224
-			throw new Exception('Principal not found');
225
-		}
226
-
227
-		$groups = [];
228
-
229
-		if ($this->hasGroups || $needGroups) {
230
-			$userGroups = $this->groupManager->getUserGroups($user);
231
-			foreach ($userGroups as $userGroup) {
232
-				$groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
233
-			}
234
-		}
235
-
236
-		$groups = array_unique(array_merge(
237
-			$groups,
238
-			$this->traitGetGroupMembership($principal, $needGroups)
239
-		));
240
-
241
-		return $groups;
242
-	}
243
-
244
-	/**
245
-	 * @param string $path
246
-	 * @param PropPatch $propPatch
247
-	 * @return int
248
-	 */
249
-	public function updatePrincipal($path, PropPatch $propPatch) {
250
-		return 0;
251
-	}
252
-
253
-	/**
254
-	 * Search user principals
255
-	 *
256
-	 * @param array $searchProperties
257
-	 * @param string $test
258
-	 * @return array
259
-	 */
260
-	protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
261
-		$results = [];
262
-
263
-		// If sharing is disabled, return the empty array
264
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
265
-		if (!$shareAPIEnabled) {
266
-			return [];
267
-		}
268
-
269
-		$allowEnumeration = $this->shareManager->allowEnumeration();
270
-		$limitEnumeration = $this->shareManager->limitEnumerationToGroups();
271
-
272
-		// If sharing is restricted to group members only,
273
-		// return only members that have groups in common
274
-		$restrictGroups = false;
275
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
276
-			$user = $this->userSession->getUser();
277
-			if (!$user) {
278
-				return [];
279
-			}
280
-
281
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
282
-		}
283
-
284
-		$currentUserGroups = [];
285
-		if ($limitEnumeration) {
286
-			$currentUser = $this->userSession->getUser();
287
-			if ($currentUser) {
288
-				$currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
289
-			}
290
-		}
291
-
292
-		$searchLimit = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT);
293
-		if ($searchLimit <= 0) {
294
-			$searchLimit = null;
295
-		}
296
-		foreach ($searchProperties as $prop => $value) {
297
-			switch ($prop) {
298
-				case '{http://sabredav.org/ns}email-address':
299
-					$users = $this->userManager->getByEmail($value);
300
-
301
-					if (!$allowEnumeration) {
302
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
303
-							return $user->getEMailAddress() === $value;
304
-						});
305
-					}
306
-
307
-					if ($limitEnumeration) {
308
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
309
-							return !empty(array_intersect(
310
-									$this->groupManager->getUserGroupIds($user),
311
-									$currentUserGroups
312
-								)) || $user->getEMailAddress() === $value;
313
-						});
314
-					}
315
-
316
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
317
-						// is sharing restricted to groups only?
318
-						if ($restrictGroups !== false) {
319
-							$userGroups = $this->groupManager->getUserGroupIds($user);
320
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
321
-								return $carry;
322
-							}
323
-						}
324
-
325
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
326
-						return $carry;
327
-					}, []);
328
-					break;
329
-
330
-				case '{DAV:}displayname':
331
-					$users = $this->userManager->searchDisplayName($value, $searchLimit);
332
-
333
-					if (!$allowEnumeration) {
334
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
335
-							return $user->getDisplayName() === $value;
336
-						});
337
-					}
338
-
339
-					if ($limitEnumeration) {
340
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
341
-							return !empty(array_intersect(
342
-									$this->groupManager->getUserGroupIds($user),
343
-									$currentUserGroups
344
-								)) || $user->getDisplayName() === $value;
345
-						});
346
-					}
347
-
348
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
349
-						// is sharing restricted to groups only?
350
-						if ($restrictGroups !== false) {
351
-							$userGroups = $this->groupManager->getUserGroupIds($user);
352
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
353
-								return $carry;
354
-							}
355
-						}
356
-
357
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
358
-						return $carry;
359
-					}, []);
360
-					break;
361
-
362
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
363
-					// If you add support for more search properties that qualify as a user-address,
364
-					// please also add them to the array below
365
-					$results[] = $this->searchUserPrincipals([
366
-						// In theory this should also search for principal:principals/users/...
367
-						// but that's used internally only anyway and i don't know of any client querying that
368
-						'{http://sabredav.org/ns}email-address' => $value,
369
-					], 'anyof');
370
-					break;
371
-
372
-				default:
373
-					$results[] = [];
374
-					break;
375
-			}
376
-		}
377
-
378
-		// results is an array of arrays, so this is not the first search result
379
-		// but the results of the first searchProperty
380
-		if (count($results) === 1) {
381
-			return $results[0];
382
-		}
383
-
384
-		switch ($test) {
385
-			case 'anyof':
386
-				return array_values(array_unique(array_merge(...$results)));
387
-
388
-			case 'allof':
389
-			default:
390
-				return array_values(array_intersect(...$results));
391
-		}
392
-	}
393
-
394
-	/**
395
-	 * @param string $prefixPath
396
-	 * @param array $searchProperties
397
-	 * @param string $test
398
-	 * @return array
399
-	 */
400
-	public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
401
-		if (count($searchProperties) === 0) {
402
-			return [];
403
-		}
404
-
405
-		switch ($prefixPath) {
406
-			case 'principals/users':
407
-				return $this->searchUserPrincipals($searchProperties, $test);
408
-
409
-			default:
410
-				return [];
411
-		}
412
-	}
413
-
414
-	/**
415
-	 * @param string $uri
416
-	 * @param string $principalPrefix
417
-	 * @return string
418
-	 */
419
-	public function findByUri($uri, $principalPrefix) {
420
-		// If sharing is disabled, return the empty array
421
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
422
-		if (!$shareAPIEnabled) {
423
-			return null;
424
-		}
425
-
426
-		// If sharing is restricted to group members only,
427
-		// return only members that have groups in common
428
-		$restrictGroups = false;
429
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
430
-			$user = $this->userSession->getUser();
431
-			if (!$user) {
432
-				return null;
433
-			}
434
-
435
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
436
-		}
437
-
438
-		if (strpos($uri, 'mailto:') === 0) {
439
-			if ($principalPrefix === 'principals/users') {
440
-				$users = $this->userManager->getByEmail(substr($uri, 7));
441
-				if (count($users) !== 1) {
442
-					return null;
443
-				}
444
-				$user = $users[0];
445
-
446
-				if ($restrictGroups !== false) {
447
-					$userGroups = $this->groupManager->getUserGroupIds($user);
448
-					if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
449
-						return null;
450
-					}
451
-				}
452
-
453
-				return $this->principalPrefix . '/' . $user->getUID();
454
-			}
455
-		}
456
-		if (substr($uri, 0, 10) === 'principal:') {
457
-			$principal = substr($uri, 10);
458
-			$principal = $this->getPrincipalByPath($principal);
459
-			if ($principal !== null) {
460
-				return $principal['uri'];
461
-			}
462
-		}
463
-
464
-		return null;
465
-	}
466
-
467
-	/**
468
-	 * @param IUser $user
469
-	 * @return array
470
-	 */
471
-	protected function userToPrincipal($user) {
472
-		$userId = $user->getUID();
473
-		$displayName = $user->getDisplayName();
474
-		$principal = [
475
-			'uri' => $this->principalPrefix . '/' . $userId,
476
-			'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
477
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
478
-		];
479
-
480
-		$email = $user->getEMailAddress();
481
-		if (!empty($email)) {
482
-			$principal['{http://sabredav.org/ns}email-address'] = $email;
483
-		}
484
-
485
-		return $principal;
486
-	}
487
-
488
-	public function getPrincipalPrefix() {
489
-		return $this->principalPrefix;
490
-	}
491
-
492
-	/**
493
-	 * @param string $circleUniqueId
494
-	 * @return array|null
495
-	 */
496
-	protected function circleToPrincipal($circleUniqueId) {
497
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
498
-			return null;
499
-		}
500
-
501
-		try {
502
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
503
-		} catch (QueryException $ex) {
504
-			return null;
505
-		} catch (CircleDoesNotExistException $ex) {
506
-			return null;
507
-		}
508
-
509
-		if (!$circle) {
510
-			return null;
511
-		}
512
-
513
-		$principal = [
514
-			'uri' => 'principals/circles/' . $circleUniqueId,
515
-			'{DAV:}displayname' => $circle->getName(),
516
-		];
517
-
518
-		return $principal;
519
-	}
520
-
521
-	/**
522
-	 * Returns the list of circles a principal is a member of
523
-	 *
524
-	 * @param string $principal
525
-	 * @return array
526
-	 * @throws Exception
527
-	 * @throws \OCP\AppFramework\QueryException
528
-	 * @suppress PhanUndeclaredClassMethod
529
-	 */
530
-	public function getCircleMembership($principal):array {
531
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
532
-			return [];
533
-		}
534
-
535
-		[$prefix, $name] = \Sabre\Uri\split($principal);
536
-		if ($this->hasCircles && $prefix === $this->principalPrefix) {
537
-			$user = $this->userManager->get($name);
538
-			if (!$user) {
539
-				throw new Exception('Principal not found');
540
-			}
541
-
542
-			$circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
543
-
544
-			$circles = array_map(function ($circle) {
545
-				/** @var \OCA\Circles\Model\Circle $circle */
546
-				return 'principals/circles/' . urlencode($circle->getUniqueId());
547
-			}, $circles);
548
-
549
-			return $circles;
550
-		}
551
-
552
-		return [];
553
-	}
58
+    /** @var IUserManager */
59
+    private $userManager;
60
+
61
+    /** @var IGroupManager */
62
+    private $groupManager;
63
+
64
+    /** @var IShareManager */
65
+    private $shareManager;
66
+
67
+    /** @var IUserSession */
68
+    private $userSession;
69
+
70
+    /** @var IAppManager */
71
+    private $appManager;
72
+
73
+    /** @var string */
74
+    private $principalPrefix;
75
+
76
+    /** @var bool */
77
+    private $hasGroups;
78
+
79
+    /** @var bool */
80
+    private $hasCircles;
81
+
82
+    /** @var ProxyMapper */
83
+    private $proxyMapper;
84
+
85
+    /** @var IConfig */
86
+    private $config;
87
+
88
+    /**
89
+     * Principal constructor.
90
+     *
91
+     * @param IUserManager $userManager
92
+     * @param IGroupManager $groupManager
93
+     * @param IShareManager $shareManager
94
+     * @param IUserSession $userSession
95
+     * @param IAppManager $appManager
96
+     * @param ProxyMapper $proxyMapper
97
+     * @param IConfig $config
98
+     * @param string $principalPrefix
99
+     */
100
+    public function __construct(IUserManager $userManager,
101
+                                IGroupManager $groupManager,
102
+                                IShareManager $shareManager,
103
+                                IUserSession $userSession,
104
+                                IAppManager $appManager,
105
+                                ProxyMapper $proxyMapper,
106
+                                IConfig $config,
107
+                                string $principalPrefix = 'principals/users/') {
108
+        $this->userManager = $userManager;
109
+        $this->groupManager = $groupManager;
110
+        $this->shareManager = $shareManager;
111
+        $this->userSession = $userSession;
112
+        $this->appManager = $appManager;
113
+        $this->principalPrefix = trim($principalPrefix, '/');
114
+        $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
115
+        $this->proxyMapper = $proxyMapper;
116
+        $this->config = $config;
117
+    }
118
+
119
+    use PrincipalProxyTrait {
120
+        getGroupMembership as protected traitGetGroupMembership;
121
+    }
122
+
123
+    /**
124
+     * Returns a list of principals based on a prefix.
125
+     *
126
+     * This prefix will often contain something like 'principals'. You are only
127
+     * expected to return principals that are in this base path.
128
+     *
129
+     * You are expected to return at least a 'uri' for every user, you can
130
+     * return any additional properties if you wish so. Common properties are:
131
+     *   {DAV:}displayname
132
+     *
133
+     * @param string $prefixPath
134
+     * @return string[]
135
+     */
136
+    public function getPrincipalsByPrefix($prefixPath) {
137
+        $principals = [];
138
+
139
+        if ($prefixPath === $this->principalPrefix) {
140
+            foreach ($this->userManager->search('') as $user) {
141
+                $principals[] = $this->userToPrincipal($user);
142
+            }
143
+        }
144
+
145
+        return $principals;
146
+    }
147
+
148
+    /**
149
+     * Returns a specific principal, specified by it's path.
150
+     * The returned structure should be the exact same as from
151
+     * getPrincipalsByPrefix.
152
+     *
153
+     * @param string $path
154
+     * @return array
155
+     */
156
+    public function getPrincipalByPath($path) {
157
+        [$prefix, $name] = \Sabre\Uri\split($path);
158
+        $decodedName = urldecode($name);
159
+
160
+        if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
161
+            [$prefix2, $name2] = \Sabre\Uri\split($prefix);
162
+
163
+            if ($prefix2 === $this->principalPrefix) {
164
+                $user = $this->userManager->get($name2);
165
+
166
+                if ($user !== null) {
167
+                    return [
168
+                        'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
169
+                    ];
170
+                }
171
+                return null;
172
+            }
173
+        }
174
+
175
+        if ($prefix === $this->principalPrefix) {
176
+            // Depending on where it is called, it may happen that this function
177
+            // is called either with a urlencoded version of the name or with a non-urlencoded one.
178
+            // The urldecode function replaces %## and +, both of which are forbidden in usernames.
179
+            // Hence there can be no ambiguity here and it is safe to call urldecode on all usernames
180
+            $user = $this->userManager->get($decodedName);
181
+
182
+            if ($user !== null) {
183
+                return $this->userToPrincipal($user);
184
+            }
185
+        } elseif ($prefix === 'principals/circles') {
186
+            if ($this->userSession->getUser() !== null) {
187
+                // At the time of writing - 2021-01-19 — a mixed state is possible.
188
+                // The second condition can be removed when this is fixed.
189
+                return $this->circleToPrincipal($decodedName)
190
+                    ?: $this->circleToPrincipal($name);
191
+            }
192
+        } elseif ($prefix === 'principals/groups') {
193
+            // At the time of writing - 2021-01-19 — a mixed state is possible.
194
+            // The second condition can be removed when this is fixed.
195
+            $group = $this->groupManager->get($decodedName)
196
+                ?: $this->groupManager->get($name);
197
+            if ($group instanceof IGroup) {
198
+                return [
199
+                    'uri' => 'principals/groups/' . $name,
200
+                    '{DAV:}displayname' => $group->getDisplayName(),
201
+                ];
202
+            }
203
+        }
204
+        return null;
205
+    }
206
+
207
+    /**
208
+     * Returns the list of groups a principal is a member of
209
+     *
210
+     * @param string $principal
211
+     * @param bool $needGroups
212
+     * @return array
213
+     * @throws Exception
214
+     */
215
+    public function getGroupMembership($principal, $needGroups = false) {
216
+        [$prefix, $name] = \Sabre\Uri\split($principal);
217
+
218
+        if ($prefix !== $this->principalPrefix) {
219
+            return [];
220
+        }
221
+
222
+        $user = $this->userManager->get($name);
223
+        if (!$user) {
224
+            throw new Exception('Principal not found');
225
+        }
226
+
227
+        $groups = [];
228
+
229
+        if ($this->hasGroups || $needGroups) {
230
+            $userGroups = $this->groupManager->getUserGroups($user);
231
+            foreach ($userGroups as $userGroup) {
232
+                $groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
233
+            }
234
+        }
235
+
236
+        $groups = array_unique(array_merge(
237
+            $groups,
238
+            $this->traitGetGroupMembership($principal, $needGroups)
239
+        ));
240
+
241
+        return $groups;
242
+    }
243
+
244
+    /**
245
+     * @param string $path
246
+     * @param PropPatch $propPatch
247
+     * @return int
248
+     */
249
+    public function updatePrincipal($path, PropPatch $propPatch) {
250
+        return 0;
251
+    }
252
+
253
+    /**
254
+     * Search user principals
255
+     *
256
+     * @param array $searchProperties
257
+     * @param string $test
258
+     * @return array
259
+     */
260
+    protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
261
+        $results = [];
262
+
263
+        // If sharing is disabled, return the empty array
264
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
265
+        if (!$shareAPIEnabled) {
266
+            return [];
267
+        }
268
+
269
+        $allowEnumeration = $this->shareManager->allowEnumeration();
270
+        $limitEnumeration = $this->shareManager->limitEnumerationToGroups();
271
+
272
+        // If sharing is restricted to group members only,
273
+        // return only members that have groups in common
274
+        $restrictGroups = false;
275
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
276
+            $user = $this->userSession->getUser();
277
+            if (!$user) {
278
+                return [];
279
+            }
280
+
281
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
282
+        }
283
+
284
+        $currentUserGroups = [];
285
+        if ($limitEnumeration) {
286
+            $currentUser = $this->userSession->getUser();
287
+            if ($currentUser) {
288
+                $currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
289
+            }
290
+        }
291
+
292
+        $searchLimit = $this->config->getSystemValueInt('sharing.maxAutocompleteResults', Constants::SHARING_MAX_AUTOCOMPLETE_RESULTS_DEFAULT);
293
+        if ($searchLimit <= 0) {
294
+            $searchLimit = null;
295
+        }
296
+        foreach ($searchProperties as $prop => $value) {
297
+            switch ($prop) {
298
+                case '{http://sabredav.org/ns}email-address':
299
+                    $users = $this->userManager->getByEmail($value);
300
+
301
+                    if (!$allowEnumeration) {
302
+                        $users = \array_filter($users, static function (IUser $user) use ($value) {
303
+                            return $user->getEMailAddress() === $value;
304
+                        });
305
+                    }
306
+
307
+                    if ($limitEnumeration) {
308
+                        $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
309
+                            return !empty(array_intersect(
310
+                                    $this->groupManager->getUserGroupIds($user),
311
+                                    $currentUserGroups
312
+                                )) || $user->getEMailAddress() === $value;
313
+                        });
314
+                    }
315
+
316
+                    $results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
317
+                        // is sharing restricted to groups only?
318
+                        if ($restrictGroups !== false) {
319
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
320
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
321
+                                return $carry;
322
+                            }
323
+                        }
324
+
325
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
326
+                        return $carry;
327
+                    }, []);
328
+                    break;
329
+
330
+                case '{DAV:}displayname':
331
+                    $users = $this->userManager->searchDisplayName($value, $searchLimit);
332
+
333
+                    if (!$allowEnumeration) {
334
+                        $users = \array_filter($users, static function (IUser $user) use ($value) {
335
+                            return $user->getDisplayName() === $value;
336
+                        });
337
+                    }
338
+
339
+                    if ($limitEnumeration) {
340
+                        $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
341
+                            return !empty(array_intersect(
342
+                                    $this->groupManager->getUserGroupIds($user),
343
+                                    $currentUserGroups
344
+                                )) || $user->getDisplayName() === $value;
345
+                        });
346
+                    }
347
+
348
+                    $results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
349
+                        // is sharing restricted to groups only?
350
+                        if ($restrictGroups !== false) {
351
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
352
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
353
+                                return $carry;
354
+                            }
355
+                        }
356
+
357
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
358
+                        return $carry;
359
+                    }, []);
360
+                    break;
361
+
362
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
363
+                    // If you add support for more search properties that qualify as a user-address,
364
+                    // please also add them to the array below
365
+                    $results[] = $this->searchUserPrincipals([
366
+                        // In theory this should also search for principal:principals/users/...
367
+                        // but that's used internally only anyway and i don't know of any client querying that
368
+                        '{http://sabredav.org/ns}email-address' => $value,
369
+                    ], 'anyof');
370
+                    break;
371
+
372
+                default:
373
+                    $results[] = [];
374
+                    break;
375
+            }
376
+        }
377
+
378
+        // results is an array of arrays, so this is not the first search result
379
+        // but the results of the first searchProperty
380
+        if (count($results) === 1) {
381
+            return $results[0];
382
+        }
383
+
384
+        switch ($test) {
385
+            case 'anyof':
386
+                return array_values(array_unique(array_merge(...$results)));
387
+
388
+            case 'allof':
389
+            default:
390
+                return array_values(array_intersect(...$results));
391
+        }
392
+    }
393
+
394
+    /**
395
+     * @param string $prefixPath
396
+     * @param array $searchProperties
397
+     * @param string $test
398
+     * @return array
399
+     */
400
+    public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
401
+        if (count($searchProperties) === 0) {
402
+            return [];
403
+        }
404
+
405
+        switch ($prefixPath) {
406
+            case 'principals/users':
407
+                return $this->searchUserPrincipals($searchProperties, $test);
408
+
409
+            default:
410
+                return [];
411
+        }
412
+    }
413
+
414
+    /**
415
+     * @param string $uri
416
+     * @param string $principalPrefix
417
+     * @return string
418
+     */
419
+    public function findByUri($uri, $principalPrefix) {
420
+        // If sharing is disabled, return the empty array
421
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
422
+        if (!$shareAPIEnabled) {
423
+            return null;
424
+        }
425
+
426
+        // If sharing is restricted to group members only,
427
+        // return only members that have groups in common
428
+        $restrictGroups = false;
429
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
430
+            $user = $this->userSession->getUser();
431
+            if (!$user) {
432
+                return null;
433
+            }
434
+
435
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
436
+        }
437
+
438
+        if (strpos($uri, 'mailto:') === 0) {
439
+            if ($principalPrefix === 'principals/users') {
440
+                $users = $this->userManager->getByEmail(substr($uri, 7));
441
+                if (count($users) !== 1) {
442
+                    return null;
443
+                }
444
+                $user = $users[0];
445
+
446
+                if ($restrictGroups !== false) {
447
+                    $userGroups = $this->groupManager->getUserGroupIds($user);
448
+                    if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
449
+                        return null;
450
+                    }
451
+                }
452
+
453
+                return $this->principalPrefix . '/' . $user->getUID();
454
+            }
455
+        }
456
+        if (substr($uri, 0, 10) === 'principal:') {
457
+            $principal = substr($uri, 10);
458
+            $principal = $this->getPrincipalByPath($principal);
459
+            if ($principal !== null) {
460
+                return $principal['uri'];
461
+            }
462
+        }
463
+
464
+        return null;
465
+    }
466
+
467
+    /**
468
+     * @param IUser $user
469
+     * @return array
470
+     */
471
+    protected function userToPrincipal($user) {
472
+        $userId = $user->getUID();
473
+        $displayName = $user->getDisplayName();
474
+        $principal = [
475
+            'uri' => $this->principalPrefix . '/' . $userId,
476
+            '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
477
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
478
+        ];
479
+
480
+        $email = $user->getEMailAddress();
481
+        if (!empty($email)) {
482
+            $principal['{http://sabredav.org/ns}email-address'] = $email;
483
+        }
484
+
485
+        return $principal;
486
+    }
487
+
488
+    public function getPrincipalPrefix() {
489
+        return $this->principalPrefix;
490
+    }
491
+
492
+    /**
493
+     * @param string $circleUniqueId
494
+     * @return array|null
495
+     */
496
+    protected function circleToPrincipal($circleUniqueId) {
497
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
498
+            return null;
499
+        }
500
+
501
+        try {
502
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
503
+        } catch (QueryException $ex) {
504
+            return null;
505
+        } catch (CircleDoesNotExistException $ex) {
506
+            return null;
507
+        }
508
+
509
+        if (!$circle) {
510
+            return null;
511
+        }
512
+
513
+        $principal = [
514
+            'uri' => 'principals/circles/' . $circleUniqueId,
515
+            '{DAV:}displayname' => $circle->getName(),
516
+        ];
517
+
518
+        return $principal;
519
+    }
520
+
521
+    /**
522
+     * Returns the list of circles a principal is a member of
523
+     *
524
+     * @param string $principal
525
+     * @return array
526
+     * @throws Exception
527
+     * @throws \OCP\AppFramework\QueryException
528
+     * @suppress PhanUndeclaredClassMethod
529
+     */
530
+    public function getCircleMembership($principal):array {
531
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
532
+            return [];
533
+        }
534
+
535
+        [$prefix, $name] = \Sabre\Uri\split($principal);
536
+        if ($this->hasCircles && $prefix === $this->principalPrefix) {
537
+            $user = $this->userManager->get($name);
538
+            if (!$user) {
539
+                throw new Exception('Principal not found');
540
+            }
541
+
542
+            $circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
543
+
544
+            $circles = array_map(function ($circle) {
545
+                /** @var \OCA\Circles\Model\Circle $circle */
546
+                return 'principals/circles/' . urlencode($circle->getUniqueId());
547
+            }, $circles);
548
+
549
+            return $circles;
550
+        }
551
+
552
+        return [];
553
+    }
554 554
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Node.php 2 patches
Indentation   +363 added lines, -363 removed lines patch added patch discarded remove patch
@@ -48,372 +48,372 @@
 block discarded – undo
48 48
 
49 49
 abstract class Node implements \Sabre\DAV\INode {
50 50
 
51
-	/**
52
-	 * @var \OC\Files\View
53
-	 */
54
-	protected $fileView;
55
-
56
-	/**
57
-	 * The path to the current node
58
-	 *
59
-	 * @var string
60
-	 */
61
-	protected $path;
62
-
63
-	/**
64
-	 * node properties cache
65
-	 *
66
-	 * @var array
67
-	 */
68
-	protected $property_cache = null;
69
-
70
-	/**
71
-	 * @var \OCP\Files\FileInfo
72
-	 */
73
-	protected $info;
74
-
75
-	/**
76
-	 * @var IManager
77
-	 */
78
-	protected $shareManager;
79
-
80
-	/**
81
-	 * Sets up the node, expects a full path name
82
-	 *
83
-	 * @param \OC\Files\View $view
84
-	 * @param \OCP\Files\FileInfo $info
85
-	 * @param IManager $shareManager
86
-	 */
87
-	public function __construct(View $view, FileInfo $info, IManager $shareManager = null) {
88
-		$this->fileView = $view;
89
-		$this->path = $this->fileView->getRelativePath($info->getPath());
90
-		$this->info = $info;
91
-		if ($shareManager) {
92
-			$this->shareManager = $shareManager;
93
-		} else {
94
-			$this->shareManager = \OC::$server->getShareManager();
95
-		}
96
-	}
97
-
98
-	protected function refreshInfo() {
99
-		$this->info = $this->fileView->getFileInfo($this->path);
100
-	}
101
-
102
-	/**
103
-	 *  Returns the name of the node
104
-	 *
105
-	 * @return string
106
-	 */
107
-	public function getName() {
108
-		return $this->info->getName();
109
-	}
110
-
111
-	/**
112
-	 * Returns the full path
113
-	 *
114
-	 * @return string
115
-	 */
116
-	public function getPath() {
117
-		return $this->path;
118
-	}
119
-
120
-	/**
121
-	 * Renames the node
122
-	 *
123
-	 * @param string $name The new name
124
-	 * @throws \Sabre\DAV\Exception\BadRequest
125
-	 * @throws \Sabre\DAV\Exception\Forbidden
126
-	 */
127
-	public function setName($name) {
128
-
129
-		// rename is only allowed if the update privilege is granted
130
-		if (!$this->info->isUpdateable()) {
131
-			throw new \Sabre\DAV\Exception\Forbidden();
132
-		}
133
-
134
-		[$parentPath,] = \Sabre\Uri\split($this->path);
135
-		[, $newName] = \Sabre\Uri\split($name);
136
-
137
-		// verify path of the target
138
-		$this->verifyPath();
139
-
140
-		$newPath = $parentPath . '/' . $newName;
141
-
142
-		if (!$this->fileView->rename($this->path, $newPath)) {
143
-			throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
144
-		}
145
-
146
-		$this->path = $newPath;
147
-
148
-		$this->refreshInfo();
149
-	}
150
-
151
-	public function setPropertyCache($property_cache) {
152
-		$this->property_cache = $property_cache;
153
-	}
154
-
155
-	/**
156
-	 * Returns the last modification time, as a unix timestamp
157
-	 *
158
-	 * @return int timestamp as integer
159
-	 */
160
-	public function getLastModified() {
161
-		$timestamp = $this->info->getMtime();
162
-		if (!empty($timestamp)) {
163
-			return (int)$timestamp;
164
-		}
165
-		return $timestamp;
166
-	}
167
-
168
-	/**
169
-	 *  sets the last modification time of the file (mtime) to the value given
170
-	 *  in the second parameter or to now if the second param is empty.
171
-	 *  Even if the modification time is set to a custom value the access time is set to now.
172
-	 */
173
-	public function touch($mtime) {
174
-		$mtime = $this->sanitizeMtime($mtime);
175
-		$this->fileView->touch($this->path, $mtime);
176
-		$this->refreshInfo();
177
-	}
178
-
179
-	/**
180
-	 * Returns the ETag for a file
181
-	 *
182
-	 * An ETag is a unique identifier representing the current version of the
183
-	 * file. If the file changes, the ETag MUST change.  The ETag is an
184
-	 * arbitrary string, but MUST be surrounded by double-quotes.
185
-	 *
186
-	 * Return null if the ETag can not effectively be determined
187
-	 *
188
-	 * @return string
189
-	 */
190
-	public function getETag() {
191
-		return '"' . $this->info->getEtag() . '"';
192
-	}
193
-
194
-	/**
195
-	 * Sets the ETag
196
-	 *
197
-	 * @param string $etag
198
-	 *
199
-	 * @return int file id of updated file or -1 on failure
200
-	 */
201
-	public function setETag($etag) {
202
-		return $this->fileView->putFileInfo($this->path, ['etag' => $etag]);
203
-	}
204
-
205
-	public function setCreationTime(int $time) {
206
-		return $this->fileView->putFileInfo($this->path, ['creation_time' => $time]);
207
-	}
208
-
209
-	public function setUploadTime(int $time) {
210
-		return $this->fileView->putFileInfo($this->path, ['upload_time' => $time]);
211
-	}
212
-
213
-	/**
214
-	 * Returns the size of the node, in bytes
215
-	 *
216
-	 * @return integer
217
-	 */
218
-	public function getSize() {
219
-		return $this->info->getSize();
220
-	}
221
-
222
-	/**
223
-	 * Returns the cache's file id
224
-	 *
225
-	 * @return int
226
-	 */
227
-	public function getId() {
228
-		return $this->info->getId();
229
-	}
230
-
231
-	/**
232
-	 * @return string|null
233
-	 */
234
-	public function getFileId() {
235
-		if ($this->info->getId()) {
236
-			$instanceId = \OC_Util::getInstanceId();
237
-			$id = sprintf('%08d', $this->info->getId());
238
-			return $id . $instanceId;
239
-		}
240
-
241
-		return null;
242
-	}
243
-
244
-	/**
245
-	 * @return integer
246
-	 */
247
-	public function getInternalFileId() {
248
-		return $this->info->getId();
249
-	}
250
-
251
-	/**
252
-	 * @param string $user
253
-	 * @return int
254
-	 */
255
-	public function getSharePermissions($user) {
256
-
257
-		// check of we access a federated share
258
-		if ($user !== null) {
259
-			try {
260
-				$share = $this->shareManager->getShareByToken($user);
261
-				return $share->getPermissions();
262
-			} catch (ShareNotFound $e) {
263
-				// ignore
264
-			}
265
-		}
266
-
267
-		try {
268
-			$storage = $this->info->getStorage();
269
-		} catch (StorageNotAvailableException $e) {
270
-			$storage = null;
271
-		}
272
-
273
-		if ($storage && $storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
274
-			/** @var \OCA\Files_Sharing\SharedStorage $storage */
275
-			$permissions = (int)$storage->getShare()->getPermissions();
276
-		} else {
277
-			$permissions = $this->info->getPermissions();
278
-		}
279
-
280
-		/*
51
+    /**
52
+     * @var \OC\Files\View
53
+     */
54
+    protected $fileView;
55
+
56
+    /**
57
+     * The path to the current node
58
+     *
59
+     * @var string
60
+     */
61
+    protected $path;
62
+
63
+    /**
64
+     * node properties cache
65
+     *
66
+     * @var array
67
+     */
68
+    protected $property_cache = null;
69
+
70
+    /**
71
+     * @var \OCP\Files\FileInfo
72
+     */
73
+    protected $info;
74
+
75
+    /**
76
+     * @var IManager
77
+     */
78
+    protected $shareManager;
79
+
80
+    /**
81
+     * Sets up the node, expects a full path name
82
+     *
83
+     * @param \OC\Files\View $view
84
+     * @param \OCP\Files\FileInfo $info
85
+     * @param IManager $shareManager
86
+     */
87
+    public function __construct(View $view, FileInfo $info, IManager $shareManager = null) {
88
+        $this->fileView = $view;
89
+        $this->path = $this->fileView->getRelativePath($info->getPath());
90
+        $this->info = $info;
91
+        if ($shareManager) {
92
+            $this->shareManager = $shareManager;
93
+        } else {
94
+            $this->shareManager = \OC::$server->getShareManager();
95
+        }
96
+    }
97
+
98
+    protected function refreshInfo() {
99
+        $this->info = $this->fileView->getFileInfo($this->path);
100
+    }
101
+
102
+    /**
103
+     *  Returns the name of the node
104
+     *
105
+     * @return string
106
+     */
107
+    public function getName() {
108
+        return $this->info->getName();
109
+    }
110
+
111
+    /**
112
+     * Returns the full path
113
+     *
114
+     * @return string
115
+     */
116
+    public function getPath() {
117
+        return $this->path;
118
+    }
119
+
120
+    /**
121
+     * Renames the node
122
+     *
123
+     * @param string $name The new name
124
+     * @throws \Sabre\DAV\Exception\BadRequest
125
+     * @throws \Sabre\DAV\Exception\Forbidden
126
+     */
127
+    public function setName($name) {
128
+
129
+        // rename is only allowed if the update privilege is granted
130
+        if (!$this->info->isUpdateable()) {
131
+            throw new \Sabre\DAV\Exception\Forbidden();
132
+        }
133
+
134
+        [$parentPath,] = \Sabre\Uri\split($this->path);
135
+        [, $newName] = \Sabre\Uri\split($name);
136
+
137
+        // verify path of the target
138
+        $this->verifyPath();
139
+
140
+        $newPath = $parentPath . '/' . $newName;
141
+
142
+        if (!$this->fileView->rename($this->path, $newPath)) {
143
+            throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
144
+        }
145
+
146
+        $this->path = $newPath;
147
+
148
+        $this->refreshInfo();
149
+    }
150
+
151
+    public function setPropertyCache($property_cache) {
152
+        $this->property_cache = $property_cache;
153
+    }
154
+
155
+    /**
156
+     * Returns the last modification time, as a unix timestamp
157
+     *
158
+     * @return int timestamp as integer
159
+     */
160
+    public function getLastModified() {
161
+        $timestamp = $this->info->getMtime();
162
+        if (!empty($timestamp)) {
163
+            return (int)$timestamp;
164
+        }
165
+        return $timestamp;
166
+    }
167
+
168
+    /**
169
+     *  sets the last modification time of the file (mtime) to the value given
170
+     *  in the second parameter or to now if the second param is empty.
171
+     *  Even if the modification time is set to a custom value the access time is set to now.
172
+     */
173
+    public function touch($mtime) {
174
+        $mtime = $this->sanitizeMtime($mtime);
175
+        $this->fileView->touch($this->path, $mtime);
176
+        $this->refreshInfo();
177
+    }
178
+
179
+    /**
180
+     * Returns the ETag for a file
181
+     *
182
+     * An ETag is a unique identifier representing the current version of the
183
+     * file. If the file changes, the ETag MUST change.  The ETag is an
184
+     * arbitrary string, but MUST be surrounded by double-quotes.
185
+     *
186
+     * Return null if the ETag can not effectively be determined
187
+     *
188
+     * @return string
189
+     */
190
+    public function getETag() {
191
+        return '"' . $this->info->getEtag() . '"';
192
+    }
193
+
194
+    /**
195
+     * Sets the ETag
196
+     *
197
+     * @param string $etag
198
+     *
199
+     * @return int file id of updated file or -1 on failure
200
+     */
201
+    public function setETag($etag) {
202
+        return $this->fileView->putFileInfo($this->path, ['etag' => $etag]);
203
+    }
204
+
205
+    public function setCreationTime(int $time) {
206
+        return $this->fileView->putFileInfo($this->path, ['creation_time' => $time]);
207
+    }
208
+
209
+    public function setUploadTime(int $time) {
210
+        return $this->fileView->putFileInfo($this->path, ['upload_time' => $time]);
211
+    }
212
+
213
+    /**
214
+     * Returns the size of the node, in bytes
215
+     *
216
+     * @return integer
217
+     */
218
+    public function getSize() {
219
+        return $this->info->getSize();
220
+    }
221
+
222
+    /**
223
+     * Returns the cache's file id
224
+     *
225
+     * @return int
226
+     */
227
+    public function getId() {
228
+        return $this->info->getId();
229
+    }
230
+
231
+    /**
232
+     * @return string|null
233
+     */
234
+    public function getFileId() {
235
+        if ($this->info->getId()) {
236
+            $instanceId = \OC_Util::getInstanceId();
237
+            $id = sprintf('%08d', $this->info->getId());
238
+            return $id . $instanceId;
239
+        }
240
+
241
+        return null;
242
+    }
243
+
244
+    /**
245
+     * @return integer
246
+     */
247
+    public function getInternalFileId() {
248
+        return $this->info->getId();
249
+    }
250
+
251
+    /**
252
+     * @param string $user
253
+     * @return int
254
+     */
255
+    public function getSharePermissions($user) {
256
+
257
+        // check of we access a federated share
258
+        if ($user !== null) {
259
+            try {
260
+                $share = $this->shareManager->getShareByToken($user);
261
+                return $share->getPermissions();
262
+            } catch (ShareNotFound $e) {
263
+                // ignore
264
+            }
265
+        }
266
+
267
+        try {
268
+            $storage = $this->info->getStorage();
269
+        } catch (StorageNotAvailableException $e) {
270
+            $storage = null;
271
+        }
272
+
273
+        if ($storage && $storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
274
+            /** @var \OCA\Files_Sharing\SharedStorage $storage */
275
+            $permissions = (int)$storage->getShare()->getPermissions();
276
+        } else {
277
+            $permissions = $this->info->getPermissions();
278
+        }
279
+
280
+        /*
281 281
 		 * We can always share non moveable mount points with DELETE and UPDATE
282 282
 		 * Eventually we need to do this properly
283 283
 		 */
284
-		$mountpoint = $this->info->getMountPoint();
285
-		if (!($mountpoint instanceof MoveableMount)) {
286
-			$mountpointpath = $mountpoint->getMountPoint();
287
-			if (substr($mountpointpath, -1) === '/') {
288
-				$mountpointpath = substr($mountpointpath, 0, -1);
289
-			}
290
-
291
-			if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) {
292
-				$permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
293
-			}
294
-		}
295
-
296
-		/*
284
+        $mountpoint = $this->info->getMountPoint();
285
+        if (!($mountpoint instanceof MoveableMount)) {
286
+            $mountpointpath = $mountpoint->getMountPoint();
287
+            if (substr($mountpointpath, -1) === '/') {
288
+                $mountpointpath = substr($mountpointpath, 0, -1);
289
+            }
290
+
291
+            if (!$mountpoint->getOption('readonly', false) && $mountpointpath === $this->info->getPath()) {
292
+                $permissions |= \OCP\Constants::PERMISSION_DELETE | \OCP\Constants::PERMISSION_UPDATE;
293
+            }
294
+        }
295
+
296
+        /*
297 297
 		 * Files can't have create or delete permissions
298 298
 		 */
299
-		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
300
-			$permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
301
-		}
302
-
303
-		return $permissions;
304
-	}
305
-
306
-	/**
307
-	 * @param string $user
308
-	 * @return string
309
-	 */
310
-	public function getNoteFromShare($user) {
311
-		if ($user === null) {
312
-			return '';
313
-		}
314
-
315
-		$types = [
316
-			IShare::TYPE_USER,
317
-			IShare::TYPE_GROUP,
318
-			IShare::TYPE_CIRCLE,
319
-			IShare::TYPE_ROOM
320
-		];
321
-
322
-		foreach ($types as $shareType) {
323
-			$shares = $this->shareManager->getSharedWith($user, $shareType, $this, -1);
324
-			foreach ($shares as $share) {
325
-				$note = $share->getNote();
326
-				if ($share->getShareOwner() !== $user && !empty($note)) {
327
-					return $note;
328
-				}
329
-			}
330
-		}
331
-
332
-		return '';
333
-	}
334
-
335
-	/**
336
-	 * @return string
337
-	 */
338
-	public function getDavPermissions() {
339
-		$p = '';
340
-		if ($this->info->isShared()) {
341
-			$p .= 'S';
342
-		}
343
-		if ($this->info->isShareable()) {
344
-			$p .= 'R';
345
-		}
346
-		if ($this->info->isMounted()) {
347
-			$p .= 'M';
348
-		}
349
-		if ($this->info->isReadable()) {
350
-			$p .= 'G';
351
-		}
352
-		if ($this->info->isDeletable()) {
353
-			$p .= 'D';
354
-		}
355
-		if ($this->info->isUpdateable()) {
356
-			$p .= 'NV'; // Renameable, Moveable
357
-		}
358
-		if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
359
-			if ($this->info->isUpdateable()) {
360
-				$p .= 'W';
361
-			}
362
-		} else {
363
-			if ($this->info->isCreatable()) {
364
-				$p .= 'CK';
365
-			}
366
-		}
367
-		return $p;
368
-	}
369
-
370
-	public function getOwner() {
371
-		return $this->info->getOwner();
372
-	}
373
-
374
-	protected function verifyPath() {
375
-		try {
376
-			$fileName = basename($this->info->getPath());
377
-			$this->fileView->verifyPath($this->path, $fileName);
378
-		} catch (\OCP\Files\InvalidPathException $ex) {
379
-			throw new InvalidPath($ex->getMessage());
380
-		}
381
-	}
382
-
383
-	/**
384
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
385
-	 */
386
-	public function acquireLock($type) {
387
-		$this->fileView->lockFile($this->path, $type);
388
-	}
389
-
390
-	/**
391
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
392
-	 */
393
-	public function releaseLock($type) {
394
-		$this->fileView->unlockFile($this->path, $type);
395
-	}
396
-
397
-	/**
398
-	 * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
399
-	 */
400
-	public function changeLock($type) {
401
-		$this->fileView->changeLock($this->path, $type);
402
-	}
403
-
404
-	public function getFileInfo() {
405
-		return $this->info;
406
-	}
407
-
408
-	protected function sanitizeMtime($mtimeFromRequest) {
409
-		// In PHP 5.X "is_numeric" returns true for strings in hexadecimal
410
-		// notation. This is no longer the case in PHP 7.X, so this check
411
-		// ensures that strings with hexadecimal notations fail too in PHP 5.X.
412
-		$isHexadecimal = is_string($mtimeFromRequest) && preg_match('/^\s*0[xX]/', $mtimeFromRequest);
413
-		if ($isHexadecimal || !is_numeric($mtimeFromRequest)) {
414
-			throw new \InvalidArgumentException('X-OC-MTime header must be an integer (unix timestamp).');
415
-		}
416
-
417
-		return (int)$mtimeFromRequest;
418
-	}
299
+        if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
300
+            $permissions &= ~(\OCP\Constants::PERMISSION_CREATE | \OCP\Constants::PERMISSION_DELETE);
301
+        }
302
+
303
+        return $permissions;
304
+    }
305
+
306
+    /**
307
+     * @param string $user
308
+     * @return string
309
+     */
310
+    public function getNoteFromShare($user) {
311
+        if ($user === null) {
312
+            return '';
313
+        }
314
+
315
+        $types = [
316
+            IShare::TYPE_USER,
317
+            IShare::TYPE_GROUP,
318
+            IShare::TYPE_CIRCLE,
319
+            IShare::TYPE_ROOM
320
+        ];
321
+
322
+        foreach ($types as $shareType) {
323
+            $shares = $this->shareManager->getSharedWith($user, $shareType, $this, -1);
324
+            foreach ($shares as $share) {
325
+                $note = $share->getNote();
326
+                if ($share->getShareOwner() !== $user && !empty($note)) {
327
+                    return $note;
328
+                }
329
+            }
330
+        }
331
+
332
+        return '';
333
+    }
334
+
335
+    /**
336
+     * @return string
337
+     */
338
+    public function getDavPermissions() {
339
+        $p = '';
340
+        if ($this->info->isShared()) {
341
+            $p .= 'S';
342
+        }
343
+        if ($this->info->isShareable()) {
344
+            $p .= 'R';
345
+        }
346
+        if ($this->info->isMounted()) {
347
+            $p .= 'M';
348
+        }
349
+        if ($this->info->isReadable()) {
350
+            $p .= 'G';
351
+        }
352
+        if ($this->info->isDeletable()) {
353
+            $p .= 'D';
354
+        }
355
+        if ($this->info->isUpdateable()) {
356
+            $p .= 'NV'; // Renameable, Moveable
357
+        }
358
+        if ($this->info->getType() === \OCP\Files\FileInfo::TYPE_FILE) {
359
+            if ($this->info->isUpdateable()) {
360
+                $p .= 'W';
361
+            }
362
+        } else {
363
+            if ($this->info->isCreatable()) {
364
+                $p .= 'CK';
365
+            }
366
+        }
367
+        return $p;
368
+    }
369
+
370
+    public function getOwner() {
371
+        return $this->info->getOwner();
372
+    }
373
+
374
+    protected function verifyPath() {
375
+        try {
376
+            $fileName = basename($this->info->getPath());
377
+            $this->fileView->verifyPath($this->path, $fileName);
378
+        } catch (\OCP\Files\InvalidPathException $ex) {
379
+            throw new InvalidPath($ex->getMessage());
380
+        }
381
+    }
382
+
383
+    /**
384
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
385
+     */
386
+    public function acquireLock($type) {
387
+        $this->fileView->lockFile($this->path, $type);
388
+    }
389
+
390
+    /**
391
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
392
+     */
393
+    public function releaseLock($type) {
394
+        $this->fileView->unlockFile($this->path, $type);
395
+    }
396
+
397
+    /**
398
+     * @param int $type \OCP\Lock\ILockingProvider::LOCK_SHARED or \OCP\Lock\ILockingProvider::LOCK_EXCLUSIVE
399
+     */
400
+    public function changeLock($type) {
401
+        $this->fileView->changeLock($this->path, $type);
402
+    }
403
+
404
+    public function getFileInfo() {
405
+        return $this->info;
406
+    }
407
+
408
+    protected function sanitizeMtime($mtimeFromRequest) {
409
+        // In PHP 5.X "is_numeric" returns true for strings in hexadecimal
410
+        // notation. This is no longer the case in PHP 7.X, so this check
411
+        // ensures that strings with hexadecimal notations fail too in PHP 5.X.
412
+        $isHexadecimal = is_string($mtimeFromRequest) && preg_match('/^\s*0[xX]/', $mtimeFromRequest);
413
+        if ($isHexadecimal || !is_numeric($mtimeFromRequest)) {
414
+            throw new \InvalidArgumentException('X-OC-MTime header must be an integer (unix timestamp).');
415
+        }
416
+
417
+        return (int)$mtimeFromRequest;
418
+    }
419 419
 }
Please login to merge, or discard this patch.
Spacing   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -131,16 +131,16 @@  discard block
 block discarded – undo
131 131
 			throw new \Sabre\DAV\Exception\Forbidden();
132 132
 		}
133 133
 
134
-		[$parentPath,] = \Sabre\Uri\split($this->path);
134
+		[$parentPath, ] = \Sabre\Uri\split($this->path);
135 135
 		[, $newName] = \Sabre\Uri\split($name);
136 136
 
137 137
 		// verify path of the target
138 138
 		$this->verifyPath();
139 139
 
140
-		$newPath = $parentPath . '/' . $newName;
140
+		$newPath = $parentPath.'/'.$newName;
141 141
 
142 142
 		if (!$this->fileView->rename($this->path, $newPath)) {
143
-			throw new \Sabre\DAV\Exception('Failed to rename '. $this->path . ' to ' . $newPath);
143
+			throw new \Sabre\DAV\Exception('Failed to rename '.$this->path.' to '.$newPath);
144 144
 		}
145 145
 
146 146
 		$this->path = $newPath;
@@ -160,7 +160,7 @@  discard block
 block discarded – undo
160 160
 	public function getLastModified() {
161 161
 		$timestamp = $this->info->getMtime();
162 162
 		if (!empty($timestamp)) {
163
-			return (int)$timestamp;
163
+			return (int) $timestamp;
164 164
 		}
165 165
 		return $timestamp;
166 166
 	}
@@ -188,7 +188,7 @@  discard block
 block discarded – undo
188 188
 	 * @return string
189 189
 	 */
190 190
 	public function getETag() {
191
-		return '"' . $this->info->getEtag() . '"';
191
+		return '"'.$this->info->getEtag().'"';
192 192
 	}
193 193
 
194 194
 	/**
@@ -235,7 +235,7 @@  discard block
 block discarded – undo
235 235
 		if ($this->info->getId()) {
236 236
 			$instanceId = \OC_Util::getInstanceId();
237 237
 			$id = sprintf('%08d', $this->info->getId());
238
-			return $id . $instanceId;
238
+			return $id.$instanceId;
239 239
 		}
240 240
 
241 241
 		return null;
@@ -272,7 +272,7 @@  discard block
 block discarded – undo
272 272
 
273 273
 		if ($storage && $storage->instanceOfStorage('\OCA\Files_Sharing\SharedStorage')) {
274 274
 			/** @var \OCA\Files_Sharing\SharedStorage $storage */
275
-			$permissions = (int)$storage->getShare()->getPermissions();
275
+			$permissions = (int) $storage->getShare()->getPermissions();
276 276
 		} else {
277 277
 			$permissions = $this->info->getPermissions();
278 278
 		}
@@ -414,6 +414,6 @@  discard block
 block discarded – undo
414 414
 			throw new \InvalidArgumentException('X-OC-MTime header must be an integer (unix timestamp).');
415 415
 		}
416 416
 
417
-		return (int)$mtimeFromRequest;
417
+		return (int) $mtimeFromRequest;
418 418
 	}
419 419
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/ObjectTree.php 2 patches
Indentation   +199 added lines, -199 removed lines patch added patch discarded remove patch
@@ -41,203 +41,203 @@
 block discarded – undo
41 41
 
42 42
 class ObjectTree extends CachingTree {
43 43
 
44
-	/**
45
-	 * @var \OC\Files\View
46
-	 */
47
-	protected $fileView;
48
-
49
-	/**
50
-	 * @var  \OCP\Files\Mount\IMountManager
51
-	 */
52
-	protected $mountManager;
53
-
54
-	/**
55
-	 * Creates the object
56
-	 */
57
-	public function __construct() {
58
-	}
59
-
60
-	/**
61
-	 * @param \Sabre\DAV\INode $rootNode
62
-	 * @param \OC\Files\View $view
63
-	 * @param  \OCP\Files\Mount\IMountManager $mountManager
64
-	 */
65
-	public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) {
66
-		$this->rootNode = $rootNode;
67
-		$this->fileView = $view;
68
-		$this->mountManager = $mountManager;
69
-	}
70
-
71
-	/**
72
-	 * If the given path is a chunked file name, converts it
73
-	 * to the real file name. Only applies if the OC-CHUNKED header
74
-	 * is present.
75
-	 *
76
-	 * @param string $path chunk file path to convert
77
-	 *
78
-	 * @return string path to real file
79
-	 */
80
-	private function resolveChunkFile($path) {
81
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
82
-			// resolve to real file name to find the proper node
83
-			[$dir, $name] = \Sabre\Uri\split($path);
84
-			if ($dir === '/' || $dir === '.') {
85
-				$dir = '';
86
-			}
87
-
88
-			$info = \OC_FileChunking::decodeName($name);
89
-			// only replace path if it was really the chunked file
90
-			if (isset($info['transferid'])) {
91
-				// getNodePath is called for multiple nodes within a chunk
92
-				// upload call
93
-				$path = $dir . '/' . $info['name'];
94
-				$path = ltrim($path, '/');
95
-			}
96
-		}
97
-		return $path;
98
-	}
99
-
100
-	/**
101
-	 * Returns the INode object for the requested path
102
-	 *
103
-	 * @param string $path
104
-	 * @return \Sabre\DAV\INode
105
-	 * @throws InvalidPath
106
-	 * @throws \Sabre\DAV\Exception\Locked
107
-	 * @throws \Sabre\DAV\Exception\NotFound
108
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
109
-	 */
110
-	public function getNodeForPath($path) {
111
-		if (!$this->fileView) {
112
-			throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
113
-		}
114
-
115
-		$path = trim($path, '/');
116
-
117
-		if (isset($this->cache[$path])) {
118
-			return $this->cache[$path];
119
-		}
120
-
121
-		if ($path) {
122
-			try {
123
-				$this->fileView->verifyPath($path, basename($path));
124
-			} catch (\OCP\Files\InvalidPathException $ex) {
125
-				throw new InvalidPath($ex->getMessage());
126
-			}
127
-		}
128
-
129
-		// Is it the root node?
130
-		if (!strlen($path)) {
131
-			return $this->rootNode;
132
-		}
133
-
134
-		if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
135
-			// read from storage
136
-			$absPath = $this->fileView->getAbsolutePath($path);
137
-			$mount = $this->fileView->getMount($path);
138
-			$storage = $mount->getStorage();
139
-			$internalPath = $mount->getInternalPath($absPath);
140
-			if ($storage && $storage->file_exists($internalPath)) {
141
-				/**
142
-				 * @var \OC\Files\Storage\Storage $storage
143
-				 */
144
-				// get data directly
145
-				$data = $storage->getMetaData($internalPath);
146
-				$info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
147
-			} else {
148
-				$info = null;
149
-			}
150
-		} else {
151
-			// resolve chunk file name to real name, if applicable
152
-			$path = $this->resolveChunkFile($path);
153
-
154
-			// read from cache
155
-			try {
156
-				$info = $this->fileView->getFileInfo($path);
157
-
158
-				if ($info instanceof \OCP\Files\FileInfo && $info->getStorage()->instanceOfStorage(FailedStorage::class)) {
159
-					throw new StorageNotAvailableException();
160
-				}
161
-			} catch (StorageNotAvailableException $e) {
162
-				throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163
-			} catch (StorageInvalidException $e) {
164
-				throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
165
-			} catch (LockedException $e) {
166
-				throw new \Sabre\DAV\Exception\Locked();
167
-			} catch (ForbiddenException $e) {
168
-				throw new \Sabre\DAV\Exception\Forbidden();
169
-			}
170
-		}
171
-
172
-		if (!$info) {
173
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
174
-		}
175
-
176
-		if ($info->getType() === 'dir') {
177
-			$node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this);
178
-		} else {
179
-			$node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
180
-		}
181
-
182
-		$this->cache[$path] = $node;
183
-		return $node;
184
-	}
185
-
186
-	/**
187
-	 * Copies a file or directory.
188
-	 *
189
-	 * This method must work recursively and delete the destination
190
-	 * if it exists
191
-	 *
192
-	 * @param string $sourcePath
193
-	 * @param string $destinationPath
194
-	 * @throws FileLocked
195
-	 * @throws Forbidden
196
-	 * @throws InvalidPath
197
-	 * @throws \Exception
198
-	 * @throws \Sabre\DAV\Exception\Forbidden
199
-	 * @throws \Sabre\DAV\Exception\Locked
200
-	 * @throws \Sabre\DAV\Exception\NotFound
201
-	 * @throws \Sabre\DAV\Exception\ServiceUnavailable
202
-	 * @return void
203
-	 */
204
-	public function copy($sourcePath, $destinationPath) {
205
-		if (!$this->fileView) {
206
-			throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
207
-		}
208
-
209
-
210
-		$info = $this->fileView->getFileInfo(dirname($destinationPath));
211
-		if ($this->fileView->file_exists($destinationPath)) {
212
-			$destinationPermission = $info && $info->isUpdateable();
213
-		} else {
214
-			$destinationPermission = $info && $info->isCreatable();
215
-		}
216
-		if (!$destinationPermission) {
217
-			throw new Forbidden('No permissions to copy object.');
218
-		}
219
-
220
-		// this will trigger existence check
221
-		$this->getNodeForPath($sourcePath);
222
-
223
-		[$destinationDir, $destinationName] = \Sabre\Uri\split($destinationPath);
224
-		try {
225
-			$this->fileView->verifyPath($destinationDir, $destinationName);
226
-		} catch (\OCP\Files\InvalidPathException $ex) {
227
-			throw new InvalidPath($ex->getMessage());
228
-		}
229
-
230
-		try {
231
-			$this->fileView->copy($sourcePath, $destinationPath);
232
-		} catch (StorageNotAvailableException $e) {
233
-			throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
234
-		} catch (ForbiddenException $ex) {
235
-			throw new Forbidden($ex->getMessage(), $ex->getRetry());
236
-		} catch (LockedException $e) {
237
-			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238
-		}
239
-
240
-		[$destinationDir,] = \Sabre\Uri\split($destinationPath);
241
-		$this->markDirty($destinationDir);
242
-	}
44
+    /**
45
+     * @var \OC\Files\View
46
+     */
47
+    protected $fileView;
48
+
49
+    /**
50
+     * @var  \OCP\Files\Mount\IMountManager
51
+     */
52
+    protected $mountManager;
53
+
54
+    /**
55
+     * Creates the object
56
+     */
57
+    public function __construct() {
58
+    }
59
+
60
+    /**
61
+     * @param \Sabre\DAV\INode $rootNode
62
+     * @param \OC\Files\View $view
63
+     * @param  \OCP\Files\Mount\IMountManager $mountManager
64
+     */
65
+    public function init(\Sabre\DAV\INode $rootNode, \OC\Files\View $view, \OCP\Files\Mount\IMountManager $mountManager) {
66
+        $this->rootNode = $rootNode;
67
+        $this->fileView = $view;
68
+        $this->mountManager = $mountManager;
69
+    }
70
+
71
+    /**
72
+     * If the given path is a chunked file name, converts it
73
+     * to the real file name. Only applies if the OC-CHUNKED header
74
+     * is present.
75
+     *
76
+     * @param string $path chunk file path to convert
77
+     *
78
+     * @return string path to real file
79
+     */
80
+    private function resolveChunkFile($path) {
81
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
82
+            // resolve to real file name to find the proper node
83
+            [$dir, $name] = \Sabre\Uri\split($path);
84
+            if ($dir === '/' || $dir === '.') {
85
+                $dir = '';
86
+            }
87
+
88
+            $info = \OC_FileChunking::decodeName($name);
89
+            // only replace path if it was really the chunked file
90
+            if (isset($info['transferid'])) {
91
+                // getNodePath is called for multiple nodes within a chunk
92
+                // upload call
93
+                $path = $dir . '/' . $info['name'];
94
+                $path = ltrim($path, '/');
95
+            }
96
+        }
97
+        return $path;
98
+    }
99
+
100
+    /**
101
+     * Returns the INode object for the requested path
102
+     *
103
+     * @param string $path
104
+     * @return \Sabre\DAV\INode
105
+     * @throws InvalidPath
106
+     * @throws \Sabre\DAV\Exception\Locked
107
+     * @throws \Sabre\DAV\Exception\NotFound
108
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
109
+     */
110
+    public function getNodeForPath($path) {
111
+        if (!$this->fileView) {
112
+            throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
113
+        }
114
+
115
+        $path = trim($path, '/');
116
+
117
+        if (isset($this->cache[$path])) {
118
+            return $this->cache[$path];
119
+        }
120
+
121
+        if ($path) {
122
+            try {
123
+                $this->fileView->verifyPath($path, basename($path));
124
+            } catch (\OCP\Files\InvalidPathException $ex) {
125
+                throw new InvalidPath($ex->getMessage());
126
+            }
127
+        }
128
+
129
+        // Is it the root node?
130
+        if (!strlen($path)) {
131
+            return $this->rootNode;
132
+        }
133
+
134
+        if (pathinfo($path, PATHINFO_EXTENSION) === 'part') {
135
+            // read from storage
136
+            $absPath = $this->fileView->getAbsolutePath($path);
137
+            $mount = $this->fileView->getMount($path);
138
+            $storage = $mount->getStorage();
139
+            $internalPath = $mount->getInternalPath($absPath);
140
+            if ($storage && $storage->file_exists($internalPath)) {
141
+                /**
142
+                 * @var \OC\Files\Storage\Storage $storage
143
+                 */
144
+                // get data directly
145
+                $data = $storage->getMetaData($internalPath);
146
+                $info = new FileInfo($absPath, $storage, $internalPath, $data, $mount);
147
+            } else {
148
+                $info = null;
149
+            }
150
+        } else {
151
+            // resolve chunk file name to real name, if applicable
152
+            $path = $this->resolveChunkFile($path);
153
+
154
+            // read from cache
155
+            try {
156
+                $info = $this->fileView->getFileInfo($path);
157
+
158
+                if ($info instanceof \OCP\Files\FileInfo && $info->getStorage()->instanceOfStorage(FailedStorage::class)) {
159
+                    throw new StorageNotAvailableException();
160
+                }
161
+            } catch (StorageNotAvailableException $e) {
162
+                throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163
+            } catch (StorageInvalidException $e) {
164
+                throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
165
+            } catch (LockedException $e) {
166
+                throw new \Sabre\DAV\Exception\Locked();
167
+            } catch (ForbiddenException $e) {
168
+                throw new \Sabre\DAV\Exception\Forbidden();
169
+            }
170
+        }
171
+
172
+        if (!$info) {
173
+            throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
174
+        }
175
+
176
+        if ($info->getType() === 'dir') {
177
+            $node = new \OCA\DAV\Connector\Sabre\Directory($this->fileView, $info, $this);
178
+        } else {
179
+            $node = new \OCA\DAV\Connector\Sabre\File($this->fileView, $info);
180
+        }
181
+
182
+        $this->cache[$path] = $node;
183
+        return $node;
184
+    }
185
+
186
+    /**
187
+     * Copies a file or directory.
188
+     *
189
+     * This method must work recursively and delete the destination
190
+     * if it exists
191
+     *
192
+     * @param string $sourcePath
193
+     * @param string $destinationPath
194
+     * @throws FileLocked
195
+     * @throws Forbidden
196
+     * @throws InvalidPath
197
+     * @throws \Exception
198
+     * @throws \Sabre\DAV\Exception\Forbidden
199
+     * @throws \Sabre\DAV\Exception\Locked
200
+     * @throws \Sabre\DAV\Exception\NotFound
201
+     * @throws \Sabre\DAV\Exception\ServiceUnavailable
202
+     * @return void
203
+     */
204
+    public function copy($sourcePath, $destinationPath) {
205
+        if (!$this->fileView) {
206
+            throw new \Sabre\DAV\Exception\ServiceUnavailable('filesystem not setup');
207
+        }
208
+
209
+
210
+        $info = $this->fileView->getFileInfo(dirname($destinationPath));
211
+        if ($this->fileView->file_exists($destinationPath)) {
212
+            $destinationPermission = $info && $info->isUpdateable();
213
+        } else {
214
+            $destinationPermission = $info && $info->isCreatable();
215
+        }
216
+        if (!$destinationPermission) {
217
+            throw new Forbidden('No permissions to copy object.');
218
+        }
219
+
220
+        // this will trigger existence check
221
+        $this->getNodeForPath($sourcePath);
222
+
223
+        [$destinationDir, $destinationName] = \Sabre\Uri\split($destinationPath);
224
+        try {
225
+            $this->fileView->verifyPath($destinationDir, $destinationName);
226
+        } catch (\OCP\Files\InvalidPathException $ex) {
227
+            throw new InvalidPath($ex->getMessage());
228
+        }
229
+
230
+        try {
231
+            $this->fileView->copy($sourcePath, $destinationPath);
232
+        } catch (StorageNotAvailableException $e) {
233
+            throw new \Sabre\DAV\Exception\ServiceUnavailable($e->getMessage());
234
+        } catch (ForbiddenException $ex) {
235
+            throw new Forbidden($ex->getMessage(), $ex->getRetry());
236
+        } catch (LockedException $e) {
237
+            throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238
+        }
239
+
240
+        [$destinationDir,] = \Sabre\Uri\split($destinationPath);
241
+        $this->markDirty($destinationDir);
242
+    }
243 243
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -90,7 +90,7 @@  discard block
 block discarded – undo
90 90
 			if (isset($info['transferid'])) {
91 91
 				// getNodePath is called for multiple nodes within a chunk
92 92
 				// upload call
93
-				$path = $dir . '/' . $info['name'];
93
+				$path = $dir.'/'.$info['name'];
94 94
 				$path = ltrim($path, '/');
95 95
 			}
96 96
 		}
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
 			} catch (StorageNotAvailableException $e) {
162 162
 				throw new \Sabre\DAV\Exception\ServiceUnavailable('Storage is temporarily not available', 0, $e);
163 163
 			} catch (StorageInvalidException $e) {
164
-				throw new \Sabre\DAV\Exception\NotFound('Storage ' . $path . ' is invalid');
164
+				throw new \Sabre\DAV\Exception\NotFound('Storage '.$path.' is invalid');
165 165
 			} catch (LockedException $e) {
166 166
 				throw new \Sabre\DAV\Exception\Locked();
167 167
 			} catch (ForbiddenException $e) {
@@ -170,7 +170,7 @@  discard block
 block discarded – undo
170 170
 		}
171 171
 
172 172
 		if (!$info) {
173
-			throw new \Sabre\DAV\Exception\NotFound('File with name ' . $path . ' could not be located');
173
+			throw new \Sabre\DAV\Exception\NotFound('File with name '.$path.' could not be located');
174 174
 		}
175 175
 
176 176
 		if ($info->getType() === 'dir') {
@@ -237,7 +237,7 @@  discard block
 block discarded – undo
237 237
 			throw new FileLocked($e->getMessage(), $e->getCode(), $e);
238 238
 		}
239 239
 
240
-		[$destinationDir,] = \Sabre\Uri\split($destinationPath);
240
+		[$destinationDir, ] = \Sabre\Uri\split($destinationPath);
241 241
 		$this->markDirty($destinationDir);
242 242
 	}
243 243
 }
Please login to merge, or discard this patch.
apps/dav/lib/Connector/LegacyDAVACL.php 1 patch
Indentation   +35 added lines, -35 removed lines patch added patch discarded remove patch
@@ -33,44 +33,44 @@
 block discarded – undo
33 33
 
34 34
 class LegacyDAVACL extends DavAclPlugin {
35 35
 
36
-	/**
37
-	 * @inheritdoc
38
-	 */
39
-	public function getCurrentUserPrincipals() {
40
-		$principalV2 = $this->getCurrentUserPrincipal();
36
+    /**
37
+     * @inheritdoc
38
+     */
39
+    public function getCurrentUserPrincipals() {
40
+        $principalV2 = $this->getCurrentUserPrincipal();
41 41
 
42
-		if (is_null($principalV2)) {
43
-			return [];
44
-		}
42
+        if (is_null($principalV2)) {
43
+            return [];
44
+        }
45 45
 
46
-		$principalV1 = $this->convertPrincipal($principalV2, false);
47
-		return array_merge(
48
-			[
49
-				$principalV2,
50
-				$principalV1
51
-			],
52
-			$this->getPrincipalMembership($principalV1)
53
-		);
54
-	}
46
+        $principalV1 = $this->convertPrincipal($principalV2, false);
47
+        return array_merge(
48
+            [
49
+                $principalV2,
50
+                $principalV1
51
+            ],
52
+            $this->getPrincipalMembership($principalV1)
53
+        );
54
+    }
55 55
 
56
-	private function convertPrincipal($principal, $toV2) {
57
-		[, $name] = \Sabre\Uri\split($principal);
58
-		if ($toV2) {
59
-			return "principals/users/$name";
60
-		}
61
-		return "principals/$name";
62
-	}
56
+    private function convertPrincipal($principal, $toV2) {
57
+        [, $name] = \Sabre\Uri\split($principal);
58
+        if ($toV2) {
59
+            return "principals/users/$name";
60
+        }
61
+        return "principals/$name";
62
+    }
63 63
 
64
-	public function propFind(PropFind $propFind, INode $node) {
65
-		/* Overload current-user-principal */
66
-		$propFind->handle('{DAV:}current-user-principal', function () {
67
-			if ($url = parent::getCurrentUserPrincipal()) {
68
-				return new Principal(Principal::HREF, $url . '/');
69
-			} else {
70
-				return new Principal(Principal::UNAUTHENTICATED);
71
-			}
72
-		});
64
+    public function propFind(PropFind $propFind, INode $node) {
65
+        /* Overload current-user-principal */
66
+        $propFind->handle('{DAV:}current-user-principal', function () {
67
+            if ($url = parent::getCurrentUserPrincipal()) {
68
+                return new Principal(Principal::HREF, $url . '/');
69
+            } else {
70
+                return new Principal(Principal::UNAUTHENTICATED);
71
+            }
72
+        });
73 73
 
74
-		return parent::propFind($propFind, $node);
75
-	}
74
+        return parent::propFind($propFind, $node);
75
+    }
76 76
 }
Please login to merge, or discard this patch.
apps/dav/lib/Avatars/AvatarHome.php 1 patch
Indentation   +73 added lines, -73 removed lines patch added patch discarded remove patch
@@ -34,87 +34,87 @@
 block discarded – undo
34 34
 
35 35
 class AvatarHome implements ICollection {
36 36
 
37
-	/** @var array */
38
-	private $principalInfo;
39
-	/** @var IAvatarManager */
40
-	private $avatarManager;
37
+    /** @var array */
38
+    private $principalInfo;
39
+    /** @var IAvatarManager */
40
+    private $avatarManager;
41 41
 
42
-	/**
43
-	 * AvatarHome constructor.
44
-	 *
45
-	 * @param array $principalInfo
46
-	 * @param IAvatarManager $avatarManager
47
-	 */
48
-	public function __construct($principalInfo, IAvatarManager $avatarManager) {
49
-		$this->principalInfo = $principalInfo;
50
-		$this->avatarManager = $avatarManager;
51
-	}
42
+    /**
43
+     * AvatarHome constructor.
44
+     *
45
+     * @param array $principalInfo
46
+     * @param IAvatarManager $avatarManager
47
+     */
48
+    public function __construct($principalInfo, IAvatarManager $avatarManager) {
49
+        $this->principalInfo = $principalInfo;
50
+        $this->avatarManager = $avatarManager;
51
+    }
52 52
 
53
-	public function createFile($name, $data = null) {
54
-		throw new Forbidden('Permission denied to create a file');
55
-	}
53
+    public function createFile($name, $data = null) {
54
+        throw new Forbidden('Permission denied to create a file');
55
+    }
56 56
 
57
-	public function createDirectory($name) {
58
-		throw new Forbidden('Permission denied to create a folder');
59
-	}
57
+    public function createDirectory($name) {
58
+        throw new Forbidden('Permission denied to create a folder');
59
+    }
60 60
 
61
-	public function getChild($name) {
62
-		$elements = pathinfo($name);
63
-		$ext = isset($elements['extension']) ? $elements['extension'] : '';
64
-		$size = (int)(isset($elements['filename']) ? $elements['filename'] : '64');
65
-		if (!in_array($ext, ['jpeg', 'png'], true)) {
66
-			throw new MethodNotAllowed('File format not allowed');
67
-		}
68
-		if ($size <= 0 || $size > 1024) {
69
-			throw new MethodNotAllowed('Invalid image size');
70
-		}
71
-		$avatar = $this->avatarManager->getAvatar($this->getName());
72
-		if (!$avatar->exists()) {
73
-			throw new NotFound();
74
-		}
75
-		return new AvatarNode($size, $ext, $avatar);
76
-	}
61
+    public function getChild($name) {
62
+        $elements = pathinfo($name);
63
+        $ext = isset($elements['extension']) ? $elements['extension'] : '';
64
+        $size = (int)(isset($elements['filename']) ? $elements['filename'] : '64');
65
+        if (!in_array($ext, ['jpeg', 'png'], true)) {
66
+            throw new MethodNotAllowed('File format not allowed');
67
+        }
68
+        if ($size <= 0 || $size > 1024) {
69
+            throw new MethodNotAllowed('Invalid image size');
70
+        }
71
+        $avatar = $this->avatarManager->getAvatar($this->getName());
72
+        if (!$avatar->exists()) {
73
+            throw new NotFound();
74
+        }
75
+        return new AvatarNode($size, $ext, $avatar);
76
+    }
77 77
 
78
-	public function getChildren() {
79
-		try {
80
-			return [
81
-				$this->getChild('96.jpeg')
82
-			];
83
-		} catch (NotFound $exception) {
84
-			return [];
85
-		}
86
-	}
78
+    public function getChildren() {
79
+        try {
80
+            return [
81
+                $this->getChild('96.jpeg')
82
+            ];
83
+        } catch (NotFound $exception) {
84
+            return [];
85
+        }
86
+    }
87 87
 
88
-	public function childExists($name) {
89
-		try {
90
-			$ret = $this->getChild($name);
91
-			return $ret !== null;
92
-		} catch (NotFound $ex) {
93
-			return false;
94
-		} catch (MethodNotAllowed $ex) {
95
-			return false;
96
-		}
97
-	}
88
+    public function childExists($name) {
89
+        try {
90
+            $ret = $this->getChild($name);
91
+            return $ret !== null;
92
+        } catch (NotFound $ex) {
93
+            return false;
94
+        } catch (MethodNotAllowed $ex) {
95
+            return false;
96
+        }
97
+    }
98 98
 
99
-	public function delete() {
100
-		throw new Forbidden('Permission denied to delete this folder');
101
-	}
99
+    public function delete() {
100
+        throw new Forbidden('Permission denied to delete this folder');
101
+    }
102 102
 
103
-	public function getName() {
104
-		[,$name] = Uri\split($this->principalInfo['uri']);
105
-		return $name;
106
-	}
103
+    public function getName() {
104
+        [,$name] = Uri\split($this->principalInfo['uri']);
105
+        return $name;
106
+    }
107 107
 
108
-	public function setName($name) {
109
-		throw new Forbidden('Permission denied to rename this folder');
110
-	}
108
+    public function setName($name) {
109
+        throw new Forbidden('Permission denied to rename this folder');
110
+    }
111 111
 
112
-	/**
113
-	 * Returns the last modification time, as a unix timestamp
114
-	 *
115
-	 * @return int|null
116
-	 */
117
-	public function getLastModified() {
118
-		return null;
119
-	}
112
+    /**
113
+     * Returns the last modification time, as a unix timestamp
114
+     *
115
+     * @return int|null
116
+     */
117
+    public function getLastModified() {
118
+        return null;
119
+    }
120 120
 }
Please login to merge, or discard this patch.
apps/dav/lib/DAV/SystemPrincipalBackend.php 1 patch
Indentation   +160 added lines, -160 removed lines patch added patch discarded remove patch
@@ -28,164 +28,164 @@
 block discarded – undo
28 28
 
29 29
 class SystemPrincipalBackend extends AbstractBackend {
30 30
 
31
-	/**
32
-	 * Returns a list of principals based on a prefix.
33
-	 *
34
-	 * This prefix will often contain something like 'principals'. You are only
35
-	 * expected to return principals that are in this base path.
36
-	 *
37
-	 * You are expected to return at least a 'uri' for every user, you can
38
-	 * return any additional properties if you wish so. Common properties are:
39
-	 *   {DAV:}displayname
40
-	 *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
41
-	 *     field that's actually injected in a number of other properties. If
42
-	 *     you have an email address, use this property.
43
-	 *
44
-	 * @param string $prefixPath
45
-	 * @return array
46
-	 */
47
-	public function getPrincipalsByPrefix($prefixPath) {
48
-		$principals = [];
49
-
50
-		if ($prefixPath === 'principals/system') {
51
-			$principals[] = [
52
-				'uri' => 'principals/system/system',
53
-				'{DAV:}displayname' => 'system',
54
-			];
55
-			$principals[] = [
56
-				'uri' => 'principals/system/public',
57
-				'{DAV:}displayname' => 'public',
58
-			];
59
-		}
60
-
61
-		return $principals;
62
-	}
63
-
64
-	/**
65
-	 * Returns a specific principal, specified by it's path.
66
-	 * The returned structure should be the exact same as from
67
-	 * getPrincipalsByPrefix.
68
-	 *
69
-	 * @param string $path
70
-	 * @return array
71
-	 */
72
-	public function getPrincipalByPath($path) {
73
-		if ($path === 'principals/system/system') {
74
-			$principal = [
75
-				'uri' => 'principals/system/system',
76
-				'{DAV:}displayname' => 'system',
77
-			];
78
-			return $principal;
79
-		}
80
-		if ($path === 'principals/system/public') {
81
-			$principal = [
82
-				'uri' => 'principals/system/public',
83
-				'{DAV:}displayname' => 'public',
84
-			];
85
-			return $principal;
86
-		}
87
-
88
-		return null;
89
-	}
90
-
91
-	/**
92
-	 * Updates one ore more webdav properties on a principal.
93
-	 *
94
-	 * The list of mutations is stored in a Sabre\DAV\PropPatch object.
95
-	 * To do the actual updates, you must tell this object which properties
96
-	 * you're going to process with the handle() method.
97
-	 *
98
-	 * Calling the handle method is like telling the PropPatch object "I
99
-	 * promise I can handle updating this property".
100
-	 *
101
-	 * Read the PropPatch documentation for more info and examples.
102
-	 *
103
-	 * @param string $path
104
-	 * @param \Sabre\DAV\PropPatch $propPatch
105
-	 * @return void
106
-	 */
107
-	public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) {
108
-	}
109
-
110
-	/**
111
-	 * This method is used to search for principals matching a set of
112
-	 * properties.
113
-	 *
114
-	 * This search is specifically used by RFC3744's principal-property-search
115
-	 * REPORT.
116
-	 *
117
-	 * The actual search should be a unicode-non-case-sensitive search. The
118
-	 * keys in searchProperties are the WebDAV property names, while the values
119
-	 * are the property values to search on.
120
-	 *
121
-	 * By default, if multiple properties are submitted to this method, the
122
-	 * various properties should be combined with 'AND'. If $test is set to
123
-	 * 'anyof', it should be combined using 'OR'.
124
-	 *
125
-	 * This method should simply return an array with full principal uri's.
126
-	 *
127
-	 * If somebody attempted to search on a property the backend does not
128
-	 * support, you should simply return 0 results.
129
-	 *
130
-	 * You can also just return 0 results if you choose to not support
131
-	 * searching at all, but keep in mind that this may stop certain features
132
-	 * from working.
133
-	 *
134
-	 * @param string $prefixPath
135
-	 * @param array $searchProperties
136
-	 * @param string $test
137
-	 * @return array
138
-	 */
139
-	public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
140
-		return [];
141
-	}
142
-
143
-	/**
144
-	 * Returns the list of members for a group-principal
145
-	 *
146
-	 * @param string $principal
147
-	 * @return array
148
-	 */
149
-	public function getGroupMemberSet($principal) {
150
-		// TODO: for now the group principal has only one member, the user itself
151
-		$principal = $this->getPrincipalByPath($principal);
152
-		if (!$principal) {
153
-			throw new \Sabre\DAV\Exception('Principal not found');
154
-		}
155
-
156
-		return [$principal['uri']];
157
-	}
158
-
159
-	/**
160
-	 * Returns the list of groups a principal is a member of
161
-	 *
162
-	 * @param string $principal
163
-	 * @return array
164
-	 */
165
-	public function getGroupMembership($principal) {
166
-		[$prefix, ] = \Sabre\Uri\split($principal);
167
-
168
-		if ($prefix === 'principals/system') {
169
-			$principal = $this->getPrincipalByPath($principal);
170
-			if (!$principal) {
171
-				throw new \Sabre\DAV\Exception('Principal not found');
172
-			}
173
-
174
-			return [];
175
-		}
176
-		return [];
177
-	}
178
-
179
-	/**
180
-	 * Updates the list of group members for a group principal.
181
-	 *
182
-	 * The principals should be passed as a list of uri's.
183
-	 *
184
-	 * @param string $principal
185
-	 * @param array $members
186
-	 * @return void
187
-	 */
188
-	public function setGroupMemberSet($principal, array $members) {
189
-		throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet');
190
-	}
31
+    /**
32
+     * Returns a list of principals based on a prefix.
33
+     *
34
+     * This prefix will often contain something like 'principals'. You are only
35
+     * expected to return principals that are in this base path.
36
+     *
37
+     * You are expected to return at least a 'uri' for every user, you can
38
+     * return any additional properties if you wish so. Common properties are:
39
+     *   {DAV:}displayname
40
+     *   {http://sabredav.org/ns}email-address - This is a custom SabreDAV
41
+     *     field that's actually injected in a number of other properties. If
42
+     *     you have an email address, use this property.
43
+     *
44
+     * @param string $prefixPath
45
+     * @return array
46
+     */
47
+    public function getPrincipalsByPrefix($prefixPath) {
48
+        $principals = [];
49
+
50
+        if ($prefixPath === 'principals/system') {
51
+            $principals[] = [
52
+                'uri' => 'principals/system/system',
53
+                '{DAV:}displayname' => 'system',
54
+            ];
55
+            $principals[] = [
56
+                'uri' => 'principals/system/public',
57
+                '{DAV:}displayname' => 'public',
58
+            ];
59
+        }
60
+
61
+        return $principals;
62
+    }
63
+
64
+    /**
65
+     * Returns a specific principal, specified by it's path.
66
+     * The returned structure should be the exact same as from
67
+     * getPrincipalsByPrefix.
68
+     *
69
+     * @param string $path
70
+     * @return array
71
+     */
72
+    public function getPrincipalByPath($path) {
73
+        if ($path === 'principals/system/system') {
74
+            $principal = [
75
+                'uri' => 'principals/system/system',
76
+                '{DAV:}displayname' => 'system',
77
+            ];
78
+            return $principal;
79
+        }
80
+        if ($path === 'principals/system/public') {
81
+            $principal = [
82
+                'uri' => 'principals/system/public',
83
+                '{DAV:}displayname' => 'public',
84
+            ];
85
+            return $principal;
86
+        }
87
+
88
+        return null;
89
+    }
90
+
91
+    /**
92
+     * Updates one ore more webdav properties on a principal.
93
+     *
94
+     * The list of mutations is stored in a Sabre\DAV\PropPatch object.
95
+     * To do the actual updates, you must tell this object which properties
96
+     * you're going to process with the handle() method.
97
+     *
98
+     * Calling the handle method is like telling the PropPatch object "I
99
+     * promise I can handle updating this property".
100
+     *
101
+     * Read the PropPatch documentation for more info and examples.
102
+     *
103
+     * @param string $path
104
+     * @param \Sabre\DAV\PropPatch $propPatch
105
+     * @return void
106
+     */
107
+    public function updatePrincipal($path, \Sabre\DAV\PropPatch $propPatch) {
108
+    }
109
+
110
+    /**
111
+     * This method is used to search for principals matching a set of
112
+     * properties.
113
+     *
114
+     * This search is specifically used by RFC3744's principal-property-search
115
+     * REPORT.
116
+     *
117
+     * The actual search should be a unicode-non-case-sensitive search. The
118
+     * keys in searchProperties are the WebDAV property names, while the values
119
+     * are the property values to search on.
120
+     *
121
+     * By default, if multiple properties are submitted to this method, the
122
+     * various properties should be combined with 'AND'. If $test is set to
123
+     * 'anyof', it should be combined using 'OR'.
124
+     *
125
+     * This method should simply return an array with full principal uri's.
126
+     *
127
+     * If somebody attempted to search on a property the backend does not
128
+     * support, you should simply return 0 results.
129
+     *
130
+     * You can also just return 0 results if you choose to not support
131
+     * searching at all, but keep in mind that this may stop certain features
132
+     * from working.
133
+     *
134
+     * @param string $prefixPath
135
+     * @param array $searchProperties
136
+     * @param string $test
137
+     * @return array
138
+     */
139
+    public function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
140
+        return [];
141
+    }
142
+
143
+    /**
144
+     * Returns the list of members for a group-principal
145
+     *
146
+     * @param string $principal
147
+     * @return array
148
+     */
149
+    public function getGroupMemberSet($principal) {
150
+        // TODO: for now the group principal has only one member, the user itself
151
+        $principal = $this->getPrincipalByPath($principal);
152
+        if (!$principal) {
153
+            throw new \Sabre\DAV\Exception('Principal not found');
154
+        }
155
+
156
+        return [$principal['uri']];
157
+    }
158
+
159
+    /**
160
+     * Returns the list of groups a principal is a member of
161
+     *
162
+     * @param string $principal
163
+     * @return array
164
+     */
165
+    public function getGroupMembership($principal) {
166
+        [$prefix, ] = \Sabre\Uri\split($principal);
167
+
168
+        if ($prefix === 'principals/system') {
169
+            $principal = $this->getPrincipalByPath($principal);
170
+            if (!$principal) {
171
+                throw new \Sabre\DAV\Exception('Principal not found');
172
+            }
173
+
174
+            return [];
175
+        }
176
+        return [];
177
+    }
178
+
179
+    /**
180
+     * Updates the list of group members for a group principal.
181
+     *
182
+     * The principals should be passed as a list of uri's.
183
+     *
184
+     * @param string $principal
185
+     * @param array $members
186
+     * @return void
187
+     */
188
+    public function setGroupMemberSet($principal, array $members) {
189
+        throw new \Sabre\DAV\Exception('Setting members of the group is not supported yet');
190
+    }
191 191
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Plugin.php 2 patches
Indentation   +25 added lines, -25 removed lines patch added patch discarded remove patch
@@ -26,30 +26,30 @@
 block discarded – undo
26 26
 namespace OCA\DAV\CalDAV;
27 27
 
28 28
 class Plugin extends \Sabre\CalDAV\Plugin {
29
-	public const SYSTEM_CALENDAR_ROOT = 'system-calendars';
29
+    public const SYSTEM_CALENDAR_ROOT = 'system-calendars';
30 30
 
31
-	/**
32
-	 * Returns the path to a principal's calendar home.
33
-	 *
34
-	 * The return url must not end with a slash.
35
-	 * This function should return null in case a principal did not have
36
-	 * a calendar home.
37
-	 *
38
-	 * @param string $principalUrl
39
-	 * @return string|null
40
-	 */
41
-	public function getCalendarHomeForPrincipal($principalUrl) {
42
-		if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
43
-			[, $principalId] = \Sabre\Uri\split($principalUrl);
44
-			return self::CALENDAR_ROOT . '/' . $principalId;
45
-		}
46
-		if (strrpos($principalUrl, 'principals/calendar-resources', -strlen($principalUrl)) !== false) {
47
-			[, $principalId] = \Sabre\Uri\split($principalUrl);
48
-			return self::SYSTEM_CALENDAR_ROOT . '/calendar-resources/' . $principalId;
49
-		}
50
-		if (strrpos($principalUrl, 'principals/calendar-rooms', -strlen($principalUrl)) !== false) {
51
-			[, $principalId] = \Sabre\Uri\split($principalUrl);
52
-			return self::SYSTEM_CALENDAR_ROOT . '/calendar-rooms/' . $principalId;
53
-		}
54
-	}
31
+    /**
32
+     * Returns the path to a principal's calendar home.
33
+     *
34
+     * The return url must not end with a slash.
35
+     * This function should return null in case a principal did not have
36
+     * a calendar home.
37
+     *
38
+     * @param string $principalUrl
39
+     * @return string|null
40
+     */
41
+    public function getCalendarHomeForPrincipal($principalUrl) {
42
+        if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
43
+            [, $principalId] = \Sabre\Uri\split($principalUrl);
44
+            return self::CALENDAR_ROOT . '/' . $principalId;
45
+        }
46
+        if (strrpos($principalUrl, 'principals/calendar-resources', -strlen($principalUrl)) !== false) {
47
+            [, $principalId] = \Sabre\Uri\split($principalUrl);
48
+            return self::SYSTEM_CALENDAR_ROOT . '/calendar-resources/' . $principalId;
49
+        }
50
+        if (strrpos($principalUrl, 'principals/calendar-rooms', -strlen($principalUrl)) !== false) {
51
+            [, $principalId] = \Sabre\Uri\split($principalUrl);
52
+            return self::SYSTEM_CALENDAR_ROOT . '/calendar-rooms/' . $principalId;
53
+        }
54
+    }
55 55
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -41,15 +41,15 @@
 block discarded – undo
41 41
 	public function getCalendarHomeForPrincipal($principalUrl) {
42 42
 		if (strrpos($principalUrl, 'principals/users', -strlen($principalUrl)) !== false) {
43 43
 			[, $principalId] = \Sabre\Uri\split($principalUrl);
44
-			return self::CALENDAR_ROOT . '/' . $principalId;
44
+			return self::CALENDAR_ROOT.'/'.$principalId;
45 45
 		}
46 46
 		if (strrpos($principalUrl, 'principals/calendar-resources', -strlen($principalUrl)) !== false) {
47 47
 			[, $principalId] = \Sabre\Uri\split($principalUrl);
48
-			return self::SYSTEM_CALENDAR_ROOT . '/calendar-resources/' . $principalId;
48
+			return self::SYSTEM_CALENDAR_ROOT.'/calendar-resources/'.$principalId;
49 49
 		}
50 50
 		if (strrpos($principalUrl, 'principals/calendar-rooms', -strlen($principalUrl)) !== false) {
51 51
 			[, $principalId] = \Sabre\Uri\split($principalUrl);
52
-			return self::SYSTEM_CALENDAR_ROOT . '/calendar-rooms/' . $principalId;
52
+			return self::SYSTEM_CALENDAR_ROOT.'/calendar-rooms/'.$principalId;
53 53
 		}
54 54
 	}
55 55
 }
Please login to merge, or discard this patch.
apps/dav/lib/CalDAV/Search/SearchPlugin.php 2 patches
Indentation   +130 added lines, -130 removed lines patch added patch discarded remove patch
@@ -33,134 +33,134 @@
 block discarded – undo
33 33
 use Sabre\DAV\ServerPlugin;
34 34
 
35 35
 class SearchPlugin extends ServerPlugin {
36
-	public const NS_Nextcloud = 'http://nextcloud.com/ns';
37
-
38
-	/**
39
-	 * Reference to SabreDAV server object.
40
-	 *
41
-	 * @var \Sabre\DAV\Server
42
-	 */
43
-	protected $server;
44
-
45
-	/**
46
-	 * This method should return a list of server-features.
47
-	 *
48
-	 * This is for example 'versioning' and is added to the DAV: header
49
-	 * in an OPTIONS response.
50
-	 *
51
-	 * @return string[]
52
-	 */
53
-	public function getFeatures() {
54
-		// May have to be changed to be detected
55
-		return ['nc-calendar-search'];
56
-	}
57
-
58
-	/**
59
-	 * Returns a plugin name.
60
-	 *
61
-	 * Using this name other plugins will be able to access other plugins
62
-	 * using Sabre\DAV\Server::getPlugin
63
-	 *
64
-	 * @return string
65
-	 */
66
-	public function getPluginName() {
67
-		return 'nc-calendar-search';
68
-	}
69
-
70
-	/**
71
-	 * This initializes the plugin.
72
-	 *
73
-	 * This function is called by Sabre\DAV\Server, after
74
-	 * addPlugin is called.
75
-	 *
76
-	 * This method should set up the required event subscriptions.
77
-	 *
78
-	 * @param Server $server
79
-	 */
80
-	public function initialize(Server $server) {
81
-		$this->server = $server;
82
-
83
-		$server->on('report', [$this, 'report']);
84
-
85
-		$server->xml->elementMap['{' . self::NS_Nextcloud . '}calendar-search'] =
86
-			CalendarSearchReport::class;
87
-	}
88
-
89
-	/**
90
-	 * This functions handles REPORT requests specific to CalDAV
91
-	 *
92
-	 * @param string $reportName
93
-	 * @param mixed $report
94
-	 * @param mixed $path
95
-	 * @return bool
96
-	 */
97
-	public function report($reportName, $report, $path) {
98
-		switch ($reportName) {
99
-			case '{' . self::NS_Nextcloud . '}calendar-search':
100
-				$this->server->transactionType = 'report-nc-calendar-search';
101
-				$this->calendarSearch($report);
102
-				return false;
103
-		}
104
-	}
105
-
106
-	/**
107
-	 * Returns a list of reports this plugin supports.
108
-	 *
109
-	 * This will be used in the {DAV:}supported-report-set property.
110
-	 * Note that you still need to subscribe to the 'report' event to actually
111
-	 * implement them
112
-	 *
113
-	 * @param string $uri
114
-	 * @return array
115
-	 */
116
-	public function getSupportedReportSet($uri) {
117
-		$node = $this->server->tree->getNodeForPath($uri);
118
-
119
-		$reports = [];
120
-		if ($node instanceof CalendarHome) {
121
-			$reports[] = '{' . self::NS_Nextcloud . '}calendar-search';
122
-		}
123
-
124
-		return $reports;
125
-	}
126
-
127
-	/**
128
-	 * This function handles the calendar-query REPORT
129
-	 *
130
-	 * This report is used by clients to request calendar objects based on
131
-	 * complex conditions.
132
-	 *
133
-	 * @param Xml\Request\CalendarSearchReport $report
134
-	 * @return void
135
-	 */
136
-	private function calendarSearch($report) {
137
-		$node = $this->server->tree->getNodeForPath($this->server->getRequestUri());
138
-		$depth = $this->server->getHTTPDepth(2);
139
-
140
-		// The default result is an empty array
141
-		$result = [];
142
-
143
-		// If we're dealing with the calendar home, the calendar home itself is
144
-		// responsible for the calendar-query
145
-		if ($node instanceof CalendarHome && $depth === 2) {
146
-			$nodePaths = $node->calendarSearch($report->filters, $report->limit, $report->offset);
147
-
148
-			foreach ($nodePaths as $path) {
149
-				[$properties] = $this->server->getPropertiesForPath(
150
-					$this->server->getRequestUri() . '/' . $path,
151
-					$report->properties);
152
-				$result[] = $properties;
153
-			}
154
-		}
155
-
156
-		$prefer = $this->server->getHTTPPrefer();
157
-
158
-		$this->server->httpResponse->setStatus(207);
159
-		$this->server->httpResponse->setHeader('Content-Type',
160
-			'application/xml; charset=utf-8');
161
-		$this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
162
-		$this->server->httpResponse->setBody(
163
-			$this->server->generateMultiStatus($result,
164
-				$prefer['return'] === 'minimal'));
165
-	}
36
+    public const NS_Nextcloud = 'http://nextcloud.com/ns';
37
+
38
+    /**
39
+     * Reference to SabreDAV server object.
40
+     *
41
+     * @var \Sabre\DAV\Server
42
+     */
43
+    protected $server;
44
+
45
+    /**
46
+     * This method should return a list of server-features.
47
+     *
48
+     * This is for example 'versioning' and is added to the DAV: header
49
+     * in an OPTIONS response.
50
+     *
51
+     * @return string[]
52
+     */
53
+    public function getFeatures() {
54
+        // May have to be changed to be detected
55
+        return ['nc-calendar-search'];
56
+    }
57
+
58
+    /**
59
+     * Returns a plugin name.
60
+     *
61
+     * Using this name other plugins will be able to access other plugins
62
+     * using Sabre\DAV\Server::getPlugin
63
+     *
64
+     * @return string
65
+     */
66
+    public function getPluginName() {
67
+        return 'nc-calendar-search';
68
+    }
69
+
70
+    /**
71
+     * This initializes the plugin.
72
+     *
73
+     * This function is called by Sabre\DAV\Server, after
74
+     * addPlugin is called.
75
+     *
76
+     * This method should set up the required event subscriptions.
77
+     *
78
+     * @param Server $server
79
+     */
80
+    public function initialize(Server $server) {
81
+        $this->server = $server;
82
+
83
+        $server->on('report', [$this, 'report']);
84
+
85
+        $server->xml->elementMap['{' . self::NS_Nextcloud . '}calendar-search'] =
86
+            CalendarSearchReport::class;
87
+    }
88
+
89
+    /**
90
+     * This functions handles REPORT requests specific to CalDAV
91
+     *
92
+     * @param string $reportName
93
+     * @param mixed $report
94
+     * @param mixed $path
95
+     * @return bool
96
+     */
97
+    public function report($reportName, $report, $path) {
98
+        switch ($reportName) {
99
+            case '{' . self::NS_Nextcloud . '}calendar-search':
100
+                $this->server->transactionType = 'report-nc-calendar-search';
101
+                $this->calendarSearch($report);
102
+                return false;
103
+        }
104
+    }
105
+
106
+    /**
107
+     * Returns a list of reports this plugin supports.
108
+     *
109
+     * This will be used in the {DAV:}supported-report-set property.
110
+     * Note that you still need to subscribe to the 'report' event to actually
111
+     * implement them
112
+     *
113
+     * @param string $uri
114
+     * @return array
115
+     */
116
+    public function getSupportedReportSet($uri) {
117
+        $node = $this->server->tree->getNodeForPath($uri);
118
+
119
+        $reports = [];
120
+        if ($node instanceof CalendarHome) {
121
+            $reports[] = '{' . self::NS_Nextcloud . '}calendar-search';
122
+        }
123
+
124
+        return $reports;
125
+    }
126
+
127
+    /**
128
+     * This function handles the calendar-query REPORT
129
+     *
130
+     * This report is used by clients to request calendar objects based on
131
+     * complex conditions.
132
+     *
133
+     * @param Xml\Request\CalendarSearchReport $report
134
+     * @return void
135
+     */
136
+    private function calendarSearch($report) {
137
+        $node = $this->server->tree->getNodeForPath($this->server->getRequestUri());
138
+        $depth = $this->server->getHTTPDepth(2);
139
+
140
+        // The default result is an empty array
141
+        $result = [];
142
+
143
+        // If we're dealing with the calendar home, the calendar home itself is
144
+        // responsible for the calendar-query
145
+        if ($node instanceof CalendarHome && $depth === 2) {
146
+            $nodePaths = $node->calendarSearch($report->filters, $report->limit, $report->offset);
147
+
148
+            foreach ($nodePaths as $path) {
149
+                [$properties] = $this->server->getPropertiesForPath(
150
+                    $this->server->getRequestUri() . '/' . $path,
151
+                    $report->properties);
152
+                $result[] = $properties;
153
+            }
154
+        }
155
+
156
+        $prefer = $this->server->getHTTPPrefer();
157
+
158
+        $this->server->httpResponse->setStatus(207);
159
+        $this->server->httpResponse->setHeader('Content-Type',
160
+            'application/xml; charset=utf-8');
161
+        $this->server->httpResponse->setHeader('Vary', 'Brief,Prefer');
162
+        $this->server->httpResponse->setBody(
163
+            $this->server->generateMultiStatus($result,
164
+                $prefer['return'] === 'minimal'));
165
+    }
166 166
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -82,7 +82,7 @@  discard block
 block discarded – undo
82 82
 
83 83
 		$server->on('report', [$this, 'report']);
84 84
 
85
-		$server->xml->elementMap['{' . self::NS_Nextcloud . '}calendar-search'] =
85
+		$server->xml->elementMap['{'.self::NS_Nextcloud.'}calendar-search'] =
86 86
 			CalendarSearchReport::class;
87 87
 	}
88 88
 
@@ -96,7 +96,7 @@  discard block
 block discarded – undo
96 96
 	 */
97 97
 	public function report($reportName, $report, $path) {
98 98
 		switch ($reportName) {
99
-			case '{' . self::NS_Nextcloud . '}calendar-search':
99
+			case '{'.self::NS_Nextcloud.'}calendar-search':
100 100
 				$this->server->transactionType = 'report-nc-calendar-search';
101 101
 				$this->calendarSearch($report);
102 102
 				return false;
@@ -118,7 +118,7 @@  discard block
 block discarded – undo
118 118
 
119 119
 		$reports = [];
120 120
 		if ($node instanceof CalendarHome) {
121
-			$reports[] = '{' . self::NS_Nextcloud . '}calendar-search';
121
+			$reports[] = '{'.self::NS_Nextcloud.'}calendar-search';
122 122
 		}
123 123
 
124 124
 		return $reports;
@@ -147,7 +147,7 @@  discard block
 block discarded – undo
147 147
 
148 148
 			foreach ($nodePaths as $path) {
149 149
 				[$properties] = $this->server->getPropertiesForPath(
150
-					$this->server->getRequestUri() . '/' . $path,
150
+					$this->server->getRequestUri().'/'.$path,
151 151
 					$report->properties);
152 152
 				$result[] = $properties;
153 153
 			}
Please login to merge, or discard this patch.