Completed
Push — master ( a9b811...8eff65 )
by
unknown
32:34
created
apps/dav/lib/Connector/Sabre/QuotaPlugin.php 1 patch
Indentation   +235 added lines, -235 removed lines patch added patch discarded remove patch
@@ -26,239 +26,239 @@
 block discarded – undo
26 26
  * @license http://code.google.com/p/sabredav/wiki/License Modified BSD License
27 27
  */
28 28
 class QuotaPlugin extends \Sabre\DAV\ServerPlugin {
29
-	/**
30
-	 * Reference to main server object
31
-	 *
32
-	 * @var \Sabre\DAV\Server
33
-	 */
34
-	private $server;
35
-
36
-	/**
37
-	 * @param View $view
38
-	 */
39
-	public function __construct(
40
-		private $view,
41
-	) {
42
-	}
43
-
44
-	/**
45
-	 * This initializes the plugin.
46
-	 *
47
-	 * This function is called by \Sabre\DAV\Server, after
48
-	 * addPlugin is called.
49
-	 *
50
-	 * This method should set up the requires event subscriptions.
51
-	 *
52
-	 * @param \Sabre\DAV\Server $server
53
-	 * @return void
54
-	 */
55
-	public function initialize(\Sabre\DAV\Server $server) {
56
-		$this->server = $server;
57
-
58
-		$server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
59
-		$server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
60
-		$server->on('method:MKCOL', [$this, 'onCreateCollection'], 30);
61
-		$server->on('beforeMove', [$this, 'beforeMove'], 10);
62
-		$server->on('beforeCopy', [$this, 'beforeCopy'], 10);
63
-	}
64
-
65
-	/**
66
-	 * Check quota before creating file
67
-	 *
68
-	 * @param string $uri target file URI
69
-	 * @param resource $data data
70
-	 * @param INode $parent Sabre Node
71
-	 * @param bool $modified modified
72
-	 */
73
-	public function beforeCreateFile($uri, $data, INode $parent, $modified) {
74
-		$request = $this->server->httpRequest;
75
-		if ($parent instanceof UploadFolder && $request->getHeader('Destination')) {
76
-			// If chunked upload and Total-Length header is set, use that
77
-			// value for quota check. This allows us to also check quota while
78
-			// uploading chunks and not only when the file is assembled.
79
-			$length = $request->getHeader('OC-Total-Length');
80
-			$destinationPath = $this->server->calculateUri($request->getHeader('Destination'));
81
-			$quotaPath = $this->getPathForDestination($destinationPath);
82
-			if ($quotaPath && is_numeric($length)) {
83
-				return $this->checkQuota($quotaPath, (int)$length);
84
-			}
85
-		}
86
-
87
-		if (!$parent instanceof Node) {
88
-			return;
89
-		}
90
-
91
-		return $this->checkQuota($parent->getPath() . '/' . basename($uri));
92
-	}
93
-
94
-	/**
95
-	 * Check quota before creating directory
96
-	 *
97
-	 * @param RequestInterface $request
98
-	 * @param ResponseInterface $response
99
-	 * @return bool
100
-	 * @throws InsufficientStorage
101
-	 * @throws \Sabre\DAV\Exception\Forbidden
102
-	 */
103
-	public function onCreateCollection(RequestInterface $request, ResponseInterface $response): bool {
104
-		try {
105
-			$destinationPath = $this->server->calculateUri($request->getUrl());
106
-			$quotaPath = $this->getPathForDestination($destinationPath);
107
-		} catch (\Exception $e) {
108
-			return true;
109
-		}
110
-		if ($quotaPath) {
111
-			// MKCOL does not have a Content-Length header, so we can use
112
-			// a fixed value for the quota check.
113
-			return $this->checkQuota($quotaPath, 4096, true);
114
-		}
115
-
116
-		return true;
117
-	}
118
-
119
-	/**
120
-	 * Check quota before writing content
121
-	 *
122
-	 * @param string $uri target file URI
123
-	 * @param INode $node Sabre Node
124
-	 * @param resource $data data
125
-	 * @param bool $modified modified
126
-	 */
127
-	public function beforeWriteContent($uri, INode $node, $data, $modified) {
128
-		if (!$node instanceof Node) {
129
-			return;
130
-		}
131
-
132
-		return $this->checkQuota($node->getPath());
133
-	}
134
-
135
-	/**
136
-	 * Check if we're moving a FutureFile in which case we need to check
137
-	 * the quota on the target destination.
138
-	 */
139
-	public function beforeMove(string $sourcePath, string $destinationPath): bool {
140
-		$sourceNode = $this->server->tree->getNodeForPath($sourcePath);
141
-		if (!$sourceNode instanceof IFile) {
142
-			return true;
143
-		}
144
-
145
-		try {
146
-			// The final path is not known yet, we check the quota on the parent
147
-			$path = $this->getPathForDestination($destinationPath);
148
-		} catch (\Exception $e) {
149
-			return true;
150
-		}
151
-
152
-		return $this->checkQuota($path, $sourceNode->getSize());
153
-	}
154
-
155
-	/**
156
-	 * Check quota on the target destination before a copy.
157
-	 */
158
-	public function beforeCopy(string $sourcePath, string $destinationPath): bool {
159
-		$sourceNode = $this->server->tree->getNodeForPath($sourcePath);
160
-		if (!$sourceNode instanceof Node) {
161
-			return true;
162
-		}
163
-
164
-		try {
165
-			$path = $this->getPathForDestination($destinationPath);
166
-		} catch (\Exception $e) {
167
-			return true;
168
-		}
169
-
170
-		return $this->checkQuota($path, $sourceNode->getSize());
171
-	}
172
-
173
-	private function getPathForDestination(string $destinationPath): string {
174
-		// get target node for proper path conversion
175
-		if ($this->server->tree->nodeExists($destinationPath)) {
176
-			$destinationNode = $this->server->tree->getNodeForPath($destinationPath);
177
-			if (!$destinationNode instanceof Node) {
178
-				throw new \Exception('Invalid destination node');
179
-			}
180
-			return $destinationNode->getPath();
181
-		}
182
-
183
-		$parent = dirname($destinationPath);
184
-		if ($parent === '.') {
185
-			$parent = '';
186
-		}
187
-
188
-		$parentNode = $this->server->tree->getNodeForPath($parent);
189
-		if (!$parentNode instanceof Node) {
190
-			throw new \Exception('Invalid destination node');
191
-		}
192
-
193
-		return $parentNode->getPath();
194
-	}
195
-
196
-
197
-	/**
198
-	 * This method is called before any HTTP method and validates there is enough free space to store the file
199
-	 *
200
-	 * @param string $path relative to the users home
201
-	 * @param int|float|null $length
202
-	 * @throws InsufficientStorage
203
-	 * @return bool
204
-	 */
205
-	public function checkQuota(string $path, $length = null, $isDir = false) {
206
-		if ($length === null) {
207
-			$length = $this->getLength();
208
-		}
209
-
210
-		if ($length) {
211
-			[$parentPath, $newName] = \Sabre\Uri\split($path);
212
-			if (is_null($parentPath)) {
213
-				$parentPath = '';
214
-			}
215
-			$req = $this->server->httpRequest;
216
-
217
-			// Strip any duplicate slashes
218
-			$path = str_replace('//', '/', $path);
219
-
220
-			$freeSpace = $this->getFreeSpace($path);
221
-			if ($freeSpace >= 0 && $length > $freeSpace) {
222
-				if ($isDir) {
223
-					throw new InsufficientStorage("Insufficient space in $path. $freeSpace available. Cannot create directory");
224
-				}
225
-
226
-				throw new InsufficientStorage("Insufficient space in $path, $length required, $freeSpace available");
227
-			}
228
-		}
229
-
230
-		return true;
231
-	}
232
-
233
-	public function getLength() {
234
-		$req = $this->server->httpRequest;
235
-		$length = $req->getHeader('X-Expected-Entity-Length');
236
-		if (!is_numeric($length)) {
237
-			$length = $req->getHeader('Content-Length');
238
-			$length = is_numeric($length) ? $length : null;
239
-		}
240
-
241
-		$ocLength = $req->getHeader('OC-Total-Length');
242
-		if (!is_numeric($ocLength)) {
243
-			return $length;
244
-		}
245
-		if (!is_numeric($length)) {
246
-			return $ocLength;
247
-		}
248
-		return max($length, $ocLength);
249
-	}
250
-
251
-	/**
252
-	 * @param string $uri
253
-	 * @return mixed
254
-	 * @throws ServiceUnavailable
255
-	 */
256
-	public function getFreeSpace($uri) {
257
-		try {
258
-			$freeSpace = $this->view->free_space(ltrim($uri, '/'));
259
-			return $freeSpace;
260
-		} catch (StorageNotAvailableException $e) {
261
-			throw new ServiceUnavailable($e->getMessage());
262
-		}
263
-	}
29
+    /**
30
+     * Reference to main server object
31
+     *
32
+     * @var \Sabre\DAV\Server
33
+     */
34
+    private $server;
35
+
36
+    /**
37
+     * @param View $view
38
+     */
39
+    public function __construct(
40
+        private $view,
41
+    ) {
42
+    }
43
+
44
+    /**
45
+     * This initializes the plugin.
46
+     *
47
+     * This function is called by \Sabre\DAV\Server, after
48
+     * addPlugin is called.
49
+     *
50
+     * This method should set up the requires event subscriptions.
51
+     *
52
+     * @param \Sabre\DAV\Server $server
53
+     * @return void
54
+     */
55
+    public function initialize(\Sabre\DAV\Server $server) {
56
+        $this->server = $server;
57
+
58
+        $server->on('beforeWriteContent', [$this, 'beforeWriteContent'], 10);
59
+        $server->on('beforeCreateFile', [$this, 'beforeCreateFile'], 10);
60
+        $server->on('method:MKCOL', [$this, 'onCreateCollection'], 30);
61
+        $server->on('beforeMove', [$this, 'beforeMove'], 10);
62
+        $server->on('beforeCopy', [$this, 'beforeCopy'], 10);
63
+    }
64
+
65
+    /**
66
+     * Check quota before creating file
67
+     *
68
+     * @param string $uri target file URI
69
+     * @param resource $data data
70
+     * @param INode $parent Sabre Node
71
+     * @param bool $modified modified
72
+     */
73
+    public function beforeCreateFile($uri, $data, INode $parent, $modified) {
74
+        $request = $this->server->httpRequest;
75
+        if ($parent instanceof UploadFolder && $request->getHeader('Destination')) {
76
+            // If chunked upload and Total-Length header is set, use that
77
+            // value for quota check. This allows us to also check quota while
78
+            // uploading chunks and not only when the file is assembled.
79
+            $length = $request->getHeader('OC-Total-Length');
80
+            $destinationPath = $this->server->calculateUri($request->getHeader('Destination'));
81
+            $quotaPath = $this->getPathForDestination($destinationPath);
82
+            if ($quotaPath && is_numeric($length)) {
83
+                return $this->checkQuota($quotaPath, (int)$length);
84
+            }
85
+        }
86
+
87
+        if (!$parent instanceof Node) {
88
+            return;
89
+        }
90
+
91
+        return $this->checkQuota($parent->getPath() . '/' . basename($uri));
92
+    }
93
+
94
+    /**
95
+     * Check quota before creating directory
96
+     *
97
+     * @param RequestInterface $request
98
+     * @param ResponseInterface $response
99
+     * @return bool
100
+     * @throws InsufficientStorage
101
+     * @throws \Sabre\DAV\Exception\Forbidden
102
+     */
103
+    public function onCreateCollection(RequestInterface $request, ResponseInterface $response): bool {
104
+        try {
105
+            $destinationPath = $this->server->calculateUri($request->getUrl());
106
+            $quotaPath = $this->getPathForDestination($destinationPath);
107
+        } catch (\Exception $e) {
108
+            return true;
109
+        }
110
+        if ($quotaPath) {
111
+            // MKCOL does not have a Content-Length header, so we can use
112
+            // a fixed value for the quota check.
113
+            return $this->checkQuota($quotaPath, 4096, true);
114
+        }
115
+
116
+        return true;
117
+    }
118
+
119
+    /**
120
+     * Check quota before writing content
121
+     *
122
+     * @param string $uri target file URI
123
+     * @param INode $node Sabre Node
124
+     * @param resource $data data
125
+     * @param bool $modified modified
126
+     */
127
+    public function beforeWriteContent($uri, INode $node, $data, $modified) {
128
+        if (!$node instanceof Node) {
129
+            return;
130
+        }
131
+
132
+        return $this->checkQuota($node->getPath());
133
+    }
134
+
135
+    /**
136
+     * Check if we're moving a FutureFile in which case we need to check
137
+     * the quota on the target destination.
138
+     */
139
+    public function beforeMove(string $sourcePath, string $destinationPath): bool {
140
+        $sourceNode = $this->server->tree->getNodeForPath($sourcePath);
141
+        if (!$sourceNode instanceof IFile) {
142
+            return true;
143
+        }
144
+
145
+        try {
146
+            // The final path is not known yet, we check the quota on the parent
147
+            $path = $this->getPathForDestination($destinationPath);
148
+        } catch (\Exception $e) {
149
+            return true;
150
+        }
151
+
152
+        return $this->checkQuota($path, $sourceNode->getSize());
153
+    }
154
+
155
+    /**
156
+     * Check quota on the target destination before a copy.
157
+     */
158
+    public function beforeCopy(string $sourcePath, string $destinationPath): bool {
159
+        $sourceNode = $this->server->tree->getNodeForPath($sourcePath);
160
+        if (!$sourceNode instanceof Node) {
161
+            return true;
162
+        }
163
+
164
+        try {
165
+            $path = $this->getPathForDestination($destinationPath);
166
+        } catch (\Exception $e) {
167
+            return true;
168
+        }
169
+
170
+        return $this->checkQuota($path, $sourceNode->getSize());
171
+    }
172
+
173
+    private function getPathForDestination(string $destinationPath): string {
174
+        // get target node for proper path conversion
175
+        if ($this->server->tree->nodeExists($destinationPath)) {
176
+            $destinationNode = $this->server->tree->getNodeForPath($destinationPath);
177
+            if (!$destinationNode instanceof Node) {
178
+                throw new \Exception('Invalid destination node');
179
+            }
180
+            return $destinationNode->getPath();
181
+        }
182
+
183
+        $parent = dirname($destinationPath);
184
+        if ($parent === '.') {
185
+            $parent = '';
186
+        }
187
+
188
+        $parentNode = $this->server->tree->getNodeForPath($parent);
189
+        if (!$parentNode instanceof Node) {
190
+            throw new \Exception('Invalid destination node');
191
+        }
192
+
193
+        return $parentNode->getPath();
194
+    }
195
+
196
+
197
+    /**
198
+     * This method is called before any HTTP method and validates there is enough free space to store the file
199
+     *
200
+     * @param string $path relative to the users home
201
+     * @param int|float|null $length
202
+     * @throws InsufficientStorage
203
+     * @return bool
204
+     */
205
+    public function checkQuota(string $path, $length = null, $isDir = false) {
206
+        if ($length === null) {
207
+            $length = $this->getLength();
208
+        }
209
+
210
+        if ($length) {
211
+            [$parentPath, $newName] = \Sabre\Uri\split($path);
212
+            if (is_null($parentPath)) {
213
+                $parentPath = '';
214
+            }
215
+            $req = $this->server->httpRequest;
216
+
217
+            // Strip any duplicate slashes
218
+            $path = str_replace('//', '/', $path);
219
+
220
+            $freeSpace = $this->getFreeSpace($path);
221
+            if ($freeSpace >= 0 && $length > $freeSpace) {
222
+                if ($isDir) {
223
+                    throw new InsufficientStorage("Insufficient space in $path. $freeSpace available. Cannot create directory");
224
+                }
225
+
226
+                throw new InsufficientStorage("Insufficient space in $path, $length required, $freeSpace available");
227
+            }
228
+        }
229
+
230
+        return true;
231
+    }
232
+
233
+    public function getLength() {
234
+        $req = $this->server->httpRequest;
235
+        $length = $req->getHeader('X-Expected-Entity-Length');
236
+        if (!is_numeric($length)) {
237
+            $length = $req->getHeader('Content-Length');
238
+            $length = is_numeric($length) ? $length : null;
239
+        }
240
+
241
+        $ocLength = $req->getHeader('OC-Total-Length');
242
+        if (!is_numeric($ocLength)) {
243
+            return $length;
244
+        }
245
+        if (!is_numeric($length)) {
246
+            return $ocLength;
247
+        }
248
+        return max($length, $ocLength);
249
+    }
250
+
251
+    /**
252
+     * @param string $uri
253
+     * @return mixed
254
+     * @throws ServiceUnavailable
255
+     */
256
+    public function getFreeSpace($uri) {
257
+        try {
258
+            $freeSpace = $this->view->free_space(ltrim($uri, '/'));
259
+            return $freeSpace;
260
+        } catch (StorageNotAvailableException $e) {
261
+            throw new ServiceUnavailable($e->getMessage());
262
+        }
263
+    }
264 264
 }
Please login to merge, or discard this patch.