Completed
Push — master ( 883df4...959368 )
by Thomas
46s
created

PreviewPlugin::initialize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @author Thomas Müller <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2017, ownCloud GmbH
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace OCA\DAV\Files;
23
24
use OCP\Files\ForbiddenException;
25
use OCP\Files\IPreviewNode;
26
use OCP\ILogger;
27
use Sabre\DAV\Exception\NotFound;
28
use Sabre\DAV\Server;
29
use Sabre\DAV\ServerPlugin;
30
use Sabre\HTTP\RequestInterface;
31
use Sabre\HTTP\ResponseInterface;
32
use OCA\DAV\Connector\Sabre\Exception\Forbidden as DAVForbiddenException;
33
34
class PreviewPlugin extends ServerPlugin {
35
36
	/** @var Server */
37
	protected $server;
38
	/** @var ILogger */
39
	private $logger;
40
41
	public function __construct(ILogger $logger) {
42
		$this->logger = $logger;
43
	}
44
45
	/**
46
	 * Initializes the plugin and registers event handlers
47
	 *
48
	 * @param Server $server
49
	 * @return void
50
	 */
51
	function initialize(Server $server) {
52
53
		$this->server = $server;
54
		$this->server->on('method:GET', [$this, 'httpGet'], 90);
55
	}
56
57
	/**
58
	 * Intercepts GET requests on node urls ending with ?preview.
59
	 * The node has to implement IPreviewNode
60
	 *
61
	 * @param RequestInterface $request
62
	 * @param ResponseInterface $response
63
	 * @return bool
64
	 * @throws NotFound
65
	 * @throws \Sabre\DAVACL\Exception\NeedPrivileges
66
	 * @throws \Sabre\DAV\Exception\NotAuthenticated
67
	 */
68
	function httpGet(RequestInterface $request, ResponseInterface $response) {
69
70
		$queryParams = $request->getQueryParameters();
71
		if (!array_key_exists('preview', $queryParams)) {
72
			return true;
73
		}
74
75
		$path = $request->getPath();
76
		$node = $this->server->tree->getNodeForPath($path);
77
78
		if (!$node instanceof IFileNode) {
79
			return false;
80
		}
81
		$fileNode = $node->getNode();
82
		if (!$fileNode instanceof IPreviewNode) {
83
			return false;
84
		}
85
86
		// Checking ACL, if available.
87
		if ($aclPlugin = $this->server->getPlugin('acl')) {
88
			/** @var \Sabre\DAVACL\Plugin $aclPlugin */
89
			$aclPlugin->checkPrivileges($path, '{DAV:}read');
90
		}
91
92
		try {
93
			$image = $fileNode->getThumbnail($queryParams);
94
		} catch (ForbiddenException $ex) {
95
			throw new DAVForbiddenException($ex->getMessage(), $ex->getRetry());
96
		}
97
		if ($image) {
98
			if ($image === null || !$image->valid()) {
99
				throw new NotFound();
100
			}
101
			$type = $image->mimeType();
102
			if (!in_array($type, ['image/png', 'image/jpeg', 'image/gif'])) {
103
				$type = 'application/octet-stream';
104
			}
105
106
			// Enable output buffering
107
			ob_start();
108
			// Capture the output
109
			$image->show();
110
			$imageData = ob_get_contents();
111
			// Clear the output buffer
112
			ob_end_clean();
113
114
			$response->setHeader('Content-Type', $type);
115
			$response->setHeader('Content-Disposition', 'attachment');
116
			// cache 24h
117
			$response->setHeader('Cache-Control', 'max-age=86400, must-revalidate');
118
			$response->setHeader('Expires', gmdate ("D, d M Y H:i:s", time() + 86400) . " GMT");
119
120
			$response->setStatus(200);
121
			$response->setBody($imageData);
122
123
			// Returning false to break the event chain
124
			return false;
125
		}
126
		// TODO: add forceIcon handling .... if still needed
127
		throw new NotFound();
128
	}
129
}
130