Passed
Push — master ( f0dd71...c56a27 )
by Christoph
11:49 queued 12s
created
apps/dav/lib/Upload/FutureFile.php 2 patches
Indentation   +72 added lines, -72 removed lines patch added patch discarded remove patch
@@ -38,87 +38,87 @@
 block discarded – undo
38 38
  */
39 39
 class FutureFile implements \Sabre\DAV\IFile {
40 40
 
41
-	/** @var Directory */
42
-	private $root;
43
-	/** @var string */
44
-	private $name;
41
+    /** @var Directory */
42
+    private $root;
43
+    /** @var string */
44
+    private $name;
45 45
 
46
-	/**
47
-	 * @param Directory $root
48
-	 * @param string $name
49
-	 */
50
-	function __construct(Directory $root, $name) {
51
-		$this->root = $root;
52
-		$this->name = $name;
53
-	}
46
+    /**
47
+     * @param Directory $root
48
+     * @param string $name
49
+     */
50
+    function __construct(Directory $root, $name) {
51
+        $this->root = $root;
52
+        $this->name = $name;
53
+    }
54 54
 
55
-	/**
56
-	 * @inheritdoc
57
-	 */
58
-	function put($data) {
59
-		throw new Forbidden('Permission denied to put into this file');
60
-	}
55
+    /**
56
+     * @inheritdoc
57
+     */
58
+    function put($data) {
59
+        throw new Forbidden('Permission denied to put into this file');
60
+    }
61 61
 
62
-	/**
63
-	 * @inheritdoc
64
-	 */
65
-	function get() {
66
-		$nodes = $this->root->getChildren();
67
-		return AssemblyStream::wrap($nodes);
68
-	}
62
+    /**
63
+     * @inheritdoc
64
+     */
65
+    function get() {
66
+        $nodes = $this->root->getChildren();
67
+        return AssemblyStream::wrap($nodes);
68
+    }
69 69
 
70
-	/**
71
-	 * @inheritdoc
72
-	 */
73
-	function getContentType() {
74
-		return 'application/octet-stream';
75
-	}
70
+    /**
71
+     * @inheritdoc
72
+     */
73
+    function getContentType() {
74
+        return 'application/octet-stream';
75
+    }
76 76
 
77
-	/**
78
-	 * @inheritdoc
79
-	 */
80
-	function getETag() {
81
-		return $this->root->getETag();
82
-	}
77
+    /**
78
+     * @inheritdoc
79
+     */
80
+    function getETag() {
81
+        return $this->root->getETag();
82
+    }
83 83
 
84
-	/**
85
-	 * @inheritdoc
86
-	 */
87
-	function getSize() {
88
-		$children = $this->root->getChildren();
89
-		$sizes = array_map(function ($node) {
90
-			/** @var IFile $node */
91
-			return $node->getSize();
92
-		}, $children);
84
+    /**
85
+     * @inheritdoc
86
+     */
87
+    function getSize() {
88
+        $children = $this->root->getChildren();
89
+        $sizes = array_map(function ($node) {
90
+            /** @var IFile $node */
91
+            return $node->getSize();
92
+        }, $children);
93 93
 
94
-		return array_sum($sizes);
95
-	}
94
+        return array_sum($sizes);
95
+    }
96 96
 
97
-	/**
98
-	 * @inheritdoc
99
-	 */
100
-	function delete() {
101
-		$this->root->delete();
102
-	}
97
+    /**
98
+     * @inheritdoc
99
+     */
100
+    function delete() {
101
+        $this->root->delete();
102
+    }
103 103
 
104
-	/**
105
-	 * @inheritdoc
106
-	 */
107
-	function getName() {
108
-		return $this->name;
109
-	}
104
+    /**
105
+     * @inheritdoc
106
+     */
107
+    function getName() {
108
+        return $this->name;
109
+    }
110 110
 
111
-	/**
112
-	 * @inheritdoc
113
-	 */
114
-	function setName($name) {
115
-		throw new Forbidden('Permission denied to rename this file');
116
-	}
111
+    /**
112
+     * @inheritdoc
113
+     */
114
+    function setName($name) {
115
+        throw new Forbidden('Permission denied to rename this file');
116
+    }
117 117
 
118
-	/**
119
-	 * @inheritdoc
120
-	 */
121
-	function getLastModified() {
122
-		return $this->root->getLastModified();
123
-	}
118
+    /**
119
+     * @inheritdoc
120
+     */
121
+    function getLastModified() {
122
+        return $this->root->getLastModified();
123
+    }
124 124
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -86,7 +86,7 @@
 block discarded – undo
86 86
 	 */
87 87
 	function getSize() {
88 88
 		$children = $this->root->getChildren();
89
-		$sizes = array_map(function ($node) {
89
+		$sizes = array_map(function($node) {
90 90
 			/** @var IFile $node */
91 91
 			return $node->getSize();
92 92
 		}, $children);
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/FakeLockerPlugin.php 2 patches
Indentation   +99 added lines, -99 removed lines patch added patch discarded remove patch
@@ -47,114 +47,114 @@
 block discarded – undo
47 47
  * @package OCA\DAV\Connector\Sabre
48 48
  */
49 49
 class FakeLockerPlugin extends ServerPlugin {
50
-	/** @var \Sabre\DAV\Server */
51
-	private $server;
50
+    /** @var \Sabre\DAV\Server */
51
+    private $server;
52 52
 
53
-	/** {@inheritDoc} */
54
-	public function initialize(\Sabre\DAV\Server $server) {
55
-		$this->server = $server;
56
-		$this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1);
57
-		$this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1);
58
-		$server->on('propFind', [$this, 'propFind']);
59
-		$server->on('validateTokens', [$this, 'validateTokens']);
60
-	}
53
+    /** {@inheritDoc} */
54
+    public function initialize(\Sabre\DAV\Server $server) {
55
+        $this->server = $server;
56
+        $this->server->on('method:LOCK', [$this, 'fakeLockProvider'], 1);
57
+        $this->server->on('method:UNLOCK', [$this, 'fakeUnlockProvider'], 1);
58
+        $server->on('propFind', [$this, 'propFind']);
59
+        $server->on('validateTokens', [$this, 'validateTokens']);
60
+    }
61 61
 
62
-	/**
63
-	 * Indicate that we support LOCK and UNLOCK
64
-	 *
65
-	 * @param string $path
66
-	 * @return string[]
67
-	 */
68
-	public function getHTTPMethods($path) {
69
-		return [
70
-			'LOCK',
71
-			'UNLOCK',
72
-		];
73
-	}
62
+    /**
63
+     * Indicate that we support LOCK and UNLOCK
64
+     *
65
+     * @param string $path
66
+     * @return string[]
67
+     */
68
+    public function getHTTPMethods($path) {
69
+        return [
70
+            'LOCK',
71
+            'UNLOCK',
72
+        ];
73
+    }
74 74
 
75
-	/**
76
-	 * Indicate that we support locking
77
-	 *
78
-	 * @return integer[]
79
-	 */
80
-	function getFeatures() {
81
-		return [2];
82
-	}
75
+    /**
76
+     * Indicate that we support locking
77
+     *
78
+     * @return integer[]
79
+     */
80
+    function getFeatures() {
81
+        return [2];
82
+    }
83 83
 
84
-	/**
85
-	 * Return some dummy response for PROPFIND requests with regard to locking
86
-	 *
87
-	 * @param PropFind $propFind
88
-	 * @param INode $node
89
-	 * @return void
90
-	 */
91
-	function propFind(PropFind $propFind, INode $node) {
92
-		$propFind->handle('{DAV:}supportedlock', function () {
93
-			return new SupportedLock(true);
94
-		});
95
-		$propFind->handle('{DAV:}lockdiscovery', function () use ($propFind) {
96
-			return new LockDiscovery([]);
97
-		});
98
-	}
84
+    /**
85
+     * Return some dummy response for PROPFIND requests with regard to locking
86
+     *
87
+     * @param PropFind $propFind
88
+     * @param INode $node
89
+     * @return void
90
+     */
91
+    function propFind(PropFind $propFind, INode $node) {
92
+        $propFind->handle('{DAV:}supportedlock', function () {
93
+            return new SupportedLock(true);
94
+        });
95
+        $propFind->handle('{DAV:}lockdiscovery', function () use ($propFind) {
96
+            return new LockDiscovery([]);
97
+        });
98
+    }
99 99
 
100
-	/**
101
-	 * Mark a locking token always as valid
102
-	 *
103
-	 * @param RequestInterface $request
104
-	 * @param array $conditions
105
-	 */
106
-	public function validateTokens(RequestInterface $request, &$conditions) {
107
-		foreach($conditions as &$fileCondition) {
108
-			if(isset($fileCondition['tokens'])) {
109
-				foreach($fileCondition['tokens'] as &$token) {
110
-					if(isset($token['token'])) {
111
-						if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
112
-							$token['validToken'] = true;
113
-						}
114
-					}
115
-				}
116
-			}
117
-		}
118
-	}
100
+    /**
101
+     * Mark a locking token always as valid
102
+     *
103
+     * @param RequestInterface $request
104
+     * @param array $conditions
105
+     */
106
+    public function validateTokens(RequestInterface $request, &$conditions) {
107
+        foreach($conditions as &$fileCondition) {
108
+            if(isset($fileCondition['tokens'])) {
109
+                foreach($fileCondition['tokens'] as &$token) {
110
+                    if(isset($token['token'])) {
111
+                        if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
112
+                            $token['validToken'] = true;
113
+                        }
114
+                    }
115
+                }
116
+            }
117
+        }
118
+    }
119 119
 
120
-	/**
121
-	 * Fakes a successful LOCK
122
-	 *
123
-	 * @param RequestInterface $request
124
-	 * @param ResponseInterface $response
125
-	 * @return bool
126
-	 */
127
-	public function fakeLockProvider(RequestInterface $request,
128
-									 ResponseInterface $response) {
120
+    /**
121
+     * Fakes a successful LOCK
122
+     *
123
+     * @param RequestInterface $request
124
+     * @param ResponseInterface $response
125
+     * @return bool
126
+     */
127
+    public function fakeLockProvider(RequestInterface $request,
128
+                                        ResponseInterface $response) {
129 129
 
130
-		$lockInfo = new LockInfo();
131
-		$lockInfo->token = md5($request->getPath());
132
-		$lockInfo->uri = $request->getPath();
133
-		$lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
134
-		$lockInfo->timeout = 1800;
130
+        $lockInfo = new LockInfo();
131
+        $lockInfo->token = md5($request->getPath());
132
+        $lockInfo->uri = $request->getPath();
133
+        $lockInfo->depth = \Sabre\DAV\Server::DEPTH_INFINITY;
134
+        $lockInfo->timeout = 1800;
135 135
 
136
-		$body = $this->server->xml->write('{DAV:}prop', [
137
-			'{DAV:}lockdiscovery' =>
138
-					new LockDiscovery([$lockInfo])
139
-		]);
136
+        $body = $this->server->xml->write('{DAV:}prop', [
137
+            '{DAV:}lockdiscovery' =>
138
+                    new LockDiscovery([$lockInfo])
139
+        ]);
140 140
 
141
-		$response->setStatus(200);
142
-		$response->setBody($body);
141
+        $response->setStatus(200);
142
+        $response->setBody($body);
143 143
 
144
-		return false;
145
-	}
144
+        return false;
145
+    }
146 146
 
147
-	/**
148
-	 * Fakes a successful LOCK
149
-	 *
150
-	 * @param RequestInterface $request
151
-	 * @param ResponseInterface $response
152
-	 * @return bool
153
-	 */
154
-	public function fakeUnlockProvider(RequestInterface $request,
155
-									 ResponseInterface $response) {
156
-		$response->setStatus(204);
157
-		$response->setHeader('Content-Length', '0');
158
-		return false;
159
-	}
147
+    /**
148
+     * Fakes a successful LOCK
149
+     *
150
+     * @param RequestInterface $request
151
+     * @param ResponseInterface $response
152
+     * @return bool
153
+     */
154
+    public function fakeUnlockProvider(RequestInterface $request,
155
+                                        ResponseInterface $response) {
156
+        $response->setStatus(204);
157
+        $response->setHeader('Content-Length', '0');
158
+        return false;
159
+    }
160 160
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -89,10 +89,10 @@  discard block
 block discarded – undo
89 89
 	 * @return void
90 90
 	 */
91 91
 	function propFind(PropFind $propFind, INode $node) {
92
-		$propFind->handle('{DAV:}supportedlock', function () {
92
+		$propFind->handle('{DAV:}supportedlock', function() {
93 93
 			return new SupportedLock(true);
94 94
 		});
95
-		$propFind->handle('{DAV:}lockdiscovery', function () use ($propFind) {
95
+		$propFind->handle('{DAV:}lockdiscovery', function() use ($propFind) {
96 96
 			return new LockDiscovery([]);
97 97
 		});
98 98
 	}
@@ -104,11 +104,11 @@  discard block
 block discarded – undo
104 104
 	 * @param array $conditions
105 105
 	 */
106 106
 	public function validateTokens(RequestInterface $request, &$conditions) {
107
-		foreach($conditions as &$fileCondition) {
108
-			if(isset($fileCondition['tokens'])) {
109
-				foreach($fileCondition['tokens'] as &$token) {
110
-					if(isset($token['token'])) {
111
-						if(substr($token['token'], 0, 16) === 'opaquelocktoken:') {
107
+		foreach ($conditions as &$fileCondition) {
108
+			if (isset($fileCondition['tokens'])) {
109
+				foreach ($fileCondition['tokens'] as &$token) {
110
+					if (isset($token['token'])) {
111
+						if (substr($token['token'], 0, 16) === 'opaquelocktoken:') {
112 112
 							$token['validToken'] = true;
113 113
 						}
114 114
 					}
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/SharesPlugin.php 2 patches
Indentation   +177 added lines, -177 removed lines patch added patch discarded remove patch
@@ -36,181 +36,181 @@
 block discarded – undo
36 36
  */
37 37
 class SharesPlugin extends \Sabre\DAV\ServerPlugin {
38 38
 
39
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
40
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
41
-	const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
42
-	const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
43
-
44
-	/**
45
-	 * Reference to main server object
46
-	 *
47
-	 * @var \Sabre\DAV\Server
48
-	 */
49
-	private $server;
50
-
51
-	/**
52
-	 * @var \OCP\Share\IManager
53
-	 */
54
-	private $shareManager;
55
-
56
-	/**
57
-	 * @var \Sabre\DAV\Tree
58
-	 */
59
-	private $tree;
60
-
61
-	/**
62
-	 * @var string
63
-	 */
64
-	private $userId;
65
-
66
-	/**
67
-	 * @var \OCP\Files\Folder
68
-	 */
69
-	private $userFolder;
70
-
71
-	/** @var IShare[] */
72
-	private $cachedShares = [];
73
-
74
-	private $cachedFolders = [];
75
-
76
-	/**
77
-	 * @param \Sabre\DAV\Tree $tree tree
78
-	 * @param IUserSession $userSession user session
79
-	 * @param \OCP\Files\Folder $userFolder user home folder
80
-	 * @param \OCP\Share\IManager $shareManager share manager
81
-	 */
82
-	public function __construct(
83
-		\Sabre\DAV\Tree $tree,
84
-		IUserSession $userSession,
85
-		\OCP\Files\Folder $userFolder,
86
-		\OCP\Share\IManager $shareManager
87
-	) {
88
-		$this->tree = $tree;
89
-		$this->shareManager = $shareManager;
90
-		$this->userFolder = $userFolder;
91
-		$this->userId = $userSession->getUser()->getUID();
92
-	}
93
-
94
-	/**
95
-	 * This initializes the plugin.
96
-	 *
97
-	 * This function is called by \Sabre\DAV\Server, after
98
-	 * addPlugin is called.
99
-	 *
100
-	 * This method should set up the required event subscriptions.
101
-	 *
102
-	 * @param \Sabre\DAV\Server $server
103
-	 */
104
-	public function initialize(\Sabre\DAV\Server $server) {
105
-		$server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
106
-		$server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
107
-		$server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
108
-		$server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
109
-
110
-		$this->server = $server;
111
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
112
-	}
113
-
114
-	private function getShare(\OCP\Files\Node $node): array {
115
-		$result = [];
116
-		$requestedShareTypes = [
117
-			\OCP\Share::SHARE_TYPE_USER,
118
-			\OCP\Share::SHARE_TYPE_GROUP,
119
-			\OCP\Share::SHARE_TYPE_LINK,
120
-			\OCP\Share::SHARE_TYPE_REMOTE,
121
-			\OCP\Share::SHARE_TYPE_EMAIL,
122
-			\OCP\Share::SHARE_TYPE_ROOM,
123
-			\OCP\Share::SHARE_TYPE_CIRCLE,
124
-		];
125
-		foreach ($requestedShareTypes as $requestedShareType) {
126
-			$shares = $this->shareManager->getSharesBy(
127
-				$this->userId,
128
-				$requestedShareType,
129
-				$node,
130
-				false,
131
-				-1
132
-			);
133
-			foreach ($shares as $share) {
134
-				$result[] = $share;
135
-			}
136
-		}
137
-		return $result;
138
-	}
139
-
140
-	private function getSharesFolder(\OCP\Files\Folder $node): array {
141
-		return $this->shareManager->getSharesInFolder(
142
-			$this->userId,
143
-			$node,
144
-			true
145
-		);
146
-	}
147
-
148
-	private function getShares(\Sabre\DAV\INode $sabreNode): array {
149
-		if (isset($this->cachedShares[$sabreNode->getId()])) {
150
-			$shares = $this->cachedShares[$sabreNode->getId()];
151
-		} else {
152
-			list($parentPath,) = \Sabre\Uri\split($sabreNode->getPath());
153
-			if ($parentPath === '') {
154
-				$parentPath = '/';
155
-			}
156
-			// if we already cached the folder this file is in we know there are no shares for this file
157
-			if (array_search($parentPath, $this->cachedFolders) === false) {
158
-				$node = $this->userFolder->get($sabreNode->getPath());
159
-				$shares = $this->getShare($node);
160
-				$this->cachedShares[$sabreNode->getId()] = $shares;
161
-			} else {
162
-				return [];
163
-			}
164
-		}
165
-
166
-		return $shares;
167
-	}
168
-
169
-	/**
170
-	 * Adds shares to propfind response
171
-	 *
172
-	 * @param PropFind $propFind propfind object
173
-	 * @param \Sabre\DAV\INode $sabreNode sabre node
174
-	 */
175
-	public function handleGetProperties(
176
-		PropFind $propFind,
177
-		\Sabre\DAV\INode $sabreNode
178
-	) {
179
-		if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
180
-			return;
181
-		}
182
-
183
-		// need prefetch ?
184
-		if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
185
-			&& $propFind->getDepth() !== 0
186
-			&& (
187
-				!is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
188
-				!is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
189
-			)
190
-		) {
191
-			$folderNode = $this->userFolder->get($sabreNode->getPath());
192
-
193
-			$this->cachedFolders[] = $sabreNode->getPath();
194
-			$childShares = $this->getSharesFolder($folderNode);
195
-			foreach ($childShares as $id => $shares) {
196
-				$this->cachedShares[$id] = $shares;
197
-			}
198
-		}
199
-
200
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
201
-			$shares = $this->getShares($sabreNode);
202
-
203
-			$shareTypes = array_unique(array_map(function (IShare $share) {
204
-				return $share->getShareType();
205
-			}, $shares));
206
-
207
-			return new ShareTypeList($shareTypes);
208
-		});
209
-
210
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
211
-			$shares = $this->getShares($sabreNode);
212
-
213
-			return new ShareeList($shares);
214
-		});
215
-	}
39
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
40
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
41
+    const SHARETYPES_PROPERTYNAME = '{http://owncloud.org/ns}share-types';
42
+    const SHAREES_PROPERTYNAME = '{http://nextcloud.org/ns}sharees';
43
+
44
+    /**
45
+     * Reference to main server object
46
+     *
47
+     * @var \Sabre\DAV\Server
48
+     */
49
+    private $server;
50
+
51
+    /**
52
+     * @var \OCP\Share\IManager
53
+     */
54
+    private $shareManager;
55
+
56
+    /**
57
+     * @var \Sabre\DAV\Tree
58
+     */
59
+    private $tree;
60
+
61
+    /**
62
+     * @var string
63
+     */
64
+    private $userId;
65
+
66
+    /**
67
+     * @var \OCP\Files\Folder
68
+     */
69
+    private $userFolder;
70
+
71
+    /** @var IShare[] */
72
+    private $cachedShares = [];
73
+
74
+    private $cachedFolders = [];
75
+
76
+    /**
77
+     * @param \Sabre\DAV\Tree $tree tree
78
+     * @param IUserSession $userSession user session
79
+     * @param \OCP\Files\Folder $userFolder user home folder
80
+     * @param \OCP\Share\IManager $shareManager share manager
81
+     */
82
+    public function __construct(
83
+        \Sabre\DAV\Tree $tree,
84
+        IUserSession $userSession,
85
+        \OCP\Files\Folder $userFolder,
86
+        \OCP\Share\IManager $shareManager
87
+    ) {
88
+        $this->tree = $tree;
89
+        $this->shareManager = $shareManager;
90
+        $this->userFolder = $userFolder;
91
+        $this->userId = $userSession->getUser()->getUID();
92
+    }
93
+
94
+    /**
95
+     * This initializes the plugin.
96
+     *
97
+     * This function is called by \Sabre\DAV\Server, after
98
+     * addPlugin is called.
99
+     *
100
+     * This method should set up the required event subscriptions.
101
+     *
102
+     * @param \Sabre\DAV\Server $server
103
+     */
104
+    public function initialize(\Sabre\DAV\Server $server) {
105
+        $server->xml->namespacesMap[self::NS_OWNCLOUD] = 'oc';
106
+        $server->xml->elementMap[self::SHARETYPES_PROPERTYNAME] = ShareTypeList::class;
107
+        $server->protectedProperties[] = self::SHARETYPES_PROPERTYNAME;
108
+        $server->protectedProperties[] = self::SHAREES_PROPERTYNAME;
109
+
110
+        $this->server = $server;
111
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
112
+    }
113
+
114
+    private function getShare(\OCP\Files\Node $node): array {
115
+        $result = [];
116
+        $requestedShareTypes = [
117
+            \OCP\Share::SHARE_TYPE_USER,
118
+            \OCP\Share::SHARE_TYPE_GROUP,
119
+            \OCP\Share::SHARE_TYPE_LINK,
120
+            \OCP\Share::SHARE_TYPE_REMOTE,
121
+            \OCP\Share::SHARE_TYPE_EMAIL,
122
+            \OCP\Share::SHARE_TYPE_ROOM,
123
+            \OCP\Share::SHARE_TYPE_CIRCLE,
124
+        ];
125
+        foreach ($requestedShareTypes as $requestedShareType) {
126
+            $shares = $this->shareManager->getSharesBy(
127
+                $this->userId,
128
+                $requestedShareType,
129
+                $node,
130
+                false,
131
+                -1
132
+            );
133
+            foreach ($shares as $share) {
134
+                $result[] = $share;
135
+            }
136
+        }
137
+        return $result;
138
+    }
139
+
140
+    private function getSharesFolder(\OCP\Files\Folder $node): array {
141
+        return $this->shareManager->getSharesInFolder(
142
+            $this->userId,
143
+            $node,
144
+            true
145
+        );
146
+    }
147
+
148
+    private function getShares(\Sabre\DAV\INode $sabreNode): array {
149
+        if (isset($this->cachedShares[$sabreNode->getId()])) {
150
+            $shares = $this->cachedShares[$sabreNode->getId()];
151
+        } else {
152
+            list($parentPath,) = \Sabre\Uri\split($sabreNode->getPath());
153
+            if ($parentPath === '') {
154
+                $parentPath = '/';
155
+            }
156
+            // if we already cached the folder this file is in we know there are no shares for this file
157
+            if (array_search($parentPath, $this->cachedFolders) === false) {
158
+                $node = $this->userFolder->get($sabreNode->getPath());
159
+                $shares = $this->getShare($node);
160
+                $this->cachedShares[$sabreNode->getId()] = $shares;
161
+            } else {
162
+                return [];
163
+            }
164
+        }
165
+
166
+        return $shares;
167
+    }
168
+
169
+    /**
170
+     * Adds shares to propfind response
171
+     *
172
+     * @param PropFind $propFind propfind object
173
+     * @param \Sabre\DAV\INode $sabreNode sabre node
174
+     */
175
+    public function handleGetProperties(
176
+        PropFind $propFind,
177
+        \Sabre\DAV\INode $sabreNode
178
+    ) {
179
+        if (!($sabreNode instanceof \OCA\DAV\Connector\Sabre\Node)) {
180
+            return;
181
+        }
182
+
183
+        // need prefetch ?
184
+        if ($sabreNode instanceof \OCA\DAV\Connector\Sabre\Directory
185
+            && $propFind->getDepth() !== 0
186
+            && (
187
+                !is_null($propFind->getStatus(self::SHARETYPES_PROPERTYNAME)) ||
188
+                !is_null($propFind->getStatus(self::SHAREES_PROPERTYNAME))
189
+            )
190
+        ) {
191
+            $folderNode = $this->userFolder->get($sabreNode->getPath());
192
+
193
+            $this->cachedFolders[] = $sabreNode->getPath();
194
+            $childShares = $this->getSharesFolder($folderNode);
195
+            foreach ($childShares as $id => $shares) {
196
+                $this->cachedShares[$id] = $shares;
197
+            }
198
+        }
199
+
200
+        $propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
201
+            $shares = $this->getShares($sabreNode);
202
+
203
+            $shareTypes = array_unique(array_map(function (IShare $share) {
204
+                return $share->getShareType();
205
+            }, $shares));
206
+
207
+            return new ShareTypeList($shareTypes);
208
+        });
209
+
210
+        $propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
211
+            $shares = $this->getShares($sabreNode);
212
+
213
+            return new ShareeList($shares);
214
+        });
215
+    }
216 216
 }
Please login to merge, or discard this patch.
Spacing   +3 added lines, -3 removed lines patch added patch discarded remove patch
@@ -197,17 +197,17 @@
 block discarded – undo
197 197
 			}
198 198
 		}
199 199
 
200
-		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function () use ($sabreNode) {
200
+		$propFind->handle(self::SHARETYPES_PROPERTYNAME, function() use ($sabreNode) {
201 201
 			$shares = $this->getShares($sabreNode);
202 202
 
203
-			$shareTypes = array_unique(array_map(function (IShare $share) {
203
+			$shareTypes = array_unique(array_map(function(IShare $share) {
204 204
 				return $share->getShareType();
205 205
 			}, $shares));
206 206
 
207 207
 			return new ShareTypeList($shareTypes);
208 208
 		});
209 209
 
210
-		$propFind->handle(self::SHAREES_PROPERTYNAME, function () use ($sabreNode) {
210
+		$propFind->handle(self::SHAREES_PROPERTYNAME, function() use ($sabreNode) {
211 211
 			$shares = $this->getShares($sabreNode);
212 212
 
213 213
 			return new ShareeList($shares);
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/TagsPlugin.php 2 patches
Indentation   +217 added lines, -217 removed lines patch added patch discarded remove patch
@@ -55,246 +55,246 @@
 block discarded – undo
55 55
 class TagsPlugin extends \Sabre\DAV\ServerPlugin
56 56
 {
57 57
 
58
-	// namespace
59
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
60
-	const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
61
-	const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
62
-	const TAG_FAVORITE = '_$!<Favorite>!$_';
58
+    // namespace
59
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
60
+    const TAGS_PROPERTYNAME = '{http://owncloud.org/ns}tags';
61
+    const FAVORITE_PROPERTYNAME = '{http://owncloud.org/ns}favorite';
62
+    const TAG_FAVORITE = '_$!<Favorite>!$_';
63 63
 
64
-	/**
65
-	 * Reference to main server object
66
-	 *
67
-	 * @var \Sabre\DAV\Server
68
-	 */
69
-	private $server;
64
+    /**
65
+     * Reference to main server object
66
+     *
67
+     * @var \Sabre\DAV\Server
68
+     */
69
+    private $server;
70 70
 
71
-	/**
72
-	 * @var \OCP\ITagManager
73
-	 */
74
-	private $tagManager;
71
+    /**
72
+     * @var \OCP\ITagManager
73
+     */
74
+    private $tagManager;
75 75
 
76
-	/**
77
-	 * @var \OCP\ITags
78
-	 */
79
-	private $tagger;
76
+    /**
77
+     * @var \OCP\ITags
78
+     */
79
+    private $tagger;
80 80
 
81
-	/**
82
-	 * Array of file id to tags array
83
-	 * The null value means the cache wasn't initialized.
84
-	 *
85
-	 * @var array
86
-	 */
87
-	private $cachedTags;
81
+    /**
82
+     * Array of file id to tags array
83
+     * The null value means the cache wasn't initialized.
84
+     *
85
+     * @var array
86
+     */
87
+    private $cachedTags;
88 88
 
89
-	/**
90
-	 * @var \Sabre\DAV\Tree
91
-	 */
92
-	private $tree;
89
+    /**
90
+     * @var \Sabre\DAV\Tree
91
+     */
92
+    private $tree;
93 93
 
94
-	/**
95
-	 * @param \Sabre\DAV\Tree $tree tree
96
-	 * @param \OCP\ITagManager $tagManager tag manager
97
-	 */
98
-	public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
99
-		$this->tree = $tree;
100
-		$this->tagManager = $tagManager;
101
-		$this->tagger = null;
102
-		$this->cachedTags = [];
103
-	}
94
+    /**
95
+     * @param \Sabre\DAV\Tree $tree tree
96
+     * @param \OCP\ITagManager $tagManager tag manager
97
+     */
98
+    public function __construct(\Sabre\DAV\Tree $tree, \OCP\ITagManager $tagManager) {
99
+        $this->tree = $tree;
100
+        $this->tagManager = $tagManager;
101
+        $this->tagger = null;
102
+        $this->cachedTags = [];
103
+    }
104 104
 
105
-	/**
106
-	 * This initializes the plugin.
107
-	 *
108
-	 * This function is called by \Sabre\DAV\Server, after
109
-	 * addPlugin is called.
110
-	 *
111
-	 * This method should set up the required event subscriptions.
112
-	 *
113
-	 * @param \Sabre\DAV\Server $server
114
-	 * @return void
115
-	 */
116
-	public function initialize(\Sabre\DAV\Server $server) {
105
+    /**
106
+     * This initializes the plugin.
107
+     *
108
+     * This function is called by \Sabre\DAV\Server, after
109
+     * addPlugin is called.
110
+     *
111
+     * This method should set up the required event subscriptions.
112
+     *
113
+     * @param \Sabre\DAV\Server $server
114
+     * @return void
115
+     */
116
+    public function initialize(\Sabre\DAV\Server $server) {
117 117
 
118
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
119
-		$server->xml->elementMap[self::TAGS_PROPERTYNAME] = TagList::class;
118
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
119
+        $server->xml->elementMap[self::TAGS_PROPERTYNAME] = TagList::class;
120 120
 
121
-		$this->server = $server;
122
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
123
-		$this->server->on('propPatch', [$this, 'handleUpdateProperties']);
124
-	}
121
+        $this->server = $server;
122
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
123
+        $this->server->on('propPatch', [$this, 'handleUpdateProperties']);
124
+    }
125 125
 
126
-	/**
127
-	 * Returns the tagger
128
-	 *
129
-	 * @return \OCP\ITags tagger
130
-	 */
131
-	private function getTagger() {
132
-		if (!$this->tagger) {
133
-			$this->tagger = $this->tagManager->load('files');
134
-		}
135
-		return $this->tagger;
136
-	}
126
+    /**
127
+     * Returns the tagger
128
+     *
129
+     * @return \OCP\ITags tagger
130
+     */
131
+    private function getTagger() {
132
+        if (!$this->tagger) {
133
+            $this->tagger = $this->tagManager->load('files');
134
+        }
135
+        return $this->tagger;
136
+    }
137 137
 
138
-	/**
139
-	 * Returns tags and favorites.
140
-	 *
141
-	 * @param integer $fileId file id
142
-	 * @return array list($tags, $favorite) with $tags as tag array
143
-	 * and $favorite is a boolean whether the file was favorited
144
-	 */
145
-	private function getTagsAndFav($fileId) {
146
-		$isFav = false;
147
-		$tags = $this->getTags($fileId);
148
-		if ($tags) {
149
-			$favPos = array_search(self::TAG_FAVORITE, $tags);
150
-			if ($favPos !== false) {
151
-				$isFav = true;
152
-				unset($tags[$favPos]);
153
-			}
154
-		}
155
-		return [$tags, $isFav];
156
-	}
138
+    /**
139
+     * Returns tags and favorites.
140
+     *
141
+     * @param integer $fileId file id
142
+     * @return array list($tags, $favorite) with $tags as tag array
143
+     * and $favorite is a boolean whether the file was favorited
144
+     */
145
+    private function getTagsAndFav($fileId) {
146
+        $isFav = false;
147
+        $tags = $this->getTags($fileId);
148
+        if ($tags) {
149
+            $favPos = array_search(self::TAG_FAVORITE, $tags);
150
+            if ($favPos !== false) {
151
+                $isFav = true;
152
+                unset($tags[$favPos]);
153
+            }
154
+        }
155
+        return [$tags, $isFav];
156
+    }
157 157
 
158
-	/**
159
-	 * Returns tags for the given file id
160
-	 *
161
-	 * @param integer $fileId file id
162
-	 * @return array list of tags for that file
163
-	 */
164
-	private function getTags($fileId) {
165
-		if (isset($this->cachedTags[$fileId])) {
166
-			return $this->cachedTags[$fileId];
167
-		} else {
168
-			$tags = $this->getTagger()->getTagsForObjects([$fileId]);
169
-			if ($tags !== false) {
170
-				if (empty($tags)) {
171
-					return [];
172
-				}
173
-				return current($tags);
174
-			}
175
-		}
176
-		return null;
177
-	}
158
+    /**
159
+     * Returns tags for the given file id
160
+     *
161
+     * @param integer $fileId file id
162
+     * @return array list of tags for that file
163
+     */
164
+    private function getTags($fileId) {
165
+        if (isset($this->cachedTags[$fileId])) {
166
+            return $this->cachedTags[$fileId];
167
+        } else {
168
+            $tags = $this->getTagger()->getTagsForObjects([$fileId]);
169
+            if ($tags !== false) {
170
+                if (empty($tags)) {
171
+                    return [];
172
+                }
173
+                return current($tags);
174
+            }
175
+        }
176
+        return null;
177
+    }
178 178
 
179
-	/**
180
-	 * Updates the tags of the given file id
181
-	 *
182
-	 * @param int $fileId
183
-	 * @param array $tags array of tag strings
184
-	 */
185
-	private function updateTags($fileId, $tags) {
186
-		$tagger = $this->getTagger();
187
-		$currentTags = $this->getTags($fileId);
179
+    /**
180
+     * Updates the tags of the given file id
181
+     *
182
+     * @param int $fileId
183
+     * @param array $tags array of tag strings
184
+     */
185
+    private function updateTags($fileId, $tags) {
186
+        $tagger = $this->getTagger();
187
+        $currentTags = $this->getTags($fileId);
188 188
 
189
-		$newTags = array_diff($tags, $currentTags);
190
-		foreach ($newTags as $tag) {
191
-			if ($tag === self::TAG_FAVORITE) {
192
-				continue;
193
-			}
194
-			$tagger->tagAs($fileId, $tag);
195
-		}
196
-		$deletedTags = array_diff($currentTags, $tags);
197
-		foreach ($deletedTags as $tag) {
198
-			if ($tag === self::TAG_FAVORITE) {
199
-				continue;
200
-			}
201
-			$tagger->unTag($fileId, $tag);
202
-		}
203
-	}
189
+        $newTags = array_diff($tags, $currentTags);
190
+        foreach ($newTags as $tag) {
191
+            if ($tag === self::TAG_FAVORITE) {
192
+                continue;
193
+            }
194
+            $tagger->tagAs($fileId, $tag);
195
+        }
196
+        $deletedTags = array_diff($currentTags, $tags);
197
+        foreach ($deletedTags as $tag) {
198
+            if ($tag === self::TAG_FAVORITE) {
199
+                continue;
200
+            }
201
+            $tagger->unTag($fileId, $tag);
202
+        }
203
+    }
204 204
 
205
-	/**
206
-	 * Adds tags and favorites properties to the response,
207
-	 * if requested.
208
-	 *
209
-	 * @param PropFind $propFind
210
-	 * @param \Sabre\DAV\INode $node
211
-	 * @return void
212
-	 */
213
-	public function handleGetProperties(
214
-		PropFind $propFind,
215
-		\Sabre\DAV\INode $node
216
-	) {
217
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
218
-			return;
219
-		}
205
+    /**
206
+     * Adds tags and favorites properties to the response,
207
+     * if requested.
208
+     *
209
+     * @param PropFind $propFind
210
+     * @param \Sabre\DAV\INode $node
211
+     * @return void
212
+     */
213
+    public function handleGetProperties(
214
+        PropFind $propFind,
215
+        \Sabre\DAV\INode $node
216
+    ) {
217
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
218
+            return;
219
+        }
220 220
 
221
-		// need prefetch ?
222
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
223
-			&& $propFind->getDepth() !== 0
224
-			&& (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME))
225
-			|| !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME))
226
-		)) {
227
-			// note: pre-fetching only supported for depth <= 1
228
-			$folderContent = $node->getChildren();
229
-			$fileIds[] = (int)$node->getId();
230
-			foreach ($folderContent as $info) {
231
-				$fileIds[] = (int)$info->getId();
232
-			}
233
-			$tags = $this->getTagger()->getTagsForObjects($fileIds);
234
-			if ($tags === false) {
235
-				// the tags API returns false on error...
236
-				$tags = [];
237
-			}
221
+        // need prefetch ?
222
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
223
+            && $propFind->getDepth() !== 0
224
+            && (!is_null($propFind->getStatus(self::TAGS_PROPERTYNAME))
225
+            || !is_null($propFind->getStatus(self::FAVORITE_PROPERTYNAME))
226
+        )) {
227
+            // note: pre-fetching only supported for depth <= 1
228
+            $folderContent = $node->getChildren();
229
+            $fileIds[] = (int)$node->getId();
230
+            foreach ($folderContent as $info) {
231
+                $fileIds[] = (int)$info->getId();
232
+            }
233
+            $tags = $this->getTagger()->getTagsForObjects($fileIds);
234
+            if ($tags === false) {
235
+                // the tags API returns false on error...
236
+                $tags = [];
237
+            }
238 238
 
239
-			$this->cachedTags = $this->cachedTags + $tags;
240
-			$emptyFileIds = array_diff($fileIds, array_keys($tags));
241
-			// also cache the ones that were not found
242
-			foreach ($emptyFileIds as $fileId) {
243
-				$this->cachedTags[$fileId] = [];
244
-			}
245
-		}
239
+            $this->cachedTags = $this->cachedTags + $tags;
240
+            $emptyFileIds = array_diff($fileIds, array_keys($tags));
241
+            // also cache the ones that were not found
242
+            foreach ($emptyFileIds as $fileId) {
243
+                $this->cachedTags[$fileId] = [];
244
+            }
245
+        }
246 246
 
247
-		$isFav = null;
247
+        $isFav = null;
248 248
 
249
-		$propFind->handle(self::TAGS_PROPERTYNAME, function () use (&$isFav, $node) {
250
-			list($tags, $isFav) = $this->getTagsAndFav($node->getId());
251
-			return new TagList($tags);
252
-		});
249
+        $propFind->handle(self::TAGS_PROPERTYNAME, function () use (&$isFav, $node) {
250
+            list($tags, $isFav) = $this->getTagsAndFav($node->getId());
251
+            return new TagList($tags);
252
+        });
253 253
 
254
-		$propFind->handle(self::FAVORITE_PROPERTYNAME, function () use ($isFav, $node) {
255
-			if (is_null($isFav)) {
256
-				list(, $isFav) = $this->getTagsAndFav($node->getId());
257
-			}
258
-			if ($isFav) {
259
-				return 1;
260
-			} else {
261
-				return 0;
262
-			}
263
-		});
264
-	}
254
+        $propFind->handle(self::FAVORITE_PROPERTYNAME, function () use ($isFav, $node) {
255
+            if (is_null($isFav)) {
256
+                list(, $isFav) = $this->getTagsAndFav($node->getId());
257
+            }
258
+            if ($isFav) {
259
+                return 1;
260
+            } else {
261
+                return 0;
262
+            }
263
+        });
264
+    }
265 265
 
266
-	/**
267
-	 * Updates tags and favorites properties, if applicable.
268
-	 *
269
-	 * @param string $path
270
-	 * @param PropPatch $propPatch
271
-	 *
272
-	 * @return void
273
-	 */
274
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
275
-		$node = $this->tree->getNodeForPath($path);
276
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
277
-			return;
278
-		}
266
+    /**
267
+     * Updates tags and favorites properties, if applicable.
268
+     *
269
+     * @param string $path
270
+     * @param PropPatch $propPatch
271
+     *
272
+     * @return void
273
+     */
274
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
275
+        $node = $this->tree->getNodeForPath($path);
276
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
277
+            return;
278
+        }
279 279
 
280
-		$propPatch->handle(self::TAGS_PROPERTYNAME, function ($tagList) use ($node) {
281
-			$this->updateTags($node->getId(), $tagList->getTags());
282
-			return true;
283
-		});
280
+        $propPatch->handle(self::TAGS_PROPERTYNAME, function ($tagList) use ($node) {
281
+            $this->updateTags($node->getId(), $tagList->getTags());
282
+            return true;
283
+        });
284 284
 
285
-		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function ($favState) use ($node) {
286
-			if ((int)$favState === 1 || $favState === 'true') {
287
-				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
288
-			} else {
289
-				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
290
-			}
285
+        $propPatch->handle(self::FAVORITE_PROPERTYNAME, function ($favState) use ($node) {
286
+            if ((int)$favState === 1 || $favState === 'true') {
287
+                $this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
288
+            } else {
289
+                $this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
290
+            }
291 291
 
292
-			if (is_null($favState)) {
293
-				// confirm deletion
294
-				return 204;
295
-			}
292
+            if (is_null($favState)) {
293
+                // confirm deletion
294
+                return 204;
295
+            }
296 296
 
297
-			return 200;
298
-		});
299
-	}
297
+            return 200;
298
+        });
299
+    }
300 300
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -226,9 +226,9 @@  discard block
 block discarded – undo
226 226
 		)) {
227 227
 			// note: pre-fetching only supported for depth <= 1
228 228
 			$folderContent = $node->getChildren();
229
-			$fileIds[] = (int)$node->getId();
229
+			$fileIds[] = (int) $node->getId();
230 230
 			foreach ($folderContent as $info) {
231
-				$fileIds[] = (int)$info->getId();
231
+				$fileIds[] = (int) $info->getId();
232 232
 			}
233 233
 			$tags = $this->getTagger()->getTagsForObjects($fileIds);
234 234
 			if ($tags === false) {
@@ -246,12 +246,12 @@  discard block
 block discarded – undo
246 246
 
247 247
 		$isFav = null;
248 248
 
249
-		$propFind->handle(self::TAGS_PROPERTYNAME, function () use (&$isFav, $node) {
249
+		$propFind->handle(self::TAGS_PROPERTYNAME, function() use (&$isFav, $node) {
250 250
 			list($tags, $isFav) = $this->getTagsAndFav($node->getId());
251 251
 			return new TagList($tags);
252 252
 		});
253 253
 
254
-		$propFind->handle(self::FAVORITE_PROPERTYNAME, function () use ($isFav, $node) {
254
+		$propFind->handle(self::FAVORITE_PROPERTYNAME, function() use ($isFav, $node) {
255 255
 			if (is_null($isFav)) {
256 256
 				list(, $isFav) = $this->getTagsAndFav($node->getId());
257 257
 			}
@@ -277,13 +277,13 @@  discard block
 block discarded – undo
277 277
 			return;
278 278
 		}
279 279
 
280
-		$propPatch->handle(self::TAGS_PROPERTYNAME, function ($tagList) use ($node) {
280
+		$propPatch->handle(self::TAGS_PROPERTYNAME, function($tagList) use ($node) {
281 281
 			$this->updateTags($node->getId(), $tagList->getTags());
282 282
 			return true;
283 283
 		});
284 284
 
285
-		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function ($favState) use ($node) {
286
-			if ((int)$favState === 1 || $favState === 'true') {
285
+		$propPatch->handle(self::FAVORITE_PROPERTYNAME, function($favState) use ($node) {
286
+			if ((int) $favState === 1 || $favState === 'true') {
287 287
 				$this->getTagger()->tagAs($node->getId(), self::TAG_FAVORITE);
288 288
 			} else {
289 289
 				$this->getTagger()->unTag($node->getId(), self::TAG_FAVORITE);
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/FilesPlugin.php 2 patches
Indentation   +466 added lines, -466 removed lines patch added patch discarded remove patch
@@ -53,470 +53,470 @@
 block discarded – undo
53 53
 
54 54
 class FilesPlugin extends ServerPlugin {
55 55
 
56
-	// namespace
57
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
58
-	const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
59
-	const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
60
-	const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
61
-	const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
62
-	const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
63
-	const OCM_SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-cloud-mesh.org/ns}share-permissions';
64
-	const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
65
-	const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
66
-	const GETETAG_PROPERTYNAME = '{DAV:}getetag';
67
-	const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
68
-	const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
69
-	const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
70
-	const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
71
-	const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
72
-	const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
73
-	const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
74
-	const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
75
-	const METADATA_ETAG_PROPERTYNAME = '{http://nextcloud.org/ns}metadata_etag';
76
-	const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
77
-	const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
78
-	const SHARE_NOTE = '{http://nextcloud.org/ns}note';
79
-
80
-	/**
81
-	 * Reference to main server object
82
-	 *
83
-	 * @var \Sabre\DAV\Server
84
-	 */
85
-	private $server;
86
-
87
-	/**
88
-	 * @var Tree
89
-	 */
90
-	private $tree;
91
-
92
-	/**
93
-	 * Whether this is public webdav.
94
-	 * If true, some returned information will be stripped off.
95
-	 *
96
-	 * @var bool
97
-	 */
98
-	private $isPublic;
99
-
100
-	/**
101
-	 * @var bool
102
-	 */
103
-	private $downloadAttachment;
104
-
105
-	/**
106
-	 * @var IConfig
107
-	 */
108
-	private $config;
109
-
110
-	/**
111
-	 * @var IRequest
112
-	 */
113
-	private $request;
114
-
115
-	/**
116
-	 * @var IPreview
117
-	 */
118
-	private $previewManager;
119
-
120
-	/**
121
-	 * @param Tree $tree
122
-	 * @param IConfig $config
123
-	 * @param IRequest $request
124
-	 * @param IPreview $previewManager
125
-	 * @param bool $isPublic
126
-	 * @param bool $downloadAttachment
127
-	 */
128
-	public function __construct(Tree $tree,
129
-								IConfig $config,
130
-								IRequest $request,
131
-								IPreview $previewManager,
132
-								$isPublic = false,
133
-								$downloadAttachment = true) {
134
-		$this->tree = $tree;
135
-		$this->config = $config;
136
-		$this->request = $request;
137
-		$this->isPublic = $isPublic;
138
-		$this->downloadAttachment = $downloadAttachment;
139
-		$this->previewManager = $previewManager;
140
-	}
141
-
142
-	/**
143
-	 * This initializes the plugin.
144
-	 *
145
-	 * This function is called by \Sabre\DAV\Server, after
146
-	 * addPlugin is called.
147
-	 *
148
-	 * This method should set up the required event subscriptions.
149
-	 *
150
-	 * @param \Sabre\DAV\Server $server
151
-	 * @return void
152
-	 */
153
-	public function initialize(\Sabre\DAV\Server $server) {
154
-		$server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
155
-		$server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
156
-		$server->protectedProperties[] = self::FILEID_PROPERTYNAME;
157
-		$server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
158
-		$server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
159
-		$server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
160
-		$server->protectedProperties[] = self::OCM_SHARE_PERMISSIONS_PROPERTYNAME;
161
-		$server->protectedProperties[] = self::SIZE_PROPERTYNAME;
162
-		$server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
163
-		$server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
164
-		$server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
165
-		$server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
166
-		$server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
167
-		$server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
168
-		$server->protectedProperties[] = self::MOUNT_TYPE_PROPERTYNAME;
169
-		$server->protectedProperties[] = self::IS_ENCRYPTED_PROPERTYNAME;
170
-		$server->protectedProperties[] = self::SHARE_NOTE;
171
-
172
-		// normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
173
-		$allowedProperties = ['{DAV:}getetag'];
174
-		$server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
175
-
176
-		$this->server = $server;
177
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
178
-		$this->server->on('propPatch', [$this, 'handleUpdateProperties']);
179
-		$this->server->on('afterBind', [$this, 'sendFileIdHeader']);
180
-		$this->server->on('afterWriteContent', [$this, 'sendFileIdHeader']);
181
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
182
-		$this->server->on('afterMethod:GET', [$this, 'handleDownloadToken']);
183
-		$this->server->on('afterResponse', function ($request, ResponseInterface $response) {
184
-			$body = $response->getBody();
185
-			if (is_resource($body)) {
186
-				fclose($body);
187
-			}
188
-		});
189
-		$this->server->on('beforeMove', [$this, 'checkMove']);
190
-	}
191
-
192
-	/**
193
-	 * Plugin that checks if a move can actually be performed.
194
-	 *
195
-	 * @param string $source source path
196
-	 * @param string $destination destination path
197
-	 * @throws Forbidden
198
-	 * @throws NotFound
199
-	 */
200
-	function checkMove($source, $destination) {
201
-		$sourceNode = $this->tree->getNodeForPath($source);
202
-		if (!$sourceNode instanceof Node) {
203
-			return;
204
-		}
205
-		list($sourceDir,) = \Sabre\Uri\split($source);
206
-		list($destinationDir,) = \Sabre\Uri\split($destination);
207
-
208
-		if ($sourceDir !== $destinationDir) {
209
-			$sourceNodeFileInfo = $sourceNode->getFileInfo();
210
-			if ($sourceNodeFileInfo === null) {
211
-				throw new NotFound($source . ' does not exist');
212
-			}
213
-
214
-			if (!$sourceNodeFileInfo->isDeletable()) {
215
-				throw new Forbidden($source . " cannot be deleted");
216
-			}
217
-		}
218
-	}
219
-
220
-	/**
221
-	 * This sets a cookie to be able to recognize the start of the download
222
-	 * the content must not be longer than 32 characters and must only contain
223
-	 * alphanumeric characters
224
-	 *
225
-	 * @param RequestInterface $request
226
-	 * @param ResponseInterface $response
227
-	 */
228
-	function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
229
-		$queryParams = $request->getQueryParameters();
230
-
231
-		/**
232
-		 * this sets a cookie to be able to recognize the start of the download
233
-		 * the content must not be longer than 32 characters and must only contain
234
-		 * alphanumeric characters
235
-		 */
236
-		if (isset($queryParams['downloadStartSecret'])) {
237
-			$token = $queryParams['downloadStartSecret'];
238
-			if (!isset($token[32])
239
-				&& preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
240
-				// FIXME: use $response->setHeader() instead
241
-				setcookie('ocDownloadStarted', $token, time() + 20, '/');
242
-			}
243
-		}
244
-	}
245
-
246
-	/**
247
-	 * Add headers to file download
248
-	 *
249
-	 * @param RequestInterface $request
250
-	 * @param ResponseInterface $response
251
-	 */
252
-	function httpGet(RequestInterface $request, ResponseInterface $response) {
253
-		// Only handle valid files
254
-		$node = $this->tree->getNodeForPath($request->getPath());
255
-		if (!($node instanceof IFile)) return;
256
-
257
-		// adds a 'Content-Disposition: attachment' header in case no disposition
258
-		// header has been set before
259
-		if ($this->downloadAttachment &&
260
-			$response->getHeader('Content-Disposition') === null) {
261
-			$filename = $node->getName();
262
-			if ($this->request->isUserAgent(
263
-				[
264
-					Request::USER_AGENT_IE,
265
-					Request::USER_AGENT_ANDROID_MOBILE_CHROME,
266
-					Request::USER_AGENT_FREEBOX,
267
-				])) {
268
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
269
-			} else {
270
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
271
-													 . '; filename="' . rawurlencode($filename) . '"');
272
-			}
273
-		}
274
-
275
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
276
-			//Add OC-Checksum header
277
-			/** @var $node File */
278
-			$checksum = $node->getChecksum();
279
-			if ($checksum !== null && $checksum !== '') {
280
-				$response->addHeader('OC-Checksum', $checksum);
281
-			}
282
-		}
283
-	}
284
-
285
-	/**
286
-	 * Adds all ownCloud-specific properties
287
-	 *
288
-	 * @param PropFind $propFind
289
-	 * @param \Sabre\DAV\INode $node
290
-	 * @return void
291
-	 */
292
-	public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
293
-
294
-		$httpRequest = $this->server->httpRequest;
295
-
296
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
297
-			/**
298
-			 * This was disabled, because it made dir listing throw an exception,
299
-			 * so users were unable to navigate into folders where one subitem
300
-			 * is blocked by the files_accesscontrol app, see:
301
-			 * https://github.com/nextcloud/files_accesscontrol/issues/65
302
-			 * if (!$node->getFileInfo()->isReadable()) {
303
-			 *     // avoid detecting files through this means
304
-			 *     throw new NotFound();
305
-			 * }
306
-			 */
307
-
308
-			$propFind->handle(self::FILEID_PROPERTYNAME, function () use ($node) {
309
-				return $node->getFileId();
310
-			});
311
-
312
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function () use ($node) {
313
-				return $node->getInternalFileId();
314
-			});
315
-
316
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use ($node) {
317
-				$perms = $node->getDavPermissions();
318
-				if ($this->isPublic) {
319
-					// remove mount information
320
-					$perms = str_replace(['S', 'M'], '', $perms);
321
-				}
322
-				return $perms;
323
-			});
324
-
325
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
326
-				return $node->getSharePermissions(
327
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
328
-				);
329
-			});
330
-
331
-			$propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
332
-				$ncPermissions = $node->getSharePermissions(
333
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
334
-				);
335
-				$ocmPermissions = $this->ncPermissions2ocmPermissions($ncPermissions);
336
-				return json_encode($ocmPermissions);
337
-			});
338
-
339
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function () use ($node) {
340
-				return $node->getETag();
341
-			});
342
-
343
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function () use ($node) {
344
-				$owner = $node->getOwner();
345
-				if (!$owner) {
346
-					return null;
347
-				} else {
348
-					return $owner->getUID();
349
-				}
350
-			});
351
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function () use ($node) {
352
-				$owner = $node->getOwner();
353
-				if (!$owner) {
354
-					return null;
355
-				} else {
356
-					return $owner->getDisplayName();
357
-				}
358
-			});
359
-
360
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
361
-				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
362
-			});
363
-			$propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
364
-				return $node->getSize();
365
-			});
366
-			$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
367
-				return $node->getFileInfo()->getMountPoint()->getMountType();
368
-			});
369
-
370
-			$propFind->handle(self::SHARE_NOTE, function () use ($node, $httpRequest) {
371
-				return $node->getNoteFromShare(
372
-					$httpRequest->getRawServerValue('PHP_AUTH_USER')
373
-				);
374
-			});
375
-		}
376
-
377
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
378
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () use ($node) {
379
-				return $this->config->getSystemValue('data-fingerprint', '');
380
-			});
381
-		}
382
-
383
-		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
384
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use ($node) {
385
-				/** @var $node \OCA\DAV\Connector\Sabre\File */
386
-				try {
387
-					$directDownloadUrl = $node->getDirectDownload();
388
-					if (isset($directDownloadUrl['url'])) {
389
-						return $directDownloadUrl['url'];
390
-					}
391
-				} catch (StorageNotAvailableException $e) {
392
-					return false;
393
-				} catch (ForbiddenException $e) {
394
-					return false;
395
-				}
396
-				return false;
397
-			});
398
-
399
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function () use ($node) {
400
-				$checksum = $node->getChecksum();
401
-				if ($checksum === null || $checksum === '') {
402
-					return null;
403
-				}
404
-
405
-				return new ChecksumList($checksum);
406
-			});
407
-
408
-			$propFind->handle(self::CREATION_TIME_PROPERTYNAME, function () use ($node) {
409
-				return $node->getFileInfo()->getCreationTime();
410
-			});
411
-
412
-			$propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function () use ($node) {
413
-				return $node->getFileInfo()->getUploadTime();
414
-			});
415
-
416
-		}
417
-
418
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
419
-			$propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
420
-				return $node->getSize();
421
-			});
422
-
423
-			$propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function () use ($node) {
424
-				return $node->getFileInfo()->isEncrypted() ? '1' : '0';
425
-			});
426
-		}
427
-	}
428
-
429
-	/**
430
-	 * translate Nextcloud permissions to OCM Permissions
431
-	 *
432
-	 * @param $ncPermissions
433
-	 * @return array
434
-	 */
435
-	protected function ncPermissions2ocmPermissions($ncPermissions) {
436
-
437
-		$ocmPermissions = [];
438
-
439
-		if ($ncPermissions & Constants::PERMISSION_SHARE) {
440
-			$ocmPermissions[] = 'share';
441
-		}
442
-
443
-		if ($ncPermissions & Constants::PERMISSION_READ) {
444
-			$ocmPermissions[] = 'read';
445
-		}
446
-
447
-		if (($ncPermissions & Constants::PERMISSION_CREATE) ||
448
-			($ncPermissions & Constants::PERMISSION_UPDATE)) {
449
-			$ocmPermissions[] = 'write';
450
-		}
451
-
452
-		return $ocmPermissions;
453
-
454
-	}
455
-
456
-	/**
457
-	 * Update ownCloud-specific properties
458
-	 *
459
-	 * @param string $path
460
-	 * @param PropPatch $propPatch
461
-	 *
462
-	 * @return void
463
-	 */
464
-	public function handleUpdateProperties($path, PropPatch $propPatch) {
465
-		$node = $this->tree->getNodeForPath($path);
466
-		if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
467
-			return;
468
-		}
469
-
470
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function ($time) use ($node) {
471
-			if (empty($time)) {
472
-				return false;
473
-			}
474
-			$node->touch($time);
475
-			return true;
476
-		});
477
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function ($etag) use ($node) {
478
-			if (empty($etag)) {
479
-				return false;
480
-			}
481
-			if ($node->setEtag($etag) !== -1) {
482
-				return true;
483
-			}
484
-			return false;
485
-		});
486
-		$propPatch->handle(self::CREATION_TIME_PROPERTYNAME, function ($time) use ($node) {
487
-			if (empty($time)) {
488
-				return false;
489
-			}
490
-			$node->setCreationTime((int) $time);
491
-			return true;
492
-		});
493
-	}
494
-
495
-	/**
496
-	 * @param string $filePath
497
-	 * @param \Sabre\DAV\INode $node
498
-	 * @throws \Sabre\DAV\Exception\BadRequest
499
-	 */
500
-	public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
501
-		// chunked upload handling
502
-		if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
503
-			list($path, $name) = \Sabre\Uri\split($filePath);
504
-			$info = \OC_FileChunking::decodeName($name);
505
-			if (!empty($info)) {
506
-				$filePath = $path . '/' . $info['name'];
507
-			}
508
-		}
509
-
510
-		// we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
511
-		if (!$this->server->tree->nodeExists($filePath)) {
512
-			return;
513
-		}
514
-		$node = $this->server->tree->getNodeForPath($filePath);
515
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
516
-			$fileId = $node->getFileId();
517
-			if (!is_null($fileId)) {
518
-				$this->server->httpResponse->setHeader('OC-FileId', $fileId);
519
-			}
520
-		}
521
-	}
56
+    // namespace
57
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
58
+    const NS_NEXTCLOUD = 'http://nextcloud.org/ns';
59
+    const FILEID_PROPERTYNAME = '{http://owncloud.org/ns}id';
60
+    const INTERNAL_FILEID_PROPERTYNAME = '{http://owncloud.org/ns}fileid';
61
+    const PERMISSIONS_PROPERTYNAME = '{http://owncloud.org/ns}permissions';
62
+    const SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-collaboration-services.org/ns}share-permissions';
63
+    const OCM_SHARE_PERMISSIONS_PROPERTYNAME = '{http://open-cloud-mesh.org/ns}share-permissions';
64
+    const DOWNLOADURL_PROPERTYNAME = '{http://owncloud.org/ns}downloadURL';
65
+    const SIZE_PROPERTYNAME = '{http://owncloud.org/ns}size';
66
+    const GETETAG_PROPERTYNAME = '{DAV:}getetag';
67
+    const LASTMODIFIED_PROPERTYNAME = '{DAV:}lastmodified';
68
+    const OWNER_ID_PROPERTYNAME = '{http://owncloud.org/ns}owner-id';
69
+    const OWNER_DISPLAY_NAME_PROPERTYNAME = '{http://owncloud.org/ns}owner-display-name';
70
+    const CHECKSUMS_PROPERTYNAME = '{http://owncloud.org/ns}checksums';
71
+    const DATA_FINGERPRINT_PROPERTYNAME = '{http://owncloud.org/ns}data-fingerprint';
72
+    const HAS_PREVIEW_PROPERTYNAME = '{http://nextcloud.org/ns}has-preview';
73
+    const MOUNT_TYPE_PROPERTYNAME = '{http://nextcloud.org/ns}mount-type';
74
+    const IS_ENCRYPTED_PROPERTYNAME = '{http://nextcloud.org/ns}is-encrypted';
75
+    const METADATA_ETAG_PROPERTYNAME = '{http://nextcloud.org/ns}metadata_etag';
76
+    const UPLOAD_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}upload_time';
77
+    const CREATION_TIME_PROPERTYNAME = '{http://nextcloud.org/ns}creation_time';
78
+    const SHARE_NOTE = '{http://nextcloud.org/ns}note';
79
+
80
+    /**
81
+     * Reference to main server object
82
+     *
83
+     * @var \Sabre\DAV\Server
84
+     */
85
+    private $server;
86
+
87
+    /**
88
+     * @var Tree
89
+     */
90
+    private $tree;
91
+
92
+    /**
93
+     * Whether this is public webdav.
94
+     * If true, some returned information will be stripped off.
95
+     *
96
+     * @var bool
97
+     */
98
+    private $isPublic;
99
+
100
+    /**
101
+     * @var bool
102
+     */
103
+    private $downloadAttachment;
104
+
105
+    /**
106
+     * @var IConfig
107
+     */
108
+    private $config;
109
+
110
+    /**
111
+     * @var IRequest
112
+     */
113
+    private $request;
114
+
115
+    /**
116
+     * @var IPreview
117
+     */
118
+    private $previewManager;
119
+
120
+    /**
121
+     * @param Tree $tree
122
+     * @param IConfig $config
123
+     * @param IRequest $request
124
+     * @param IPreview $previewManager
125
+     * @param bool $isPublic
126
+     * @param bool $downloadAttachment
127
+     */
128
+    public function __construct(Tree $tree,
129
+                                IConfig $config,
130
+                                IRequest $request,
131
+                                IPreview $previewManager,
132
+                                $isPublic = false,
133
+                                $downloadAttachment = true) {
134
+        $this->tree = $tree;
135
+        $this->config = $config;
136
+        $this->request = $request;
137
+        $this->isPublic = $isPublic;
138
+        $this->downloadAttachment = $downloadAttachment;
139
+        $this->previewManager = $previewManager;
140
+    }
141
+
142
+    /**
143
+     * This initializes the plugin.
144
+     *
145
+     * This function is called by \Sabre\DAV\Server, after
146
+     * addPlugin is called.
147
+     *
148
+     * This method should set up the required event subscriptions.
149
+     *
150
+     * @param \Sabre\DAV\Server $server
151
+     * @return void
152
+     */
153
+    public function initialize(\Sabre\DAV\Server $server) {
154
+        $server->xml->namespaceMap[self::NS_OWNCLOUD] = 'oc';
155
+        $server->xml->namespaceMap[self::NS_NEXTCLOUD] = 'nc';
156
+        $server->protectedProperties[] = self::FILEID_PROPERTYNAME;
157
+        $server->protectedProperties[] = self::INTERNAL_FILEID_PROPERTYNAME;
158
+        $server->protectedProperties[] = self::PERMISSIONS_PROPERTYNAME;
159
+        $server->protectedProperties[] = self::SHARE_PERMISSIONS_PROPERTYNAME;
160
+        $server->protectedProperties[] = self::OCM_SHARE_PERMISSIONS_PROPERTYNAME;
161
+        $server->protectedProperties[] = self::SIZE_PROPERTYNAME;
162
+        $server->protectedProperties[] = self::DOWNLOADURL_PROPERTYNAME;
163
+        $server->protectedProperties[] = self::OWNER_ID_PROPERTYNAME;
164
+        $server->protectedProperties[] = self::OWNER_DISPLAY_NAME_PROPERTYNAME;
165
+        $server->protectedProperties[] = self::CHECKSUMS_PROPERTYNAME;
166
+        $server->protectedProperties[] = self::DATA_FINGERPRINT_PROPERTYNAME;
167
+        $server->protectedProperties[] = self::HAS_PREVIEW_PROPERTYNAME;
168
+        $server->protectedProperties[] = self::MOUNT_TYPE_PROPERTYNAME;
169
+        $server->protectedProperties[] = self::IS_ENCRYPTED_PROPERTYNAME;
170
+        $server->protectedProperties[] = self::SHARE_NOTE;
171
+
172
+        // normally these cannot be changed (RFC4918), but we want them modifiable through PROPPATCH
173
+        $allowedProperties = ['{DAV:}getetag'];
174
+        $server->protectedProperties = array_diff($server->protectedProperties, $allowedProperties);
175
+
176
+        $this->server = $server;
177
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
178
+        $this->server->on('propPatch', [$this, 'handleUpdateProperties']);
179
+        $this->server->on('afterBind', [$this, 'sendFileIdHeader']);
180
+        $this->server->on('afterWriteContent', [$this, 'sendFileIdHeader']);
181
+        $this->server->on('afterMethod:GET', [$this,'httpGet']);
182
+        $this->server->on('afterMethod:GET', [$this, 'handleDownloadToken']);
183
+        $this->server->on('afterResponse', function ($request, ResponseInterface $response) {
184
+            $body = $response->getBody();
185
+            if (is_resource($body)) {
186
+                fclose($body);
187
+            }
188
+        });
189
+        $this->server->on('beforeMove', [$this, 'checkMove']);
190
+    }
191
+
192
+    /**
193
+     * Plugin that checks if a move can actually be performed.
194
+     *
195
+     * @param string $source source path
196
+     * @param string $destination destination path
197
+     * @throws Forbidden
198
+     * @throws NotFound
199
+     */
200
+    function checkMove($source, $destination) {
201
+        $sourceNode = $this->tree->getNodeForPath($source);
202
+        if (!$sourceNode instanceof Node) {
203
+            return;
204
+        }
205
+        list($sourceDir,) = \Sabre\Uri\split($source);
206
+        list($destinationDir,) = \Sabre\Uri\split($destination);
207
+
208
+        if ($sourceDir !== $destinationDir) {
209
+            $sourceNodeFileInfo = $sourceNode->getFileInfo();
210
+            if ($sourceNodeFileInfo === null) {
211
+                throw new NotFound($source . ' does not exist');
212
+            }
213
+
214
+            if (!$sourceNodeFileInfo->isDeletable()) {
215
+                throw new Forbidden($source . " cannot be deleted");
216
+            }
217
+        }
218
+    }
219
+
220
+    /**
221
+     * This sets a cookie to be able to recognize the start of the download
222
+     * the content must not be longer than 32 characters and must only contain
223
+     * alphanumeric characters
224
+     *
225
+     * @param RequestInterface $request
226
+     * @param ResponseInterface $response
227
+     */
228
+    function handleDownloadToken(RequestInterface $request, ResponseInterface $response) {
229
+        $queryParams = $request->getQueryParameters();
230
+
231
+        /**
232
+         * this sets a cookie to be able to recognize the start of the download
233
+         * the content must not be longer than 32 characters and must only contain
234
+         * alphanumeric characters
235
+         */
236
+        if (isset($queryParams['downloadStartSecret'])) {
237
+            $token = $queryParams['downloadStartSecret'];
238
+            if (!isset($token[32])
239
+                && preg_match('!^[a-zA-Z0-9]+$!', $token) === 1) {
240
+                // FIXME: use $response->setHeader() instead
241
+                setcookie('ocDownloadStarted', $token, time() + 20, '/');
242
+            }
243
+        }
244
+    }
245
+
246
+    /**
247
+     * Add headers to file download
248
+     *
249
+     * @param RequestInterface $request
250
+     * @param ResponseInterface $response
251
+     */
252
+    function httpGet(RequestInterface $request, ResponseInterface $response) {
253
+        // Only handle valid files
254
+        $node = $this->tree->getNodeForPath($request->getPath());
255
+        if (!($node instanceof IFile)) return;
256
+
257
+        // adds a 'Content-Disposition: attachment' header in case no disposition
258
+        // header has been set before
259
+        if ($this->downloadAttachment &&
260
+            $response->getHeader('Content-Disposition') === null) {
261
+            $filename = $node->getName();
262
+            if ($this->request->isUserAgent(
263
+                [
264
+                    Request::USER_AGENT_IE,
265
+                    Request::USER_AGENT_ANDROID_MOBILE_CHROME,
266
+                    Request::USER_AGENT_FREEBOX,
267
+                ])) {
268
+                $response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
269
+            } else {
270
+                $response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
271
+                                                        . '; filename="' . rawurlencode($filename) . '"');
272
+            }
273
+        }
274
+
275
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
276
+            //Add OC-Checksum header
277
+            /** @var $node File */
278
+            $checksum = $node->getChecksum();
279
+            if ($checksum !== null && $checksum !== '') {
280
+                $response->addHeader('OC-Checksum', $checksum);
281
+            }
282
+        }
283
+    }
284
+
285
+    /**
286
+     * Adds all ownCloud-specific properties
287
+     *
288
+     * @param PropFind $propFind
289
+     * @param \Sabre\DAV\INode $node
290
+     * @return void
291
+     */
292
+    public function handleGetProperties(PropFind $propFind, \Sabre\DAV\INode $node) {
293
+
294
+        $httpRequest = $this->server->httpRequest;
295
+
296
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
297
+            /**
298
+             * This was disabled, because it made dir listing throw an exception,
299
+             * so users were unable to navigate into folders where one subitem
300
+             * is blocked by the files_accesscontrol app, see:
301
+             * https://github.com/nextcloud/files_accesscontrol/issues/65
302
+             * if (!$node->getFileInfo()->isReadable()) {
303
+             *     // avoid detecting files through this means
304
+             *     throw new NotFound();
305
+             * }
306
+             */
307
+
308
+            $propFind->handle(self::FILEID_PROPERTYNAME, function () use ($node) {
309
+                return $node->getFileId();
310
+            });
311
+
312
+            $propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function () use ($node) {
313
+                return $node->getInternalFileId();
314
+            });
315
+
316
+            $propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use ($node) {
317
+                $perms = $node->getDavPermissions();
318
+                if ($this->isPublic) {
319
+                    // remove mount information
320
+                    $perms = str_replace(['S', 'M'], '', $perms);
321
+                }
322
+                return $perms;
323
+            });
324
+
325
+            $propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
326
+                return $node->getSharePermissions(
327
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
328
+                );
329
+            });
330
+
331
+            $propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
332
+                $ncPermissions = $node->getSharePermissions(
333
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
334
+                );
335
+                $ocmPermissions = $this->ncPermissions2ocmPermissions($ncPermissions);
336
+                return json_encode($ocmPermissions);
337
+            });
338
+
339
+            $propFind->handle(self::GETETAG_PROPERTYNAME, function () use ($node) {
340
+                return $node->getETag();
341
+            });
342
+
343
+            $propFind->handle(self::OWNER_ID_PROPERTYNAME, function () use ($node) {
344
+                $owner = $node->getOwner();
345
+                if (!$owner) {
346
+                    return null;
347
+                } else {
348
+                    return $owner->getUID();
349
+                }
350
+            });
351
+            $propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function () use ($node) {
352
+                $owner = $node->getOwner();
353
+                if (!$owner) {
354
+                    return null;
355
+                } else {
356
+                    return $owner->getDisplayName();
357
+                }
358
+            });
359
+
360
+            $propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
361
+                return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
362
+            });
363
+            $propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
364
+                return $node->getSize();
365
+            });
366
+            $propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
367
+                return $node->getFileInfo()->getMountPoint()->getMountType();
368
+            });
369
+
370
+            $propFind->handle(self::SHARE_NOTE, function () use ($node, $httpRequest) {
371
+                return $node->getNoteFromShare(
372
+                    $httpRequest->getRawServerValue('PHP_AUTH_USER')
373
+                );
374
+            });
375
+        }
376
+
377
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
378
+            $propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () use ($node) {
379
+                return $this->config->getSystemValue('data-fingerprint', '');
380
+            });
381
+        }
382
+
383
+        if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
384
+            $propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use ($node) {
385
+                /** @var $node \OCA\DAV\Connector\Sabre\File */
386
+                try {
387
+                    $directDownloadUrl = $node->getDirectDownload();
388
+                    if (isset($directDownloadUrl['url'])) {
389
+                        return $directDownloadUrl['url'];
390
+                    }
391
+                } catch (StorageNotAvailableException $e) {
392
+                    return false;
393
+                } catch (ForbiddenException $e) {
394
+                    return false;
395
+                }
396
+                return false;
397
+            });
398
+
399
+            $propFind->handle(self::CHECKSUMS_PROPERTYNAME, function () use ($node) {
400
+                $checksum = $node->getChecksum();
401
+                if ($checksum === null || $checksum === '') {
402
+                    return null;
403
+                }
404
+
405
+                return new ChecksumList($checksum);
406
+            });
407
+
408
+            $propFind->handle(self::CREATION_TIME_PROPERTYNAME, function () use ($node) {
409
+                return $node->getFileInfo()->getCreationTime();
410
+            });
411
+
412
+            $propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function () use ($node) {
413
+                return $node->getFileInfo()->getUploadTime();
414
+            });
415
+
416
+        }
417
+
418
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
419
+            $propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
420
+                return $node->getSize();
421
+            });
422
+
423
+            $propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function () use ($node) {
424
+                return $node->getFileInfo()->isEncrypted() ? '1' : '0';
425
+            });
426
+        }
427
+    }
428
+
429
+    /**
430
+     * translate Nextcloud permissions to OCM Permissions
431
+     *
432
+     * @param $ncPermissions
433
+     * @return array
434
+     */
435
+    protected function ncPermissions2ocmPermissions($ncPermissions) {
436
+
437
+        $ocmPermissions = [];
438
+
439
+        if ($ncPermissions & Constants::PERMISSION_SHARE) {
440
+            $ocmPermissions[] = 'share';
441
+        }
442
+
443
+        if ($ncPermissions & Constants::PERMISSION_READ) {
444
+            $ocmPermissions[] = 'read';
445
+        }
446
+
447
+        if (($ncPermissions & Constants::PERMISSION_CREATE) ||
448
+            ($ncPermissions & Constants::PERMISSION_UPDATE)) {
449
+            $ocmPermissions[] = 'write';
450
+        }
451
+
452
+        return $ocmPermissions;
453
+
454
+    }
455
+
456
+    /**
457
+     * Update ownCloud-specific properties
458
+     *
459
+     * @param string $path
460
+     * @param PropPatch $propPatch
461
+     *
462
+     * @return void
463
+     */
464
+    public function handleUpdateProperties($path, PropPatch $propPatch) {
465
+        $node = $this->tree->getNodeForPath($path);
466
+        if (!($node instanceof \OCA\DAV\Connector\Sabre\Node)) {
467
+            return;
468
+        }
469
+
470
+        $propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function ($time) use ($node) {
471
+            if (empty($time)) {
472
+                return false;
473
+            }
474
+            $node->touch($time);
475
+            return true;
476
+        });
477
+        $propPatch->handle(self::GETETAG_PROPERTYNAME, function ($etag) use ($node) {
478
+            if (empty($etag)) {
479
+                return false;
480
+            }
481
+            if ($node->setEtag($etag) !== -1) {
482
+                return true;
483
+            }
484
+            return false;
485
+        });
486
+        $propPatch->handle(self::CREATION_TIME_PROPERTYNAME, function ($time) use ($node) {
487
+            if (empty($time)) {
488
+                return false;
489
+            }
490
+            $node->setCreationTime((int) $time);
491
+            return true;
492
+        });
493
+    }
494
+
495
+    /**
496
+     * @param string $filePath
497
+     * @param \Sabre\DAV\INode $node
498
+     * @throws \Sabre\DAV\Exception\BadRequest
499
+     */
500
+    public function sendFileIdHeader($filePath, \Sabre\DAV\INode $node = null) {
501
+        // chunked upload handling
502
+        if (isset($_SERVER['HTTP_OC_CHUNKED'])) {
503
+            list($path, $name) = \Sabre\Uri\split($filePath);
504
+            $info = \OC_FileChunking::decodeName($name);
505
+            if (!empty($info)) {
506
+                $filePath = $path . '/' . $info['name'];
507
+            }
508
+        }
509
+
510
+        // we get the node for the given $filePath here because in case of afterCreateFile $node is the parent folder
511
+        if (!$this->server->tree->nodeExists($filePath)) {
512
+            return;
513
+        }
514
+        $node = $this->server->tree->getNodeForPath($filePath);
515
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
516
+            $fileId = $node->getFileId();
517
+            if (!is_null($fileId)) {
518
+                $this->server->httpResponse->setHeader('OC-FileId', $fileId);
519
+            }
520
+        }
521
+    }
522 522
 }
Please login to merge, or discard this patch.
Spacing   +30 added lines, -30 removed lines patch added patch discarded remove patch
@@ -178,9 +178,9 @@  discard block
 block discarded – undo
178 178
 		$this->server->on('propPatch', [$this, 'handleUpdateProperties']);
179 179
 		$this->server->on('afterBind', [$this, 'sendFileIdHeader']);
180 180
 		$this->server->on('afterWriteContent', [$this, 'sendFileIdHeader']);
181
-		$this->server->on('afterMethod:GET', [$this,'httpGet']);
181
+		$this->server->on('afterMethod:GET', [$this, 'httpGet']);
182 182
 		$this->server->on('afterMethod:GET', [$this, 'handleDownloadToken']);
183
-		$this->server->on('afterResponse', function ($request, ResponseInterface $response) {
183
+		$this->server->on('afterResponse', function($request, ResponseInterface $response) {
184 184
 			$body = $response->getBody();
185 185
 			if (is_resource($body)) {
186 186
 				fclose($body);
@@ -208,11 +208,11 @@  discard block
 block discarded – undo
208 208
 		if ($sourceDir !== $destinationDir) {
209 209
 			$sourceNodeFileInfo = $sourceNode->getFileInfo();
210 210
 			if ($sourceNodeFileInfo === null) {
211
-				throw new NotFound($source . ' does not exist');
211
+				throw new NotFound($source.' does not exist');
212 212
 			}
213 213
 
214 214
 			if (!$sourceNodeFileInfo->isDeletable()) {
215
-				throw new Forbidden($source . " cannot be deleted");
215
+				throw new Forbidden($source." cannot be deleted");
216 216
 			}
217 217
 		}
218 218
 	}
@@ -265,10 +265,10 @@  discard block
 block discarded – undo
265 265
 					Request::USER_AGENT_ANDROID_MOBILE_CHROME,
266 266
 					Request::USER_AGENT_FREEBOX,
267 267
 				])) {
268
-				$response->addHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
268
+				$response->addHeader('Content-Disposition', 'attachment; filename="'.rawurlencode($filename).'"');
269 269
 			} else {
270
-				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\'' . rawurlencode($filename)
271
-													 . '; filename="' . rawurlencode($filename) . '"');
270
+				$response->addHeader('Content-Disposition', 'attachment; filename*=UTF-8\'\''.rawurlencode($filename)
271
+													 . '; filename="'.rawurlencode($filename).'"');
272 272
 			}
273 273
 		}
274 274
 
@@ -305,15 +305,15 @@  discard block
 block discarded – undo
305 305
 			 * }
306 306
 			 */
307 307
 
308
-			$propFind->handle(self::FILEID_PROPERTYNAME, function () use ($node) {
308
+			$propFind->handle(self::FILEID_PROPERTYNAME, function() use ($node) {
309 309
 				return $node->getFileId();
310 310
 			});
311 311
 
312
-			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function () use ($node) {
312
+			$propFind->handle(self::INTERNAL_FILEID_PROPERTYNAME, function() use ($node) {
313 313
 				return $node->getInternalFileId();
314 314
 			});
315 315
 
316
-			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function () use ($node) {
316
+			$propFind->handle(self::PERMISSIONS_PROPERTYNAME, function() use ($node) {
317 317
 				$perms = $node->getDavPermissions();
318 318
 				if ($this->isPublic) {
319 319
 					// remove mount information
@@ -322,13 +322,13 @@  discard block
 block discarded – undo
322 322
 				return $perms;
323 323
 			});
324 324
 
325
-			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
325
+			$propFind->handle(self::SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
326 326
 				return $node->getSharePermissions(
327 327
 					$httpRequest->getRawServerValue('PHP_AUTH_USER')
328 328
 				);
329 329
 			});
330 330
 
331
-			$propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function () use ($node, $httpRequest) {
331
+			$propFind->handle(self::OCM_SHARE_PERMISSIONS_PROPERTYNAME, function() use ($node, $httpRequest) {
332 332
 				$ncPermissions = $node->getSharePermissions(
333 333
 					$httpRequest->getRawServerValue('PHP_AUTH_USER')
334 334
 				);
@@ -336,11 +336,11 @@  discard block
 block discarded – undo
336 336
 				return json_encode($ocmPermissions);
337 337
 			});
338 338
 
339
-			$propFind->handle(self::GETETAG_PROPERTYNAME, function () use ($node) {
339
+			$propFind->handle(self::GETETAG_PROPERTYNAME, function() use ($node) {
340 340
 				return $node->getETag();
341 341
 			});
342 342
 
343
-			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function () use ($node) {
343
+			$propFind->handle(self::OWNER_ID_PROPERTYNAME, function() use ($node) {
344 344
 				$owner = $node->getOwner();
345 345
 				if (!$owner) {
346 346
 					return null;
@@ -348,7 +348,7 @@  discard block
 block discarded – undo
348 348
 					return $owner->getUID();
349 349
 				}
350 350
 			});
351
-			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function () use ($node) {
351
+			$propFind->handle(self::OWNER_DISPLAY_NAME_PROPERTYNAME, function() use ($node) {
352 352
 				$owner = $node->getOwner();
353 353
 				if (!$owner) {
354 354
 					return null;
@@ -357,17 +357,17 @@  discard block
 block discarded – undo
357 357
 				}
358 358
 			});
359 359
 
360
-			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function () use ($node) {
360
+			$propFind->handle(self::HAS_PREVIEW_PROPERTYNAME, function() use ($node) {
361 361
 				return json_encode($this->previewManager->isAvailable($node->getFileInfo()));
362 362
 			});
363
-			$propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
363
+			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
364 364
 				return $node->getSize();
365 365
 			});
366
-			$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function () use ($node) {
366
+			$propFind->handle(self::MOUNT_TYPE_PROPERTYNAME, function() use ($node) {
367 367
 				return $node->getFileInfo()->getMountPoint()->getMountType();
368 368
 			});
369 369
 
370
-			$propFind->handle(self::SHARE_NOTE, function () use ($node, $httpRequest) {
370
+			$propFind->handle(self::SHARE_NOTE, function() use ($node, $httpRequest) {
371 371
 				return $node->getNoteFromShare(
372 372
 					$httpRequest->getRawServerValue('PHP_AUTH_USER')
373 373
 				);
@@ -375,13 +375,13 @@  discard block
 block discarded – undo
375 375
 		}
376 376
 
377 377
 		if ($node instanceof \OCA\DAV\Connector\Sabre\Node) {
378
-			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function () use ($node) {
378
+			$propFind->handle(self::DATA_FINGERPRINT_PROPERTYNAME, function() use ($node) {
379 379
 				return $this->config->getSystemValue('data-fingerprint', '');
380 380
 			});
381 381
 		}
382 382
 
383 383
 		if ($node instanceof \OCA\DAV\Connector\Sabre\File) {
384
-			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function () use ($node) {
384
+			$propFind->handle(self::DOWNLOADURL_PROPERTYNAME, function() use ($node) {
385 385
 				/** @var $node \OCA\DAV\Connector\Sabre\File */
386 386
 				try {
387 387
 					$directDownloadUrl = $node->getDirectDownload();
@@ -396,7 +396,7 @@  discard block
 block discarded – undo
396 396
 				return false;
397 397
 			});
398 398
 
399
-			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function () use ($node) {
399
+			$propFind->handle(self::CHECKSUMS_PROPERTYNAME, function() use ($node) {
400 400
 				$checksum = $node->getChecksum();
401 401
 				if ($checksum === null || $checksum === '') {
402 402
 					return null;
@@ -405,22 +405,22 @@  discard block
 block discarded – undo
405 405
 				return new ChecksumList($checksum);
406 406
 			});
407 407
 
408
-			$propFind->handle(self::CREATION_TIME_PROPERTYNAME, function () use ($node) {
408
+			$propFind->handle(self::CREATION_TIME_PROPERTYNAME, function() use ($node) {
409 409
 				return $node->getFileInfo()->getCreationTime();
410 410
 			});
411 411
 
412
-			$propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function () use ($node) {
412
+			$propFind->handle(self::UPLOAD_TIME_PROPERTYNAME, function() use ($node) {
413 413
 				return $node->getFileInfo()->getUploadTime();
414 414
 			});
415 415
 
416 416
 		}
417 417
 
418 418
 		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory) {
419
-			$propFind->handle(self::SIZE_PROPERTYNAME, function () use ($node) {
419
+			$propFind->handle(self::SIZE_PROPERTYNAME, function() use ($node) {
420 420
 				return $node->getSize();
421 421
 			});
422 422
 
423
-			$propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function () use ($node) {
423
+			$propFind->handle(self::IS_ENCRYPTED_PROPERTYNAME, function() use ($node) {
424 424
 				return $node->getFileInfo()->isEncrypted() ? '1' : '0';
425 425
 			});
426 426
 		}
@@ -467,14 +467,14 @@  discard block
 block discarded – undo
467 467
 			return;
468 468
 		}
469 469
 
470
-		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function ($time) use ($node) {
470
+		$propPatch->handle(self::LASTMODIFIED_PROPERTYNAME, function($time) use ($node) {
471 471
 			if (empty($time)) {
472 472
 				return false;
473 473
 			}
474 474
 			$node->touch($time);
475 475
 			return true;
476 476
 		});
477
-		$propPatch->handle(self::GETETAG_PROPERTYNAME, function ($etag) use ($node) {
477
+		$propPatch->handle(self::GETETAG_PROPERTYNAME, function($etag) use ($node) {
478 478
 			if (empty($etag)) {
479 479
 				return false;
480 480
 			}
@@ -483,7 +483,7 @@  discard block
 block discarded – undo
483 483
 			}
484 484
 			return false;
485 485
 		});
486
-		$propPatch->handle(self::CREATION_TIME_PROPERTYNAME, function ($time) use ($node) {
486
+		$propPatch->handle(self::CREATION_TIME_PROPERTYNAME, function($time) use ($node) {
487 487
 			if (empty($time)) {
488 488
 				return false;
489 489
 			}
@@ -503,7 +503,7 @@  discard block
 block discarded – undo
503 503
 			list($path, $name) = \Sabre\Uri\split($filePath);
504 504
 			$info = \OC_FileChunking::decodeName($name);
505 505
 			if (!empty($info)) {
506
-				$filePath = $path . '/' . $info['name'];
506
+				$filePath = $path.'/'.$info['name'];
507 507
 			}
508 508
 		}
509 509
 
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/Principal.php 2 patches
Indentation   +478 added lines, -478 removed lines patch added patch discarded remove patch
@@ -50,482 +50,482 @@
 block discarded – undo
50 50
 
51 51
 class Principal implements BackendInterface {
52 52
 
53
-	/** @var IUserManager */
54
-	private $userManager;
55
-
56
-	/** @var IGroupManager */
57
-	private $groupManager;
58
-
59
-	/** @var IShareManager */
60
-	private $shareManager;
61
-
62
-	/** @var IUserSession */
63
-	private $userSession;
64
-
65
-	/** @var IAppManager */
66
-	private $appManager;
67
-
68
-	/** @var string */
69
-	private $principalPrefix;
70
-
71
-	/** @var bool */
72
-	private $hasGroups;
73
-
74
-	/** @var bool */
75
-	private $hasCircles;
76
-
77
-	/** @var ProxyMapper */
78
-	private $proxyMapper;
79
-
80
-	/** @var IConfig */
81
-	private $config;
82
-
83
-	/**
84
-	 * Principal constructor.
85
-	 *
86
-	 * @param IUserManager $userManager
87
-	 * @param IGroupManager $groupManager
88
-	 * @param IShareManager $shareManager
89
-	 * @param IUserSession $userSession
90
-	 * @param IAppManager $appManager
91
-	 * @param ProxyMapper $proxyMapper
92
-	 * @param IConfig $config
93
-	 * @param string $principalPrefix
94
-	 */
95
-	public function __construct(IUserManager $userManager,
96
-								IGroupManager $groupManager,
97
-								IShareManager $shareManager,
98
-								IUserSession $userSession,
99
-								IAppManager $appManager,
100
-								ProxyMapper $proxyMapper,
101
-								IConfig $config,
102
-								string $principalPrefix = 'principals/users/') {
103
-		$this->userManager = $userManager;
104
-		$this->groupManager = $groupManager;
105
-		$this->shareManager = $shareManager;
106
-		$this->userSession = $userSession;
107
-		$this->appManager = $appManager;
108
-		$this->principalPrefix = trim($principalPrefix, '/');
109
-		$this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
110
-		$this->proxyMapper = $proxyMapper;
111
-		$this->config = $config;
112
-	}
113
-
114
-	use PrincipalProxyTrait {
115
-		getGroupMembership as protected traitGetGroupMembership;
116
-	}
117
-
118
-	/**
119
-	 * Returns a list of principals based on a prefix.
120
-	 *
121
-	 * This prefix will often contain something like 'principals'. You are only
122
-	 * expected to return principals that are in this base path.
123
-	 *
124
-	 * You are expected to return at least a 'uri' for every user, you can
125
-	 * return any additional properties if you wish so. Common properties are:
126
-	 *   {DAV:}displayname
127
-	 *
128
-	 * @param string $prefixPath
129
-	 * @return string[]
130
-	 */
131
-	public function getPrincipalsByPrefix($prefixPath) {
132
-		$principals = [];
133
-
134
-		if ($prefixPath === $this->principalPrefix) {
135
-			foreach($this->userManager->search('') as $user) {
136
-				$principals[] = $this->userToPrincipal($user);
137
-			}
138
-		}
139
-
140
-		return $principals;
141
-	}
142
-
143
-	/**
144
-	 * Returns a specific principal, specified by it's path.
145
-	 * The returned structure should be the exact same as from
146
-	 * getPrincipalsByPrefix.
147
-	 *
148
-	 * @param string $path
149
-	 * @return array
150
-	 */
151
-	public function getPrincipalByPath($path) {
152
-		list($prefix, $name) = \Sabre\Uri\split($path);
153
-
154
-		if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
155
-			list($prefix2, $name2) = \Sabre\Uri\split($prefix);
156
-
157
-			if ($prefix2 === $this->principalPrefix) {
158
-				$user = $this->userManager->get($name2);
159
-
160
-				if ($user !== null) {
161
-					return [
162
-						'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
163
-					];
164
-				}
165
-				return null;
166
-			}
167
-		}
168
-
169
-		if ($prefix === $this->principalPrefix) {
170
-			$user = $this->userManager->get($name);
171
-
172
-			if ($user !== null) {
173
-				return $this->userToPrincipal($user);
174
-			}
175
-		} else if ($prefix === 'principals/circles') {
176
-			try {
177
-				return $this->circleToPrincipal($name);
178
-			} catch (QueryException $e) {
179
-				return null;
180
-			}
181
-		}
182
-		return null;
183
-	}
184
-
185
-	/**
186
-	 * Returns the list of groups a principal is a member of
187
-	 *
188
-	 * @param string $principal
189
-	 * @param bool $needGroups
190
-	 * @return array
191
-	 * @throws Exception
192
-	 */
193
-	public function getGroupMembership($principal, $needGroups = false) {
194
-		list($prefix, $name) = \Sabre\Uri\split($principal);
195
-
196
-		if ($prefix !== $this->principalPrefix) {
197
-			return [];
198
-		}
199
-
200
-		$user = $this->userManager->get($name);
201
-		if (!$user) {
202
-			throw new Exception('Principal not found');
203
-		}
204
-
205
-		$groups = [];
206
-
207
-		if ($this->hasGroups || $needGroups) {
208
-			$userGroups = $this->groupManager->getUserGroups($user);
209
-			foreach($userGroups as $userGroup) {
210
-				$groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
211
-			}
212
-		}
213
-
214
-		$groups = array_unique(array_merge(
215
-			$groups,
216
-			$this->traitGetGroupMembership($principal, $needGroups)
217
-		));
218
-
219
-		return $groups;
220
-	}
221
-
222
-	/**
223
-	 * @param string $path
224
-	 * @param PropPatch $propPatch
225
-	 * @return int
226
-	 */
227
-	function updatePrincipal($path, PropPatch $propPatch) {
228
-		return 0;
229
-	}
230
-
231
-	/**
232
-	 * Search user principals
233
-	 *
234
-	 * @param array $searchProperties
235
-	 * @param string $test
236
-	 * @return array
237
-	 */
238
-	protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
239
-		$results = [];
240
-
241
-		// If sharing is disabled, return the empty array
242
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
243
-		if (!$shareAPIEnabled) {
244
-			return [];
245
-		}
246
-
247
-		$allowEnumeration = $this->shareManager->allowEnumeration();
248
-		$limitEnumeration = $this->shareManager->limitEnumerationToGroups();
249
-
250
-		// If sharing is restricted to group members only,
251
-		// return only members that have groups in common
252
-		$restrictGroups = false;
253
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
254
-			$user = $this->userSession->getUser();
255
-			if (!$user) {
256
-				return [];
257
-			}
258
-
259
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
260
-		}
261
-
262
-		$currentUserGroups = [];
263
-		if ($limitEnumeration) {
264
-			$currentUser = $this->userSession->getUser();
265
-			if ($currentUser) {
266
-				$currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
267
-			}
268
-		}
269
-
270
-		foreach ($searchProperties as $prop => $value) {
271
-			switch ($prop) {
272
-				case '{http://sabredav.org/ns}email-address':
273
-					$users = $this->userManager->getByEmail($value);
274
-
275
-					if (!$allowEnumeration) {
276
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
277
-							return $user->getEMailAddress() === $value;
278
-						});
279
-					}
280
-
281
-					if ($limitEnumeration) {
282
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
283
-							return !empty(array_intersect(
284
-									$this->groupManager->getUserGroupIds($user),
285
-									$currentUserGroups
286
-								)) || $user->getEMailAddress() === $value;
287
-						});
288
-					}
289
-
290
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
291
-						// is sharing restricted to groups only?
292
-						if ($restrictGroups !== false) {
293
-							$userGroups = $this->groupManager->getUserGroupIds($user);
294
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
295
-								return $carry;
296
-							}
297
-						}
298
-
299
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
300
-						return $carry;
301
-					}, []);
302
-					break;
303
-
304
-				case '{DAV:}displayname':
305
-					$users = $this->userManager->searchDisplayName($value);
306
-
307
-					if (!$allowEnumeration) {
308
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
309
-							return $user->getDisplayName() === $value;
310
-						});
311
-					}
312
-
313
-					if ($limitEnumeration) {
314
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
315
-							return !empty(array_intersect(
316
-									$this->groupManager->getUserGroupIds($user),
317
-									$currentUserGroups
318
-								)) || $user->getDisplayName() === $value;
319
-						});
320
-					}
321
-
322
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
323
-						// is sharing restricted to groups only?
324
-						if ($restrictGroups !== false) {
325
-							$userGroups = $this->groupManager->getUserGroupIds($user);
326
-							if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
327
-								return $carry;
328
-							}
329
-						}
330
-
331
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
332
-						return $carry;
333
-					}, []);
334
-					break;
335
-
336
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
337
-					// If you add support for more search properties that qualify as a user-address,
338
-					// please also add them to the array below
339
-					$results[] = $this->searchUserPrincipals([
340
-						// In theory this should also search for principal:principals/users/...
341
-						// but that's used internally only anyway and i don't know of any client querying that
342
-						'{http://sabredav.org/ns}email-address' => $value,
343
-					], 'anyof');
344
-					break;
345
-
346
-				default:
347
-					$results[] = [];
348
-					break;
349
-			}
350
-		}
351
-
352
-		// results is an array of arrays, so this is not the first search result
353
-		// but the results of the first searchProperty
354
-		if (count($results) === 1) {
355
-			return $results[0];
356
-		}
357
-
358
-		switch ($test) {
359
-			case 'anyof':
360
-				return array_values(array_unique(array_merge(...$results)));
361
-
362
-			case 'allof':
363
-			default:
364
-				return array_values(array_intersect(...$results));
365
-		}
366
-	}
367
-
368
-	/**
369
-	 * @param string $prefixPath
370
-	 * @param array $searchProperties
371
-	 * @param string $test
372
-	 * @return array
373
-	 */
374
-	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
375
-		if (count($searchProperties) === 0) {
376
-			return [];
377
-		}
378
-
379
-		switch ($prefixPath) {
380
-			case 'principals/users':
381
-				return $this->searchUserPrincipals($searchProperties, $test);
382
-
383
-			default:
384
-				return [];
385
-		}
386
-	}
387
-
388
-	/**
389
-	 * @param string $uri
390
-	 * @param string $principalPrefix
391
-	 * @return string
392
-	 */
393
-	function findByUri($uri, $principalPrefix) {
394
-		// If sharing is disabled, return the empty array
395
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
396
-		if (!$shareAPIEnabled) {
397
-			return null;
398
-		}
399
-
400
-		// If sharing is restricted to group members only,
401
-		// return only members that have groups in common
402
-		$restrictGroups = false;
403
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
404
-			$user = $this->userSession->getUser();
405
-			if (!$user) {
406
-				return null;
407
-			}
408
-
409
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
410
-		}
411
-
412
-		if (strpos($uri, 'mailto:') === 0) {
413
-			if ($principalPrefix === 'principals/users') {
414
-				$users = $this->userManager->getByEmail(substr($uri, 7));
415
-				if (count($users) !== 1) {
416
-					return null;
417
-				}
418
-				$user = $users[0];
419
-
420
-				if ($restrictGroups !== false) {
421
-					$userGroups = $this->groupManager->getUserGroupIds($user);
422
-					if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
423
-						return null;
424
-					}
425
-				}
426
-
427
-				return $this->principalPrefix . '/' . $user->getUID();
428
-			}
429
-		}
430
-		if (substr($uri, 0, 10) === 'principal:') {
431
-			$principal = substr($uri, 10);
432
-			$principal = $this->getPrincipalByPath($principal);
433
-			if ($principal !== null) {
434
-				return $principal['uri'];
435
-			}
436
-		}
437
-
438
-		return null;
439
-	}
440
-
441
-	/**
442
-	 * @param IUser $user
443
-	 * @return array
444
-	 */
445
-	protected function userToPrincipal($user) {
446
-		$userId = $user->getUID();
447
-		$displayName = $user->getDisplayName();
448
-		$principal = [
449
-			'uri' => $this->principalPrefix . '/' . $userId,
450
-			'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
451
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
452
-		];
453
-
454
-		$email = $user->getEMailAddress();
455
-		if (!empty($email)) {
456
-			$principal['{http://sabredav.org/ns}email-address'] = $email;
457
-		}
458
-
459
-		return $principal;
460
-	}
461
-
462
-	public function getPrincipalPrefix() {
463
-		return $this->principalPrefix;
464
-	}
465
-
466
-	/**
467
-	 * @param string $circleUniqueId
468
-	 * @return array|null
469
-	 * @throws \OCP\AppFramework\QueryException
470
-	 * @suppress PhanUndeclaredClassMethod
471
-	 * @suppress PhanUndeclaredClassCatch
472
-	 */
473
-	protected function circleToPrincipal($circleUniqueId) {
474
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
475
-			return null;
476
-		}
477
-
478
-		try {
479
-			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
480
-		} catch(QueryException $ex) {
481
-			return null;
482
-		} catch(CircleDoesNotExistException $ex) {
483
-			return null;
484
-		}
485
-
486
-		if (!$circle) {
487
-			return null;
488
-		}
489
-
490
-		$principal = [
491
-			'uri' => 'principals/circles/' . $circleUniqueId,
492
-			'{DAV:}displayname' => $circle->getName(),
493
-		];
494
-
495
-		return $principal;
496
-	}
497
-
498
-	/**
499
-	 * Returns the list of circles a principal is a member of
500
-	 *
501
-	 * @param string $principal
502
-	 * @return array
503
-	 * @throws Exception
504
-	 * @throws \OCP\AppFramework\QueryException
505
-	 * @suppress PhanUndeclaredClassMethod
506
-	 */
507
-	public function getCircleMembership($principal):array {
508
-		if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
509
-			return [];
510
-		}
511
-
512
-		list($prefix, $name) = \Sabre\Uri\split($principal);
513
-		if ($this->hasCircles && $prefix === $this->principalPrefix) {
514
-			$user = $this->userManager->get($name);
515
-			if (!$user) {
516
-				throw new Exception('Principal not found');
517
-			}
518
-
519
-			$circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
520
-
521
-			$circles = array_map(function ($circle) {
522
-				/** @var \OCA\Circles\Model\Circle $circle */
523
-				return 'principals/circles/' . urlencode($circle->getUniqueId());
524
-			}, $circles);
525
-
526
-			return $circles;
527
-		}
528
-
529
-		return [];
530
-	}
53
+    /** @var IUserManager */
54
+    private $userManager;
55
+
56
+    /** @var IGroupManager */
57
+    private $groupManager;
58
+
59
+    /** @var IShareManager */
60
+    private $shareManager;
61
+
62
+    /** @var IUserSession */
63
+    private $userSession;
64
+
65
+    /** @var IAppManager */
66
+    private $appManager;
67
+
68
+    /** @var string */
69
+    private $principalPrefix;
70
+
71
+    /** @var bool */
72
+    private $hasGroups;
73
+
74
+    /** @var bool */
75
+    private $hasCircles;
76
+
77
+    /** @var ProxyMapper */
78
+    private $proxyMapper;
79
+
80
+    /** @var IConfig */
81
+    private $config;
82
+
83
+    /**
84
+     * Principal constructor.
85
+     *
86
+     * @param IUserManager $userManager
87
+     * @param IGroupManager $groupManager
88
+     * @param IShareManager $shareManager
89
+     * @param IUserSession $userSession
90
+     * @param IAppManager $appManager
91
+     * @param ProxyMapper $proxyMapper
92
+     * @param IConfig $config
93
+     * @param string $principalPrefix
94
+     */
95
+    public function __construct(IUserManager $userManager,
96
+                                IGroupManager $groupManager,
97
+                                IShareManager $shareManager,
98
+                                IUserSession $userSession,
99
+                                IAppManager $appManager,
100
+                                ProxyMapper $proxyMapper,
101
+                                IConfig $config,
102
+                                string $principalPrefix = 'principals/users/') {
103
+        $this->userManager = $userManager;
104
+        $this->groupManager = $groupManager;
105
+        $this->shareManager = $shareManager;
106
+        $this->userSession = $userSession;
107
+        $this->appManager = $appManager;
108
+        $this->principalPrefix = trim($principalPrefix, '/');
109
+        $this->hasGroups = $this->hasCircles = ($principalPrefix === 'principals/users/');
110
+        $this->proxyMapper = $proxyMapper;
111
+        $this->config = $config;
112
+    }
113
+
114
+    use PrincipalProxyTrait {
115
+        getGroupMembership as protected traitGetGroupMembership;
116
+    }
117
+
118
+    /**
119
+     * Returns a list of principals based on a prefix.
120
+     *
121
+     * This prefix will often contain something like 'principals'. You are only
122
+     * expected to return principals that are in this base path.
123
+     *
124
+     * You are expected to return at least a 'uri' for every user, you can
125
+     * return any additional properties if you wish so. Common properties are:
126
+     *   {DAV:}displayname
127
+     *
128
+     * @param string $prefixPath
129
+     * @return string[]
130
+     */
131
+    public function getPrincipalsByPrefix($prefixPath) {
132
+        $principals = [];
133
+
134
+        if ($prefixPath === $this->principalPrefix) {
135
+            foreach($this->userManager->search('') as $user) {
136
+                $principals[] = $this->userToPrincipal($user);
137
+            }
138
+        }
139
+
140
+        return $principals;
141
+    }
142
+
143
+    /**
144
+     * Returns a specific principal, specified by it's path.
145
+     * The returned structure should be the exact same as from
146
+     * getPrincipalsByPrefix.
147
+     *
148
+     * @param string $path
149
+     * @return array
150
+     */
151
+    public function getPrincipalByPath($path) {
152
+        list($prefix, $name) = \Sabre\Uri\split($path);
153
+
154
+        if ($name === 'calendar-proxy-write' || $name === 'calendar-proxy-read') {
155
+            list($prefix2, $name2) = \Sabre\Uri\split($prefix);
156
+
157
+            if ($prefix2 === $this->principalPrefix) {
158
+                $user = $this->userManager->get($name2);
159
+
160
+                if ($user !== null) {
161
+                    return [
162
+                        'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
163
+                    ];
164
+                }
165
+                return null;
166
+            }
167
+        }
168
+
169
+        if ($prefix === $this->principalPrefix) {
170
+            $user = $this->userManager->get($name);
171
+
172
+            if ($user !== null) {
173
+                return $this->userToPrincipal($user);
174
+            }
175
+        } else if ($prefix === 'principals/circles') {
176
+            try {
177
+                return $this->circleToPrincipal($name);
178
+            } catch (QueryException $e) {
179
+                return null;
180
+            }
181
+        }
182
+        return null;
183
+    }
184
+
185
+    /**
186
+     * Returns the list of groups a principal is a member of
187
+     *
188
+     * @param string $principal
189
+     * @param bool $needGroups
190
+     * @return array
191
+     * @throws Exception
192
+     */
193
+    public function getGroupMembership($principal, $needGroups = false) {
194
+        list($prefix, $name) = \Sabre\Uri\split($principal);
195
+
196
+        if ($prefix !== $this->principalPrefix) {
197
+            return [];
198
+        }
199
+
200
+        $user = $this->userManager->get($name);
201
+        if (!$user) {
202
+            throw new Exception('Principal not found');
203
+        }
204
+
205
+        $groups = [];
206
+
207
+        if ($this->hasGroups || $needGroups) {
208
+            $userGroups = $this->groupManager->getUserGroups($user);
209
+            foreach($userGroups as $userGroup) {
210
+                $groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
211
+            }
212
+        }
213
+
214
+        $groups = array_unique(array_merge(
215
+            $groups,
216
+            $this->traitGetGroupMembership($principal, $needGroups)
217
+        ));
218
+
219
+        return $groups;
220
+    }
221
+
222
+    /**
223
+     * @param string $path
224
+     * @param PropPatch $propPatch
225
+     * @return int
226
+     */
227
+    function updatePrincipal($path, PropPatch $propPatch) {
228
+        return 0;
229
+    }
230
+
231
+    /**
232
+     * Search user principals
233
+     *
234
+     * @param array $searchProperties
235
+     * @param string $test
236
+     * @return array
237
+     */
238
+    protected function searchUserPrincipals(array $searchProperties, $test = 'allof') {
239
+        $results = [];
240
+
241
+        // If sharing is disabled, return the empty array
242
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
243
+        if (!$shareAPIEnabled) {
244
+            return [];
245
+        }
246
+
247
+        $allowEnumeration = $this->shareManager->allowEnumeration();
248
+        $limitEnumeration = $this->shareManager->limitEnumerationToGroups();
249
+
250
+        // If sharing is restricted to group members only,
251
+        // return only members that have groups in common
252
+        $restrictGroups = false;
253
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
254
+            $user = $this->userSession->getUser();
255
+            if (!$user) {
256
+                return [];
257
+            }
258
+
259
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
260
+        }
261
+
262
+        $currentUserGroups = [];
263
+        if ($limitEnumeration) {
264
+            $currentUser = $this->userSession->getUser();
265
+            if ($currentUser) {
266
+                $currentUserGroups = $this->groupManager->getUserGroupIds($currentUser);
267
+            }
268
+        }
269
+
270
+        foreach ($searchProperties as $prop => $value) {
271
+            switch ($prop) {
272
+                case '{http://sabredav.org/ns}email-address':
273
+                    $users = $this->userManager->getByEmail($value);
274
+
275
+                    if (!$allowEnumeration) {
276
+                        $users = \array_filter($users, static function (IUser $user) use ($value) {
277
+                            return $user->getEMailAddress() === $value;
278
+                        });
279
+                    }
280
+
281
+                    if ($limitEnumeration) {
282
+                        $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
283
+                            return !empty(array_intersect(
284
+                                    $this->groupManager->getUserGroupIds($user),
285
+                                    $currentUserGroups
286
+                                )) || $user->getEMailAddress() === $value;
287
+                        });
288
+                    }
289
+
290
+                    $results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
291
+                        // is sharing restricted to groups only?
292
+                        if ($restrictGroups !== false) {
293
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
294
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
295
+                                return $carry;
296
+                            }
297
+                        }
298
+
299
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
300
+                        return $carry;
301
+                    }, []);
302
+                    break;
303
+
304
+                case '{DAV:}displayname':
305
+                    $users = $this->userManager->searchDisplayName($value);
306
+
307
+                    if (!$allowEnumeration) {
308
+                        $users = \array_filter($users, static function (IUser $user) use ($value) {
309
+                            return $user->getDisplayName() === $value;
310
+                        });
311
+                    }
312
+
313
+                    if ($limitEnumeration) {
314
+                        $users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
315
+                            return !empty(array_intersect(
316
+                                    $this->groupManager->getUserGroupIds($user),
317
+                                    $currentUserGroups
318
+                                )) || $user->getDisplayName() === $value;
319
+                        });
320
+                    }
321
+
322
+                    $results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
323
+                        // is sharing restricted to groups only?
324
+                        if ($restrictGroups !== false) {
325
+                            $userGroups = $this->groupManager->getUserGroupIds($user);
326
+                            if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
327
+                                return $carry;
328
+                            }
329
+                        }
330
+
331
+                        $carry[] = $this->principalPrefix . '/' . $user->getUID();
332
+                        return $carry;
333
+                    }, []);
334
+                    break;
335
+
336
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
337
+                    // If you add support for more search properties that qualify as a user-address,
338
+                    // please also add them to the array below
339
+                    $results[] = $this->searchUserPrincipals([
340
+                        // In theory this should also search for principal:principals/users/...
341
+                        // but that's used internally only anyway and i don't know of any client querying that
342
+                        '{http://sabredav.org/ns}email-address' => $value,
343
+                    ], 'anyof');
344
+                    break;
345
+
346
+                default:
347
+                    $results[] = [];
348
+                    break;
349
+            }
350
+        }
351
+
352
+        // results is an array of arrays, so this is not the first search result
353
+        // but the results of the first searchProperty
354
+        if (count($results) === 1) {
355
+            return $results[0];
356
+        }
357
+
358
+        switch ($test) {
359
+            case 'anyof':
360
+                return array_values(array_unique(array_merge(...$results)));
361
+
362
+            case 'allof':
363
+            default:
364
+                return array_values(array_intersect(...$results));
365
+        }
366
+    }
367
+
368
+    /**
369
+     * @param string $prefixPath
370
+     * @param array $searchProperties
371
+     * @param string $test
372
+     * @return array
373
+     */
374
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
375
+        if (count($searchProperties) === 0) {
376
+            return [];
377
+        }
378
+
379
+        switch ($prefixPath) {
380
+            case 'principals/users':
381
+                return $this->searchUserPrincipals($searchProperties, $test);
382
+
383
+            default:
384
+                return [];
385
+        }
386
+    }
387
+
388
+    /**
389
+     * @param string $uri
390
+     * @param string $principalPrefix
391
+     * @return string
392
+     */
393
+    function findByUri($uri, $principalPrefix) {
394
+        // If sharing is disabled, return the empty array
395
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
396
+        if (!$shareAPIEnabled) {
397
+            return null;
398
+        }
399
+
400
+        // If sharing is restricted to group members only,
401
+        // return only members that have groups in common
402
+        $restrictGroups = false;
403
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
404
+            $user = $this->userSession->getUser();
405
+            if (!$user) {
406
+                return null;
407
+            }
408
+
409
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
410
+        }
411
+
412
+        if (strpos($uri, 'mailto:') === 0) {
413
+            if ($principalPrefix === 'principals/users') {
414
+                $users = $this->userManager->getByEmail(substr($uri, 7));
415
+                if (count($users) !== 1) {
416
+                    return null;
417
+                }
418
+                $user = $users[0];
419
+
420
+                if ($restrictGroups !== false) {
421
+                    $userGroups = $this->groupManager->getUserGroupIds($user);
422
+                    if (count(array_intersect($userGroups, $restrictGroups)) === 0) {
423
+                        return null;
424
+                    }
425
+                }
426
+
427
+                return $this->principalPrefix . '/' . $user->getUID();
428
+            }
429
+        }
430
+        if (substr($uri, 0, 10) === 'principal:') {
431
+            $principal = substr($uri, 10);
432
+            $principal = $this->getPrincipalByPath($principal);
433
+            if ($principal !== null) {
434
+                return $principal['uri'];
435
+            }
436
+        }
437
+
438
+        return null;
439
+    }
440
+
441
+    /**
442
+     * @param IUser $user
443
+     * @return array
444
+     */
445
+    protected function userToPrincipal($user) {
446
+        $userId = $user->getUID();
447
+        $displayName = $user->getDisplayName();
448
+        $principal = [
449
+            'uri' => $this->principalPrefix . '/' . $userId,
450
+            '{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
451
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
452
+        ];
453
+
454
+        $email = $user->getEMailAddress();
455
+        if (!empty($email)) {
456
+            $principal['{http://sabredav.org/ns}email-address'] = $email;
457
+        }
458
+
459
+        return $principal;
460
+    }
461
+
462
+    public function getPrincipalPrefix() {
463
+        return $this->principalPrefix;
464
+    }
465
+
466
+    /**
467
+     * @param string $circleUniqueId
468
+     * @return array|null
469
+     * @throws \OCP\AppFramework\QueryException
470
+     * @suppress PhanUndeclaredClassMethod
471
+     * @suppress PhanUndeclaredClassCatch
472
+     */
473
+    protected function circleToPrincipal($circleUniqueId) {
474
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
475
+            return null;
476
+        }
477
+
478
+        try {
479
+            $circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
480
+        } catch(QueryException $ex) {
481
+            return null;
482
+        } catch(CircleDoesNotExistException $ex) {
483
+            return null;
484
+        }
485
+
486
+        if (!$circle) {
487
+            return null;
488
+        }
489
+
490
+        $principal = [
491
+            'uri' => 'principals/circles/' . $circleUniqueId,
492
+            '{DAV:}displayname' => $circle->getName(),
493
+        ];
494
+
495
+        return $principal;
496
+    }
497
+
498
+    /**
499
+     * Returns the list of circles a principal is a member of
500
+     *
501
+     * @param string $principal
502
+     * @return array
503
+     * @throws Exception
504
+     * @throws \OCP\AppFramework\QueryException
505
+     * @suppress PhanUndeclaredClassMethod
506
+     */
507
+    public function getCircleMembership($principal):array {
508
+        if (!$this->appManager->isEnabledForUser('circles') || !class_exists('\OCA\Circles\Api\v1\Circles')) {
509
+            return [];
510
+        }
511
+
512
+        list($prefix, $name) = \Sabre\Uri\split($principal);
513
+        if ($this->hasCircles && $prefix === $this->principalPrefix) {
514
+            $user = $this->userManager->get($name);
515
+            if (!$user) {
516
+                throw new Exception('Principal not found');
517
+            }
518
+
519
+            $circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
520
+
521
+            $circles = array_map(function ($circle) {
522
+                /** @var \OCA\Circles\Model\Circle $circle */
523
+                return 'principals/circles/' . urlencode($circle->getUniqueId());
524
+            }, $circles);
525
+
526
+            return $circles;
527
+        }
528
+
529
+        return [];
530
+    }
531 531
 }
Please login to merge, or discard this patch.
Spacing   +19 added lines, -19 removed lines patch added patch discarded remove patch
@@ -132,7 +132,7 @@  discard block
 block discarded – undo
132 132
 		$principals = [];
133 133
 
134 134
 		if ($prefixPath === $this->principalPrefix) {
135
-			foreach($this->userManager->search('') as $user) {
135
+			foreach ($this->userManager->search('') as $user) {
136 136
 				$principals[] = $this->userToPrincipal($user);
137 137
 			}
138 138
 		}
@@ -159,7 +159,7 @@  discard block
 block discarded – undo
159 159
 
160 160
 				if ($user !== null) {
161 161
 					return [
162
-						'uri' => 'principals/users/' . $user->getUID() . '/' . $name,
162
+						'uri' => 'principals/users/'.$user->getUID().'/'.$name,
163 163
 					];
164 164
 				}
165 165
 				return null;
@@ -206,8 +206,8 @@  discard block
 block discarded – undo
206 206
 
207 207
 		if ($this->hasGroups || $needGroups) {
208 208
 			$userGroups = $this->groupManager->getUserGroups($user);
209
-			foreach($userGroups as $userGroup) {
210
-				$groups[] = 'principals/groups/' . urlencode($userGroup->getGID());
209
+			foreach ($userGroups as $userGroup) {
210
+				$groups[] = 'principals/groups/'.urlencode($userGroup->getGID());
211 211
 			}
212 212
 		}
213 213
 
@@ -273,13 +273,13 @@  discard block
 block discarded – undo
273 273
 					$users = $this->userManager->getByEmail($value);
274 274
 
275 275
 					if (!$allowEnumeration) {
276
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
276
+						$users = \array_filter($users, static function(IUser $user) use ($value) {
277 277
 							return $user->getEMailAddress() === $value;
278 278
 						});
279 279
 					}
280 280
 
281 281
 					if ($limitEnumeration) {
282
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
282
+						$users = \array_filter($users, function(IUser $user) use ($currentUserGroups, $value) {
283 283
 							return !empty(array_intersect(
284 284
 									$this->groupManager->getUserGroupIds($user),
285 285
 									$currentUserGroups
@@ -287,7 +287,7 @@  discard block
 block discarded – undo
287 287
 						});
288 288
 					}
289 289
 
290
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
290
+					$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
291 291
 						// is sharing restricted to groups only?
292 292
 						if ($restrictGroups !== false) {
293 293
 							$userGroups = $this->groupManager->getUserGroupIds($user);
@@ -296,7 +296,7 @@  discard block
 block discarded – undo
296 296
 							}
297 297
 						}
298 298
 
299
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
299
+						$carry[] = $this->principalPrefix.'/'.$user->getUID();
300 300
 						return $carry;
301 301
 					}, []);
302 302
 					break;
@@ -305,13 +305,13 @@  discard block
 block discarded – undo
305 305
 					$users = $this->userManager->searchDisplayName($value);
306 306
 
307 307
 					if (!$allowEnumeration) {
308
-						$users = \array_filter($users, static function (IUser $user) use ($value) {
308
+						$users = \array_filter($users, static function(IUser $user) use ($value) {
309 309
 							return $user->getDisplayName() === $value;
310 310
 						});
311 311
 					}
312 312
 
313 313
 					if ($limitEnumeration) {
314
-						$users = \array_filter($users, function (IUser $user) use ($currentUserGroups, $value) {
314
+						$users = \array_filter($users, function(IUser $user) use ($currentUserGroups, $value) {
315 315
 							return !empty(array_intersect(
316 316
 									$this->groupManager->getUserGroupIds($user),
317 317
 									$currentUserGroups
@@ -319,7 +319,7 @@  discard block
 block discarded – undo
319 319
 						});
320 320
 					}
321 321
 
322
-					$results[] = array_reduce($users, function (array $carry, IUser $user) use ($restrictGroups) {
322
+					$results[] = array_reduce($users, function(array $carry, IUser $user) use ($restrictGroups) {
323 323
 						// is sharing restricted to groups only?
324 324
 						if ($restrictGroups !== false) {
325 325
 							$userGroups = $this->groupManager->getUserGroupIds($user);
@@ -328,7 +328,7 @@  discard block
 block discarded – undo
328 328
 							}
329 329
 						}
330 330
 
331
-						$carry[] = $this->principalPrefix . '/' . $user->getUID();
331
+						$carry[] = $this->principalPrefix.'/'.$user->getUID();
332 332
 						return $carry;
333 333
 					}, []);
334 334
 					break;
@@ -424,7 +424,7 @@  discard block
 block discarded – undo
424 424
 					}
425 425
 				}
426 426
 
427
-				return $this->principalPrefix . '/' . $user->getUID();
427
+				return $this->principalPrefix.'/'.$user->getUID();
428 428
 			}
429 429
 		}
430 430
 		if (substr($uri, 0, 10) === 'principal:') {
@@ -446,7 +446,7 @@  discard block
 block discarded – undo
446 446
 		$userId = $user->getUID();
447 447
 		$displayName = $user->getDisplayName();
448 448
 		$principal = [
449
-			'uri' => $this->principalPrefix . '/' . $userId,
449
+			'uri' => $this->principalPrefix.'/'.$userId,
450 450
 			'{DAV:}displayname' => is_null($displayName) ? $userId : $displayName,
451 451
 			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
452 452
 		];
@@ -477,9 +477,9 @@  discard block
 block discarded – undo
477 477
 
478 478
 		try {
479 479
 			$circle = \OCA\Circles\Api\v1\Circles::detailsCircle($circleUniqueId, true);
480
-		} catch(QueryException $ex) {
480
+		} catch (QueryException $ex) {
481 481
 			return null;
482
-		} catch(CircleDoesNotExistException $ex) {
482
+		} catch (CircleDoesNotExistException $ex) {
483 483
 			return null;
484 484
 		}
485 485
 
@@ -488,7 +488,7 @@  discard block
 block discarded – undo
488 488
 		}
489 489
 
490 490
 		$principal = [
491
-			'uri' => 'principals/circles/' . $circleUniqueId,
491
+			'uri' => 'principals/circles/'.$circleUniqueId,
492 492
 			'{DAV:}displayname' => $circle->getName(),
493 493
 		];
494 494
 
@@ -518,9 +518,9 @@  discard block
 block discarded – undo
518 518
 
519 519
 			$circles = \OCA\Circles\Api\v1\Circles::joinedCircles($name, true);
520 520
 
521
-			$circles = array_map(function ($circle) {
521
+			$circles = array_map(function($circle) {
522 522
 				/** @var \OCA\Circles\Model\Circle $circle */
523
-				return 'principals/circles/' . urlencode($circle->getUniqueId());
523
+				return 'principals/circles/'.urlencode($circle->getUniqueId());
524 524
 			}, $circles);
525 525
 
526 526
 			return $circles;
Please login to merge, or discard this patch.
apps/dav/lib/Connector/Sabre/CommentPropertiesPlugin.php 2 patches
Indentation   +127 added lines, -127 removed lines patch added patch discarded remove patch
@@ -33,132 +33,132 @@
 block discarded – undo
33 33
 
34 34
 class CommentPropertiesPlugin extends ServerPlugin {
35 35
 
36
-	const PROPERTY_NAME_HREF   = '{http://owncloud.org/ns}comments-href';
37
-	const PROPERTY_NAME_COUNT  = '{http://owncloud.org/ns}comments-count';
38
-	const PROPERTY_NAME_UNREAD = '{http://owncloud.org/ns}comments-unread';
39
-
40
-	/** @var  \Sabre\DAV\Server */
41
-	protected $server;
42
-
43
-	/** @var ICommentsManager */
44
-	private $commentsManager;
45
-
46
-	/** @var IUserSession */
47
-	private $userSession;
48
-
49
-	private $cachedUnreadCount = [];
50
-
51
-	private $cachedFolders = [];
52
-
53
-	public function __construct(ICommentsManager $commentsManager, IUserSession $userSession) {
54
-		$this->commentsManager = $commentsManager;
55
-		$this->userSession = $userSession;
56
-	}
57
-
58
-	/**
59
-	 * This initializes the plugin.
60
-	 *
61
-	 * This function is called by Sabre\DAV\Server, after
62
-	 * addPlugin is called.
63
-	 *
64
-	 * This method should set up the required event subscriptions.
65
-	 *
66
-	 * @param \Sabre\DAV\Server $server
67
-	 * @return void
68
-	 */
69
-	function initialize(\Sabre\DAV\Server $server) {
70
-		$this->server = $server;
71
-		$this->server->on('propFind', [$this, 'handleGetProperties']);
72
-	}
73
-
74
-	/**
75
-	 * Adds tags and favorites properties to the response,
76
-	 * if requested.
77
-	 *
78
-	 * @param PropFind $propFind
79
-	 * @param \Sabre\DAV\INode $node
80
-	 * @return void
81
-	 */
82
-	public function handleGetProperties(
83
-		PropFind $propFind,
84
-		\Sabre\DAV\INode $node
85
-	) {
86
-		if (!($node instanceof File) && !($node instanceof Directory)) {
87
-			return;
88
-		}
89
-
90
-		// need prefetch ?
91
-		if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
92
-			&& $propFind->getDepth() !== 0
93
-			&& !is_null($propFind->getStatus(self::PROPERTY_NAME_UNREAD))
94
-		) {
95
-			$unreadCounts = $this->commentsManager->getNumberOfUnreadCommentsForFolder($node->getId(), $this->userSession->getUser());
96
-			$this->cachedFolders[] = $node->getPath();
97
-			foreach ($unreadCounts as $id => $count) {
98
-				$this->cachedUnreadCount[$id] = $count;
99
-			}
100
-		}
101
-
102
-		$propFind->handle(self::PROPERTY_NAME_COUNT, function () use ($node) {
103
-			return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId());
104
-		});
105
-
106
-		$propFind->handle(self::PROPERTY_NAME_HREF, function () use ($node) {
107
-			return $this->getCommentsLink($node);
108
-		});
109
-
110
-		$propFind->handle(self::PROPERTY_NAME_UNREAD, function () use ($node) {
111
-			if (isset($this->cachedUnreadCount[$node->getId()])) {
112
-				return $this->cachedUnreadCount[$node->getId()];
113
-			} else {
114
-				list($parentPath,) = \Sabre\Uri\split($node->getPath());
115
-				if ($parentPath === '') {
116
-					$parentPath = '/';
117
-				}
118
-				// if we already cached the folder this file is in we know there are no comments for this file
119
-				if (array_search($parentPath, $this->cachedFolders) === false) {
120
-					return 0;
121
-				} else {
122
-					return $this->getUnreadCount($node);
123
-				}
124
-			}
125
-		});
126
-	}
127
-
128
-	/**
129
-	 * returns a reference to the comments node
130
-	 *
131
-	 * @param Node $node
132
-	 * @return mixed|string
133
-	 */
134
-	public function getCommentsLink(Node $node) {
135
-		$href =  $this->server->getBaseUri();
136
-		$entryPoint = strpos($href, '/remote.php/');
137
-		if($entryPoint === false) {
138
-			// in case we end up somewhere else, unexpectedly.
139
-			return null;
140
-		}
141
-		$commentsPart = 'dav/comments/files/' . rawurldecode($node->getId());
142
-		$href = substr_replace($href, $commentsPart, $entryPoint + strlen('/remote.php/'));
143
-		return $href;
144
-	}
145
-
146
-	/**
147
-	 * returns the number of unread comments for the currently logged in user
148
-	 * on the given file or directory node
149
-	 *
150
-	 * @param Node $node
151
-	 * @return Int|null
152
-	 */
153
-	public function getUnreadCount(Node $node) {
154
-		$user = $this->userSession->getUser();
155
-		if(is_null($user)) {
156
-			return null;
157
-		}
158
-
159
-		$lastRead = $this->commentsManager->getReadMark('files', (string)$node->getId(), $user);
160
-
161
-		return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId(), $lastRead);
162
-	}
36
+    const PROPERTY_NAME_HREF   = '{http://owncloud.org/ns}comments-href';
37
+    const PROPERTY_NAME_COUNT  = '{http://owncloud.org/ns}comments-count';
38
+    const PROPERTY_NAME_UNREAD = '{http://owncloud.org/ns}comments-unread';
39
+
40
+    /** @var  \Sabre\DAV\Server */
41
+    protected $server;
42
+
43
+    /** @var ICommentsManager */
44
+    private $commentsManager;
45
+
46
+    /** @var IUserSession */
47
+    private $userSession;
48
+
49
+    private $cachedUnreadCount = [];
50
+
51
+    private $cachedFolders = [];
52
+
53
+    public function __construct(ICommentsManager $commentsManager, IUserSession $userSession) {
54
+        $this->commentsManager = $commentsManager;
55
+        $this->userSession = $userSession;
56
+    }
57
+
58
+    /**
59
+     * This initializes the plugin.
60
+     *
61
+     * This function is called by Sabre\DAV\Server, after
62
+     * addPlugin is called.
63
+     *
64
+     * This method should set up the required event subscriptions.
65
+     *
66
+     * @param \Sabre\DAV\Server $server
67
+     * @return void
68
+     */
69
+    function initialize(\Sabre\DAV\Server $server) {
70
+        $this->server = $server;
71
+        $this->server->on('propFind', [$this, 'handleGetProperties']);
72
+    }
73
+
74
+    /**
75
+     * Adds tags and favorites properties to the response,
76
+     * if requested.
77
+     *
78
+     * @param PropFind $propFind
79
+     * @param \Sabre\DAV\INode $node
80
+     * @return void
81
+     */
82
+    public function handleGetProperties(
83
+        PropFind $propFind,
84
+        \Sabre\DAV\INode $node
85
+    ) {
86
+        if (!($node instanceof File) && !($node instanceof Directory)) {
87
+            return;
88
+        }
89
+
90
+        // need prefetch ?
91
+        if ($node instanceof \OCA\DAV\Connector\Sabre\Directory
92
+            && $propFind->getDepth() !== 0
93
+            && !is_null($propFind->getStatus(self::PROPERTY_NAME_UNREAD))
94
+        ) {
95
+            $unreadCounts = $this->commentsManager->getNumberOfUnreadCommentsForFolder($node->getId(), $this->userSession->getUser());
96
+            $this->cachedFolders[] = $node->getPath();
97
+            foreach ($unreadCounts as $id => $count) {
98
+                $this->cachedUnreadCount[$id] = $count;
99
+            }
100
+        }
101
+
102
+        $propFind->handle(self::PROPERTY_NAME_COUNT, function () use ($node) {
103
+            return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId());
104
+        });
105
+
106
+        $propFind->handle(self::PROPERTY_NAME_HREF, function () use ($node) {
107
+            return $this->getCommentsLink($node);
108
+        });
109
+
110
+        $propFind->handle(self::PROPERTY_NAME_UNREAD, function () use ($node) {
111
+            if (isset($this->cachedUnreadCount[$node->getId()])) {
112
+                return $this->cachedUnreadCount[$node->getId()];
113
+            } else {
114
+                list($parentPath,) = \Sabre\Uri\split($node->getPath());
115
+                if ($parentPath === '') {
116
+                    $parentPath = '/';
117
+                }
118
+                // if we already cached the folder this file is in we know there are no comments for this file
119
+                if (array_search($parentPath, $this->cachedFolders) === false) {
120
+                    return 0;
121
+                } else {
122
+                    return $this->getUnreadCount($node);
123
+                }
124
+            }
125
+        });
126
+    }
127
+
128
+    /**
129
+     * returns a reference to the comments node
130
+     *
131
+     * @param Node $node
132
+     * @return mixed|string
133
+     */
134
+    public function getCommentsLink(Node $node) {
135
+        $href =  $this->server->getBaseUri();
136
+        $entryPoint = strpos($href, '/remote.php/');
137
+        if($entryPoint === false) {
138
+            // in case we end up somewhere else, unexpectedly.
139
+            return null;
140
+        }
141
+        $commentsPart = 'dav/comments/files/' . rawurldecode($node->getId());
142
+        $href = substr_replace($href, $commentsPart, $entryPoint + strlen('/remote.php/'));
143
+        return $href;
144
+    }
145
+
146
+    /**
147
+     * returns the number of unread comments for the currently logged in user
148
+     * on the given file or directory node
149
+     *
150
+     * @param Node $node
151
+     * @return Int|null
152
+     */
153
+    public function getUnreadCount(Node $node) {
154
+        $user = $this->userSession->getUser();
155
+        if(is_null($user)) {
156
+            return null;
157
+        }
158
+
159
+        $lastRead = $this->commentsManager->getReadMark('files', (string)$node->getId(), $user);
160
+
161
+        return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId(), $lastRead);
162
+    }
163 163
 
164 164
 }
Please login to merge, or discard this patch.
Spacing   +10 added lines, -10 removed lines patch added patch discarded remove patch
@@ -99,15 +99,15 @@  discard block
 block discarded – undo
99 99
 			}
100 100
 		}
101 101
 
102
-		$propFind->handle(self::PROPERTY_NAME_COUNT, function () use ($node) {
103
-			return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId());
102
+		$propFind->handle(self::PROPERTY_NAME_COUNT, function() use ($node) {
103
+			return $this->commentsManager->getNumberOfCommentsForObject('files', (string) $node->getId());
104 104
 		});
105 105
 
106
-		$propFind->handle(self::PROPERTY_NAME_HREF, function () use ($node) {
106
+		$propFind->handle(self::PROPERTY_NAME_HREF, function() use ($node) {
107 107
 			return $this->getCommentsLink($node);
108 108
 		});
109 109
 
110
-		$propFind->handle(self::PROPERTY_NAME_UNREAD, function () use ($node) {
110
+		$propFind->handle(self::PROPERTY_NAME_UNREAD, function() use ($node) {
111 111
 			if (isset($this->cachedUnreadCount[$node->getId()])) {
112 112
 				return $this->cachedUnreadCount[$node->getId()];
113 113
 			} else {
@@ -132,13 +132,13 @@  discard block
 block discarded – undo
132 132
 	 * @return mixed|string
133 133
 	 */
134 134
 	public function getCommentsLink(Node $node) {
135
-		$href =  $this->server->getBaseUri();
135
+		$href = $this->server->getBaseUri();
136 136
 		$entryPoint = strpos($href, '/remote.php/');
137
-		if($entryPoint === false) {
137
+		if ($entryPoint === false) {
138 138
 			// in case we end up somewhere else, unexpectedly.
139 139
 			return null;
140 140
 		}
141
-		$commentsPart = 'dav/comments/files/' . rawurldecode($node->getId());
141
+		$commentsPart = 'dav/comments/files/'.rawurldecode($node->getId());
142 142
 		$href = substr_replace($href, $commentsPart, $entryPoint + strlen('/remote.php/'));
143 143
 		return $href;
144 144
 	}
@@ -152,13 +152,13 @@  discard block
 block discarded – undo
152 152
 	 */
153 153
 	public function getUnreadCount(Node $node) {
154 154
 		$user = $this->userSession->getUser();
155
-		if(is_null($user)) {
155
+		if (is_null($user)) {
156 156
 			return null;
157 157
 		}
158 158
 
159
-		$lastRead = $this->commentsManager->getReadMark('files', (string)$node->getId(), $user);
159
+		$lastRead = $this->commentsManager->getReadMark('files', (string) $node->getId(), $user);
160 160
 
161
-		return $this->commentsManager->getNumberOfCommentsForObject('files', (string)$node->getId(), $lastRead);
161
+		return $this->commentsManager->getNumberOfCommentsForObject('files', (string) $node->getId(), $lastRead);
162 162
 	}
163 163
 
164 164
 }
Please login to merge, or discard this patch.
apps/dav/lib/DAV/GroupPrincipalBackend.php 2 patches
Indentation   +290 added lines, -290 removed lines patch added patch discarded remove patch
@@ -37,294 +37,294 @@
 block discarded – undo
37 37
 
38 38
 class GroupPrincipalBackend implements BackendInterface {
39 39
 
40
-	const PRINCIPAL_PREFIX = 'principals/groups';
41
-
42
-	/** @var IGroupManager */
43
-	private $groupManager;
44
-
45
-	/** @var IUserSession */
46
-	private $userSession;
47
-
48
-	/** @var IShareManager */
49
-	private $shareManager;
50
-
51
-	/**
52
-	 * @param IGroupManager $IGroupManager
53
-	 * @param IUserSession $userSession
54
-	 * @param IShareManager $shareManager
55
-	 */
56
-	public function __construct(IGroupManager $IGroupManager,
57
-								IUserSession $userSession,
58
-								IShareManager $shareManager) {
59
-		$this->groupManager = $IGroupManager;
60
-		$this->userSession = $userSession;
61
-		$this->shareManager = $shareManager;
62
-	}
63
-
64
-	/**
65
-	 * Returns a list of principals based on a prefix.
66
-	 *
67
-	 * This prefix will often contain something like 'principals'. You are only
68
-	 * expected to return principals that are in this base path.
69
-	 *
70
-	 * You are expected to return at least a 'uri' for every user, you can
71
-	 * return any additional properties if you wish so. Common properties are:
72
-	 *   {DAV:}displayname
73
-	 *
74
-	 * @param string $prefixPath
75
-	 * @return string[]
76
-	 */
77
-	public function getPrincipalsByPrefix($prefixPath) {
78
-		$principals = [];
79
-
80
-		if ($prefixPath === self::PRINCIPAL_PREFIX) {
81
-			foreach($this->groupManager->search('') as $user) {
82
-				$principals[] = $this->groupToPrincipal($user);
83
-			}
84
-		}
85
-
86
-		return $principals;
87
-	}
88
-
89
-	/**
90
-	 * Returns a specific principal, specified by it's path.
91
-	 * The returned structure should be the exact same as from
92
-	 * getPrincipalsByPrefix.
93
-	 *
94
-	 * @param string $path
95
-	 * @return array
96
-	 */
97
-	public function getPrincipalByPath($path) {
98
-		$elements = explode('/', $path,  3);
99
-		if ($elements[0] !== 'principals') {
100
-			return null;
101
-		}
102
-		if ($elements[1] !== 'groups') {
103
-			return null;
104
-		}
105
-		$name = urldecode($elements[2]);
106
-		$group = $this->groupManager->get($name);
107
-
108
-		if (!is_null($group)) {
109
-			return $this->groupToPrincipal($group);
110
-		}
111
-
112
-		return null;
113
-	}
114
-
115
-	/**
116
-	 * Returns the list of members for a group-principal
117
-	 *
118
-	 * @param string $principal
119
-	 * @return string[]
120
-	 * @throws Exception
121
-	 */
122
-	public function getGroupMemberSet($principal) {
123
-		$elements = explode('/', $principal);
124
-		if ($elements[0] !== 'principals') {
125
-			return [];
126
-		}
127
-		if ($elements[1] !== 'groups') {
128
-			return [];
129
-		}
130
-		$name = $elements[2];
131
-		$group = $this->groupManager->get($name);
132
-
133
-		if (is_null($group)) {
134
-			return [];
135
-		}
136
-
137
-		return array_map(function ($user) {
138
-			return $this->userToPrincipal($user);
139
-		}, $group->getUsers());
140
-	}
141
-
142
-	/**
143
-	 * Returns the list of groups a principal is a member of
144
-	 *
145
-	 * @param string $principal
146
-	 * @return array
147
-	 * @throws Exception
148
-	 */
149
-	public function getGroupMembership($principal) {
150
-		return [];
151
-	}
152
-
153
-	/**
154
-	 * Updates the list of group members for a group principal.
155
-	 *
156
-	 * The principals should be passed as a list of uri's.
157
-	 *
158
-	 * @param string $principal
159
-	 * @param string[] $members
160
-	 * @throws Exception
161
-	 */
162
-	public function setGroupMemberSet($principal, array $members) {
163
-		throw new Exception('Setting members of the group is not supported yet');
164
-	}
165
-
166
-	/**
167
-	 * @param string $path
168
-	 * @param PropPatch $propPatch
169
-	 * @return int
170
-	 */
171
-	function updatePrincipal($path, PropPatch $propPatch) {
172
-		return 0;
173
-	}
174
-
175
-	/**
176
-	 * @param string $prefixPath
177
-	 * @param array $searchProperties
178
-	 * @param string $test
179
-	 * @return array
180
-	 */
181
-	function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
182
-		$results = [];
183
-
184
-		if (\count($searchProperties) === 0) {
185
-			return [];
186
-		}
187
-		if ($prefixPath !== self::PRINCIPAL_PREFIX) {
188
-			return [];
189
-		}
190
-		// If sharing is disabled, return the empty array
191
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
192
-		if (!$shareAPIEnabled) {
193
-			return [];
194
-		}
195
-
196
-		// If sharing is restricted to group members only,
197
-		// return only members that have groups in common
198
-		$restrictGroups = false;
199
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
200
-			$user = $this->userSession->getUser();
201
-			if (!$user) {
202
-				return [];
203
-			}
204
-
205
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
206
-		}
207
-
208
-		foreach ($searchProperties as $prop => $value) {
209
-			switch ($prop) {
210
-				case '{DAV:}displayname':
211
-					$groups = $this->groupManager->search($value);
212
-
213
-					$results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) {
214
-						$gid = $group->getGID();
215
-						// is sharing restricted to groups only?
216
-						if ($restrictGroups !== false) {
217
-							if (!\in_array($gid, $restrictGroups, true)) {
218
-								return $carry;
219
-							}
220
-						}
221
-
222
-						$carry[] = self::PRINCIPAL_PREFIX . '/' . $gid;
223
-						return $carry;
224
-					}, []);
225
-					break;
226
-
227
-				case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
228
-					// If you add support for more search properties that qualify as a user-address,
229
-					// please also add them to the array below
230
-					$results[] = $this->searchPrincipals(self::PRINCIPAL_PREFIX, [
231
-					], 'anyof');
232
-					break;
233
-
234
-				default:
235
-					$results[] = [];
236
-					break;
237
-			}
238
-		}
239
-
240
-		// results is an array of arrays, so this is not the first search result
241
-		// but the results of the first searchProperty
242
-		if (count($results) === 1) {
243
-			return $results[0];
244
-		}
245
-
246
-		switch ($test) {
247
-			case 'anyof':
248
-				return array_values(array_unique(array_merge(...$results)));
249
-
250
-			case 'allof':
251
-			default:
252
-				return array_values(array_intersect(...$results));
253
-		}
254
-	}
255
-
256
-	/**
257
-	 * @param string $uri
258
-	 * @param string $principalPrefix
259
-	 * @return string
260
-	 */
261
-	function findByUri($uri, $principalPrefix) {
262
-		// If sharing is disabled, return the empty array
263
-		$shareAPIEnabled = $this->shareManager->shareApiEnabled();
264
-		if (!$shareAPIEnabled) {
265
-			return null;
266
-		}
267
-
268
-		// If sharing is restricted to group members only,
269
-		// return only members that have groups in common
270
-		$restrictGroups = false;
271
-		if ($this->shareManager->shareWithGroupMembersOnly()) {
272
-			$user = $this->userSession->getUser();
273
-			if (!$user) {
274
-				return null;
275
-			}
276
-
277
-			$restrictGroups = $this->groupManager->getUserGroupIds($user);
278
-		}
279
-
280
-		if (strpos($uri, 'principal:principals/groups/') === 0) {
281
-			$name = urlencode(substr($uri, 28));
282
-			if ($restrictGroups !== false && !\in_array($name, $restrictGroups, true)) {
283
-				return null;
284
-			}
285
-
286
-			return substr($uri, 10);
287
-		}
288
-
289
-		return null;
290
-	}
291
-
292
-	/**
293
-	 * @param IGroup $group
294
-	 * @return array
295
-	 */
296
-	protected function groupToPrincipal($group) {
297
-		$groupId = $group->getGID();
298
-		// getDisplayName returns UID if none
299
-		$displayName = $group->getDisplayName();
300
-
301
-		return [
302
-			'uri' => 'principals/groups/' . urlencode($groupId),
303
-			'{DAV:}displayname' => $displayName,
304
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
305
-		];
306
-	}
307
-
308
-	/**
309
-	 * @param IUser $user
310
-	 * @return array
311
-	 */
312
-	protected function userToPrincipal($user) {
313
-		$userId = $user->getUID();
314
-		// getDisplayName returns UID if none
315
-		$displayName = $user->getDisplayName();
316
-
317
-		$principal = [
318
-			'uri' => 'principals/users/' . $userId,
319
-			'{DAV:}displayname' => $displayName,
320
-			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
321
-		];
322
-
323
-		$email = $user->getEMailAddress();
324
-		if (!empty($email)) {
325
-			$principal['{http://sabredav.org/ns}email-address'] = $email;
326
-		}
327
-
328
-		return $principal;
329
-	}
40
+    const PRINCIPAL_PREFIX = 'principals/groups';
41
+
42
+    /** @var IGroupManager */
43
+    private $groupManager;
44
+
45
+    /** @var IUserSession */
46
+    private $userSession;
47
+
48
+    /** @var IShareManager */
49
+    private $shareManager;
50
+
51
+    /**
52
+     * @param IGroupManager $IGroupManager
53
+     * @param IUserSession $userSession
54
+     * @param IShareManager $shareManager
55
+     */
56
+    public function __construct(IGroupManager $IGroupManager,
57
+                                IUserSession $userSession,
58
+                                IShareManager $shareManager) {
59
+        $this->groupManager = $IGroupManager;
60
+        $this->userSession = $userSession;
61
+        $this->shareManager = $shareManager;
62
+    }
63
+
64
+    /**
65
+     * Returns a list of principals based on a prefix.
66
+     *
67
+     * This prefix will often contain something like 'principals'. You are only
68
+     * expected to return principals that are in this base path.
69
+     *
70
+     * You are expected to return at least a 'uri' for every user, you can
71
+     * return any additional properties if you wish so. Common properties are:
72
+     *   {DAV:}displayname
73
+     *
74
+     * @param string $prefixPath
75
+     * @return string[]
76
+     */
77
+    public function getPrincipalsByPrefix($prefixPath) {
78
+        $principals = [];
79
+
80
+        if ($prefixPath === self::PRINCIPAL_PREFIX) {
81
+            foreach($this->groupManager->search('') as $user) {
82
+                $principals[] = $this->groupToPrincipal($user);
83
+            }
84
+        }
85
+
86
+        return $principals;
87
+    }
88
+
89
+    /**
90
+     * Returns a specific principal, specified by it's path.
91
+     * The returned structure should be the exact same as from
92
+     * getPrincipalsByPrefix.
93
+     *
94
+     * @param string $path
95
+     * @return array
96
+     */
97
+    public function getPrincipalByPath($path) {
98
+        $elements = explode('/', $path,  3);
99
+        if ($elements[0] !== 'principals') {
100
+            return null;
101
+        }
102
+        if ($elements[1] !== 'groups') {
103
+            return null;
104
+        }
105
+        $name = urldecode($elements[2]);
106
+        $group = $this->groupManager->get($name);
107
+
108
+        if (!is_null($group)) {
109
+            return $this->groupToPrincipal($group);
110
+        }
111
+
112
+        return null;
113
+    }
114
+
115
+    /**
116
+     * Returns the list of members for a group-principal
117
+     *
118
+     * @param string $principal
119
+     * @return string[]
120
+     * @throws Exception
121
+     */
122
+    public function getGroupMemberSet($principal) {
123
+        $elements = explode('/', $principal);
124
+        if ($elements[0] !== 'principals') {
125
+            return [];
126
+        }
127
+        if ($elements[1] !== 'groups') {
128
+            return [];
129
+        }
130
+        $name = $elements[2];
131
+        $group = $this->groupManager->get($name);
132
+
133
+        if (is_null($group)) {
134
+            return [];
135
+        }
136
+
137
+        return array_map(function ($user) {
138
+            return $this->userToPrincipal($user);
139
+        }, $group->getUsers());
140
+    }
141
+
142
+    /**
143
+     * Returns the list of groups a principal is a member of
144
+     *
145
+     * @param string $principal
146
+     * @return array
147
+     * @throws Exception
148
+     */
149
+    public function getGroupMembership($principal) {
150
+        return [];
151
+    }
152
+
153
+    /**
154
+     * Updates the list of group members for a group principal.
155
+     *
156
+     * The principals should be passed as a list of uri's.
157
+     *
158
+     * @param string $principal
159
+     * @param string[] $members
160
+     * @throws Exception
161
+     */
162
+    public function setGroupMemberSet($principal, array $members) {
163
+        throw new Exception('Setting members of the group is not supported yet');
164
+    }
165
+
166
+    /**
167
+     * @param string $path
168
+     * @param PropPatch $propPatch
169
+     * @return int
170
+     */
171
+    function updatePrincipal($path, PropPatch $propPatch) {
172
+        return 0;
173
+    }
174
+
175
+    /**
176
+     * @param string $prefixPath
177
+     * @param array $searchProperties
178
+     * @param string $test
179
+     * @return array
180
+     */
181
+    function searchPrincipals($prefixPath, array $searchProperties, $test = 'allof') {
182
+        $results = [];
183
+
184
+        if (\count($searchProperties) === 0) {
185
+            return [];
186
+        }
187
+        if ($prefixPath !== self::PRINCIPAL_PREFIX) {
188
+            return [];
189
+        }
190
+        // If sharing is disabled, return the empty array
191
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
192
+        if (!$shareAPIEnabled) {
193
+            return [];
194
+        }
195
+
196
+        // If sharing is restricted to group members only,
197
+        // return only members that have groups in common
198
+        $restrictGroups = false;
199
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
200
+            $user = $this->userSession->getUser();
201
+            if (!$user) {
202
+                return [];
203
+            }
204
+
205
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
206
+        }
207
+
208
+        foreach ($searchProperties as $prop => $value) {
209
+            switch ($prop) {
210
+                case '{DAV:}displayname':
211
+                    $groups = $this->groupManager->search($value);
212
+
213
+                    $results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) {
214
+                        $gid = $group->getGID();
215
+                        // is sharing restricted to groups only?
216
+                        if ($restrictGroups !== false) {
217
+                            if (!\in_array($gid, $restrictGroups, true)) {
218
+                                return $carry;
219
+                            }
220
+                        }
221
+
222
+                        $carry[] = self::PRINCIPAL_PREFIX . '/' . $gid;
223
+                        return $carry;
224
+                    }, []);
225
+                    break;
226
+
227
+                case '{urn:ietf:params:xml:ns:caldav}calendar-user-address-set':
228
+                    // If you add support for more search properties that qualify as a user-address,
229
+                    // please also add them to the array below
230
+                    $results[] = $this->searchPrincipals(self::PRINCIPAL_PREFIX, [
231
+                    ], 'anyof');
232
+                    break;
233
+
234
+                default:
235
+                    $results[] = [];
236
+                    break;
237
+            }
238
+        }
239
+
240
+        // results is an array of arrays, so this is not the first search result
241
+        // but the results of the first searchProperty
242
+        if (count($results) === 1) {
243
+            return $results[0];
244
+        }
245
+
246
+        switch ($test) {
247
+            case 'anyof':
248
+                return array_values(array_unique(array_merge(...$results)));
249
+
250
+            case 'allof':
251
+            default:
252
+                return array_values(array_intersect(...$results));
253
+        }
254
+    }
255
+
256
+    /**
257
+     * @param string $uri
258
+     * @param string $principalPrefix
259
+     * @return string
260
+     */
261
+    function findByUri($uri, $principalPrefix) {
262
+        // If sharing is disabled, return the empty array
263
+        $shareAPIEnabled = $this->shareManager->shareApiEnabled();
264
+        if (!$shareAPIEnabled) {
265
+            return null;
266
+        }
267
+
268
+        // If sharing is restricted to group members only,
269
+        // return only members that have groups in common
270
+        $restrictGroups = false;
271
+        if ($this->shareManager->shareWithGroupMembersOnly()) {
272
+            $user = $this->userSession->getUser();
273
+            if (!$user) {
274
+                return null;
275
+            }
276
+
277
+            $restrictGroups = $this->groupManager->getUserGroupIds($user);
278
+        }
279
+
280
+        if (strpos($uri, 'principal:principals/groups/') === 0) {
281
+            $name = urlencode(substr($uri, 28));
282
+            if ($restrictGroups !== false && !\in_array($name, $restrictGroups, true)) {
283
+                return null;
284
+            }
285
+
286
+            return substr($uri, 10);
287
+        }
288
+
289
+        return null;
290
+    }
291
+
292
+    /**
293
+     * @param IGroup $group
294
+     * @return array
295
+     */
296
+    protected function groupToPrincipal($group) {
297
+        $groupId = $group->getGID();
298
+        // getDisplayName returns UID if none
299
+        $displayName = $group->getDisplayName();
300
+
301
+        return [
302
+            'uri' => 'principals/groups/' . urlencode($groupId),
303
+            '{DAV:}displayname' => $displayName,
304
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
305
+        ];
306
+    }
307
+
308
+    /**
309
+     * @param IUser $user
310
+     * @return array
311
+     */
312
+    protected function userToPrincipal($user) {
313
+        $userId = $user->getUID();
314
+        // getDisplayName returns UID if none
315
+        $displayName = $user->getDisplayName();
316
+
317
+        $principal = [
318
+            'uri' => 'principals/users/' . $userId,
319
+            '{DAV:}displayname' => $displayName,
320
+            '{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
321
+        ];
322
+
323
+        $email = $user->getEMailAddress();
324
+        if (!empty($email)) {
325
+            $principal['{http://sabredav.org/ns}email-address'] = $email;
326
+        }
327
+
328
+        return $principal;
329
+    }
330 330
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
 		$principals = [];
79 79
 
80 80
 		if ($prefixPath === self::PRINCIPAL_PREFIX) {
81
-			foreach($this->groupManager->search('') as $user) {
81
+			foreach ($this->groupManager->search('') as $user) {
82 82
 				$principals[] = $this->groupToPrincipal($user);
83 83
 			}
84 84
 		}
@@ -95,7 +95,7 @@  discard block
 block discarded – undo
95 95
 	 * @return array
96 96
 	 */
97 97
 	public function getPrincipalByPath($path) {
98
-		$elements = explode('/', $path,  3);
98
+		$elements = explode('/', $path, 3);
99 99
 		if ($elements[0] !== 'principals') {
100 100
 			return null;
101 101
 		}
@@ -134,7 +134,7 @@  discard block
 block discarded – undo
134 134
 			return [];
135 135
 		}
136 136
 
137
-		return array_map(function ($user) {
137
+		return array_map(function($user) {
138 138
 			return $this->userToPrincipal($user);
139 139
 		}, $group->getUsers());
140 140
 	}
@@ -210,7 +210,7 @@  discard block
 block discarded – undo
210 210
 				case '{DAV:}displayname':
211 211
 					$groups = $this->groupManager->search($value);
212 212
 
213
-					$results[] = array_reduce($groups, function (array $carry, IGroup $group) use ($restrictGroups) {
213
+					$results[] = array_reduce($groups, function(array $carry, IGroup $group) use ($restrictGroups) {
214 214
 						$gid = $group->getGID();
215 215
 						// is sharing restricted to groups only?
216 216
 						if ($restrictGroups !== false) {
@@ -219,7 +219,7 @@  discard block
 block discarded – undo
219 219
 							}
220 220
 						}
221 221
 
222
-						$carry[] = self::PRINCIPAL_PREFIX . '/' . $gid;
222
+						$carry[] = self::PRINCIPAL_PREFIX.'/'.$gid;
223 223
 						return $carry;
224 224
 					}, []);
225 225
 					break;
@@ -299,7 +299,7 @@  discard block
 block discarded – undo
299 299
 		$displayName = $group->getDisplayName();
300 300
 
301 301
 		return [
302
-			'uri' => 'principals/groups/' . urlencode($groupId),
302
+			'uri' => 'principals/groups/'.urlencode($groupId),
303 303
 			'{DAV:}displayname' => $displayName,
304 304
 			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'GROUP',
305 305
 		];
@@ -315,7 +315,7 @@  discard block
 block discarded – undo
315 315
 		$displayName = $user->getDisplayName();
316 316
 
317 317
 		$principal = [
318
-			'uri' => 'principals/users/' . $userId,
318
+			'uri' => 'principals/users/'.$userId,
319 319
 			'{DAV:}displayname' => $displayName,
320 320
 			'{urn:ietf:params:xml:ns:caldav}calendar-user-type' => 'INDIVIDUAL',
321 321
 		];
Please login to merge, or discard this patch.
apps/dav/lib/DAV/Sharing/Plugin.php 2 patches
Indentation   +162 added lines, -162 removed lines patch added patch discarded remove patch
@@ -38,167 +38,167 @@
 block discarded – undo
38 38
 
39 39
 class Plugin extends ServerPlugin {
40 40
 
41
-	const NS_OWNCLOUD = 'http://owncloud.org/ns';
42
-	const NS_NEXTCLOUD = 'http://nextcloud.com/ns';
43
-
44
-	/** @var Auth */
45
-	private $auth;
46
-
47
-	/** @var IRequest */
48
-	private $request;
49
-
50
-	/**
51
-	 * Plugin constructor.
52
-	 *
53
-	 * @param Auth $authBackEnd
54
-	 * @param IRequest $request
55
-	 */
56
-	public function __construct(Auth $authBackEnd, IRequest $request) {
57
-		$this->auth = $authBackEnd;
58
-		$this->request = $request;
59
-	}
60
-
61
-	/**
62
-	 * Reference to SabreDAV server object.
63
-	 *
64
-	 * @var \Sabre\DAV\Server
65
-	 */
66
-	protected $server;
67
-
68
-	/**
69
-	 * This method should return a list of server-features.
70
-	 *
71
-	 * This is for example 'versioning' and is added to the DAV: header
72
-	 * in an OPTIONS response.
73
-	 *
74
-	 * @return string[]
75
-	 */
76
-	function getFeatures() {
77
-		return ['oc-resource-sharing'];
78
-	}
79
-
80
-	/**
81
-	 * Returns a plugin name.
82
-	 *
83
-	 * Using this name other plugins will be able to access other plugins
84
-	 * using Sabre\DAV\Server::getPlugin
85
-	 *
86
-	 * @return string
87
-	 */
88
-	function getPluginName() {
89
-		return 'oc-resource-sharing';
90
-	}
91
-
92
-	/**
93
-	 * This initializes the plugin.
94
-	 *
95
-	 * This function is called by Sabre\DAV\Server, after
96
-	 * addPlugin is called.
97
-	 *
98
-	 * This method should set up the required event subscriptions.
99
-	 *
100
-	 * @param Server $server
101
-	 * @return void
102
-	 */
103
-	function initialize(Server $server) {
104
-		$this->server = $server;
105
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = ShareRequest::class;
106
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = Invite::class;
107
-
108
-		$this->server->on('method:POST', [$this, 'httpPost']);
109
-		$this->server->on('propFind',    [$this, 'propFind']);
110
-	}
111
-
112
-	/**
113
-	 * We intercept this to handle POST requests on a dav resource.
114
-	 *
115
-	 * @param RequestInterface $request
116
-	 * @param ResponseInterface $response
117
-	 * @return null|false
118
-	 */
119
-	function httpPost(RequestInterface $request, ResponseInterface $response) {
120
-
121
-		$path = $request->getPath();
122
-
123
-		// Only handling xml
124
-		$contentType = $request->getHeader('Content-Type');
125
-		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
126
-			return;
127
-
128
-		// Making sure the node exists
129
-		try {
130
-			$node = $this->server->tree->getNodeForPath($path);
131
-		} catch (NotFound $e) {
132
-			return;
133
-		}
134
-
135
-		$requestBody = $request->getBodyAsString();
136
-
137
-		// If this request handler could not deal with this POST request, it
138
-		// will return 'null' and other plugins get a chance to handle the
139
-		// request.
140
-		//
141
-		// However, we already requested the full body. This is a problem,
142
-		// because a body can only be read once. This is why we preemptively
143
-		// re-populated the request body with the existing data.
144
-		$request->setBody($requestBody);
145
-
146
-		$message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
147
-
148
-		switch ($documentType) {
149
-
150
-			// Dealing with the 'share' document, which modified invitees on a
151
-			// calendar.
152
-			case '{' . self::NS_OWNCLOUD . '}share' :
153
-
154
-				// We can only deal with IShareableCalendar objects
155
-				if (!$node instanceof IShareable) {
156
-					return;
157
-				}
158
-
159
-				$this->server->transactionType = 'post-oc-resource-share';
160
-
161
-				// Getting ACL info
162
-				$acl = $this->server->getPlugin('acl');
163
-
164
-				// If there's no ACL support, we allow everything
165
-				if ($acl) {
166
-					/** @var \Sabre\DAVACL\Plugin $acl */
167
-					$acl->checkPrivileges($path, '{DAV:}write');
168
-				}
169
-
170
-				$node->updateShares($message->set, $message->remove);
171
-
172
-				$response->setStatus(200);
173
-				// Adding this because sending a response body may cause issues,
174
-				// and I wanted some type of indicator the response was handled.
175
-				$response->setHeader('X-Sabre-Status', 'everything-went-well');
176
-
177
-				// Breaking the event chain
178
-				return false;
179
-		}
180
-	}
181
-
182
-	/**
183
-	 * This event is triggered when properties are requested for a certain
184
-	 * node.
185
-	 *
186
-	 * This allows us to inject any properties early.
187
-	 *
188
-	 * @param PropFind $propFind
189
-	 * @param INode $node
190
-	 * @return void
191
-	 */
192
-	function propFind(PropFind $propFind, INode $node) {
193
-		if ($node instanceof IShareable) {
194
-
195
-			$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
196
-				return new Invite(
197
-					$node->getShares()
198
-				);
199
-			});
200
-
201
-		}
202
-	}
41
+    const NS_OWNCLOUD = 'http://owncloud.org/ns';
42
+    const NS_NEXTCLOUD = 'http://nextcloud.com/ns';
43
+
44
+    /** @var Auth */
45
+    private $auth;
46
+
47
+    /** @var IRequest */
48
+    private $request;
49
+
50
+    /**
51
+     * Plugin constructor.
52
+     *
53
+     * @param Auth $authBackEnd
54
+     * @param IRequest $request
55
+     */
56
+    public function __construct(Auth $authBackEnd, IRequest $request) {
57
+        $this->auth = $authBackEnd;
58
+        $this->request = $request;
59
+    }
60
+
61
+    /**
62
+     * Reference to SabreDAV server object.
63
+     *
64
+     * @var \Sabre\DAV\Server
65
+     */
66
+    protected $server;
67
+
68
+    /**
69
+     * This method should return a list of server-features.
70
+     *
71
+     * This is for example 'versioning' and is added to the DAV: header
72
+     * in an OPTIONS response.
73
+     *
74
+     * @return string[]
75
+     */
76
+    function getFeatures() {
77
+        return ['oc-resource-sharing'];
78
+    }
79
+
80
+    /**
81
+     * Returns a plugin name.
82
+     *
83
+     * Using this name other plugins will be able to access other plugins
84
+     * using Sabre\DAV\Server::getPlugin
85
+     *
86
+     * @return string
87
+     */
88
+    function getPluginName() {
89
+        return 'oc-resource-sharing';
90
+    }
91
+
92
+    /**
93
+     * This initializes the plugin.
94
+     *
95
+     * This function is called by Sabre\DAV\Server, after
96
+     * addPlugin is called.
97
+     *
98
+     * This method should set up the required event subscriptions.
99
+     *
100
+     * @param Server $server
101
+     * @return void
102
+     */
103
+    function initialize(Server $server) {
104
+        $this->server = $server;
105
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = ShareRequest::class;
106
+        $this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = Invite::class;
107
+
108
+        $this->server->on('method:POST', [$this, 'httpPost']);
109
+        $this->server->on('propFind',    [$this, 'propFind']);
110
+    }
111
+
112
+    /**
113
+     * We intercept this to handle POST requests on a dav resource.
114
+     *
115
+     * @param RequestInterface $request
116
+     * @param ResponseInterface $response
117
+     * @return null|false
118
+     */
119
+    function httpPost(RequestInterface $request, ResponseInterface $response) {
120
+
121
+        $path = $request->getPath();
122
+
123
+        // Only handling xml
124
+        $contentType = $request->getHeader('Content-Type');
125
+        if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false)
126
+            return;
127
+
128
+        // Making sure the node exists
129
+        try {
130
+            $node = $this->server->tree->getNodeForPath($path);
131
+        } catch (NotFound $e) {
132
+            return;
133
+        }
134
+
135
+        $requestBody = $request->getBodyAsString();
136
+
137
+        // If this request handler could not deal with this POST request, it
138
+        // will return 'null' and other plugins get a chance to handle the
139
+        // request.
140
+        //
141
+        // However, we already requested the full body. This is a problem,
142
+        // because a body can only be read once. This is why we preemptively
143
+        // re-populated the request body with the existing data.
144
+        $request->setBody($requestBody);
145
+
146
+        $message = $this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
147
+
148
+        switch ($documentType) {
149
+
150
+            // Dealing with the 'share' document, which modified invitees on a
151
+            // calendar.
152
+            case '{' . self::NS_OWNCLOUD . '}share' :
153
+
154
+                // We can only deal with IShareableCalendar objects
155
+                if (!$node instanceof IShareable) {
156
+                    return;
157
+                }
158
+
159
+                $this->server->transactionType = 'post-oc-resource-share';
160
+
161
+                // Getting ACL info
162
+                $acl = $this->server->getPlugin('acl');
163
+
164
+                // If there's no ACL support, we allow everything
165
+                if ($acl) {
166
+                    /** @var \Sabre\DAVACL\Plugin $acl */
167
+                    $acl->checkPrivileges($path, '{DAV:}write');
168
+                }
169
+
170
+                $node->updateShares($message->set, $message->remove);
171
+
172
+                $response->setStatus(200);
173
+                // Adding this because sending a response body may cause issues,
174
+                // and I wanted some type of indicator the response was handled.
175
+                $response->setHeader('X-Sabre-Status', 'everything-went-well');
176
+
177
+                // Breaking the event chain
178
+                return false;
179
+        }
180
+    }
181
+
182
+    /**
183
+     * This event is triggered when properties are requested for a certain
184
+     * node.
185
+     *
186
+     * This allows us to inject any properties early.
187
+     *
188
+     * @param PropFind $propFind
189
+     * @param INode $node
190
+     * @return void
191
+     */
192
+    function propFind(PropFind $propFind, INode $node) {
193
+        if ($node instanceof IShareable) {
194
+
195
+            $propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
196
+                return new Invite(
197
+                    $node->getShares()
198
+                );
199
+            });
200
+
201
+        }
202
+    }
203 203
 
204 204
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -102,11 +102,11 @@  discard block
 block discarded – undo
102 102
 	 */
103 103
 	function initialize(Server $server) {
104 104
 		$this->server = $server;
105
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}share'] = ShareRequest::class;
106
-		$this->server->xml->elementMap['{' . Plugin::NS_OWNCLOUD . '}invite'] = Invite::class;
105
+		$this->server->xml->elementMap['{'.Plugin::NS_OWNCLOUD.'}share'] = ShareRequest::class;
106
+		$this->server->xml->elementMap['{'.Plugin::NS_OWNCLOUD.'}invite'] = Invite::class;
107 107
 
108 108
 		$this->server->on('method:POST', [$this, 'httpPost']);
109
-		$this->server->on('propFind',    [$this, 'propFind']);
109
+		$this->server->on('propFind', [$this, 'propFind']);
110 110
 	}
111 111
 
112 112
 	/**
@@ -149,7 +149,7 @@  discard block
 block discarded – undo
149 149
 
150 150
 			// Dealing with the 'share' document, which modified invitees on a
151 151
 			// calendar.
152
-			case '{' . self::NS_OWNCLOUD . '}share' :
152
+			case '{'.self::NS_OWNCLOUD.'}share' :
153 153
 
154 154
 				// We can only deal with IShareableCalendar objects
155 155
 				if (!$node instanceof IShareable) {
@@ -192,7 +192,7 @@  discard block
 block discarded – undo
192 192
 	function propFind(PropFind $propFind, INode $node) {
193 193
 		if ($node instanceof IShareable) {
194 194
 
195
-			$propFind->handle('{' . Plugin::NS_OWNCLOUD . '}invite', function () use ($node) {
195
+			$propFind->handle('{'.Plugin::NS_OWNCLOUD.'}invite', function() use ($node) {
196 196
 				return new Invite(
197 197
 					$node->getShares()
198 198
 				);
Please login to merge, or discard this patch.