Passed
Push — master ( 5cdc85...37718d )
by Morris
38:53 queued 21:57
created

PublishPlugin::getPluginName()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Thomas Citharel <[email protected]>
4
 *
5
 * @author Thomas Citharel <[email protected]>
6
 * @author Thomas Müller <[email protected]>
7
 *
8
 * @license GNU AGPL version 3 or any later version
9
 *
10
 * This program is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Affero General Public License as
12
 * published by the Free Software Foundation, either version 3 of the
13
 * License, or (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU Affero General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU Affero General Public License
21
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
namespace OCA\DAV\CalDAV\Publishing;
25
26
use Sabre\DAV\PropFind;
27
use Sabre\DAV\INode;
28
use Sabre\DAV\Server;
29
use Sabre\DAV\ServerPlugin;
30
use Sabre\DAV\Exception\NotFound;
31
use Sabre\HTTP\RequestInterface;
32
use Sabre\HTTP\ResponseInterface;
33
use Sabre\CalDAV\Xml\Property\AllowedSharingModes;
34
use OCA\DAV\CalDAV\Publishing\Xml\Publisher;
35
use OCA\DAV\CalDAV\Calendar;
36
use OCP\IURLGenerator;
37
use OCP\IConfig;
38
39
class PublishPlugin extends ServerPlugin {
40
	const NS_CALENDARSERVER = 'http://calendarserver.org/ns/';
41
42
	/**
43
	 * Reference to SabreDAV server object.
44
	 *
45
	 * @var \Sabre\DAV\Server
46
	 */
47
	protected $server;
48
49
	/**
50
	 * Config instance to get instance secret.
51
	 *
52
	 * @var IConfig
53
	 */
54
	protected $config;
55
56
	/**
57
	 * URL Generator for absolute URLs.
58
	 *
59
	 * @var IURLGenerator
60
	 */
61
	protected $urlGenerator;
62
63
	/**
64
	 * PublishPlugin constructor.
65
	 *
66
	 * @param IConfig $config
67
	 * @param IURLGenerator $urlGenerator
68
	 */
69
	public function __construct(IConfig $config, IURLGenerator $urlGenerator) {
70
		$this->config = $config;
71
		$this->urlGenerator = $urlGenerator;
72
	}
73
74
	/**
75
	 * This method should return a list of server-features.
76
	 *
77
	 * This is for example 'versioning' and is added to the DAV: header
78
	 * in an OPTIONS response.
79
	 *
80
	 * @return string[]
81
	 */
82
	public function getFeatures() {
83
		// May have to be changed to be detected
84
		return ['oc-calendar-publishing', 'calendarserver-sharing'];
85
	}
86
87
	/**
88
	 * Returns a plugin name.
89
	 *
90
	 * Using this name other plugins will be able to access other plugins
91
	 * using Sabre\DAV\Server::getPlugin
92
	 *
93
	 * @return string
94
	 */
95
	public function getPluginName()	{
96
		return 'oc-calendar-publishing';
97
	}
98
99
	/**
100
	 * This initializes the plugin.
101
	 *
102
	 * This function is called by Sabre\DAV\Server, after
103
	 * addPlugin is called.
104
	 *
105
	 * This method should set up the required event subscriptions.
106
	 *
107
	 * @param Server $server
108
	 */
109
	public function initialize(Server $server) {
110
		$this->server = $server;
111
112
		$this->server->on('method:POST', [$this, 'httpPost']);
113
		$this->server->on('propFind',    [$this, 'propFind']);
114
	}
115
116
	public function propFind(PropFind $propFind, INode $node) {
117
		if ($node instanceof Calendar) {
118
			$propFind->handle('{'.self::NS_CALENDARSERVER.'}publish-url', function () use ($node) {
119
				if ($node->getPublishStatus()) {
120
					// We return the publish-url only if the calendar is published.
121
					$token = $node->getPublishStatus();
122
					$publishUrl = $this->urlGenerator->getAbsoluteURL($this->server->getBaseUri().'public-calendars/').$token;
123
124
					return new Publisher($publishUrl, true);
125
				}
126
			});
127
128
			$propFind->handle('{'.self::NS_CALENDARSERVER.'}allowed-sharing-modes', function() use ($node) {
129
				return new AllowedSharingModes(!$node->isSubscription(), !$node->isSubscription());
130
			});
131
		}
132
	}
133
134
	/**
135
	 * We intercept this to handle POST requests on calendars.
136
	 *
137
	 * @param RequestInterface $request
138
	 * @param ResponseInterface $response
139
	 *
140
	 * @return void|bool
141
	 */
142
	public function httpPost(RequestInterface $request, ResponseInterface $response) {
143
		$path = $request->getPath();
144
145
		// Only handling xml
146
		$contentType = $request->getHeader('Content-Type');
147
		if (strpos($contentType, 'application/xml') === false && strpos($contentType, 'text/xml') === false) {
148
			return;
149
		}
150
151
		// Making sure the node exists
152
		try {
153
			$node = $this->server->tree->getNodeForPath($path);
154
		} catch (NotFound $e) {
155
			return;
156
		}
157
158
		$requestBody = $request->getBodyAsString();
159
160
		// If this request handler could not deal with this POST request, it
161
		// will return 'null' and other plugins get a chance to handle the
162
		// request.
163
		//
164
		// However, we already requested the full body. This is a problem,
165
		// because a body can only be read once. This is why we preemptively
166
		// re-populated the request body with the existing data.
167
		$request->setBody($requestBody);
168
169
		$this->server->xml->parse($requestBody, $request->getUrl(), $documentType);
170
171
		switch ($documentType) {
172
173
			case '{'.self::NS_CALENDARSERVER.'}publish-calendar' :
174
175
			// We can only deal with IShareableCalendar objects
176
			if (!$node instanceof Calendar) {
177
				return;
178
			}
179
			$this->server->transactionType = 'post-publish-calendar';
180
181
			// Getting ACL info
182
			$acl = $this->server->getPlugin('acl');
183
184
			// If there's no ACL support, we allow everything
185
			if ($acl) {
0 ignored issues
show
introduced by
$acl is of type Sabre\DAV\ServerPlugin, thus it always evaluated to true.
Loading history...
186
				$acl->checkPrivileges($path, '{DAV:}write');
0 ignored issues
show
Bug introduced by
The method checkPrivileges() does not exist on Sabre\DAV\ServerPlugin. It seems like you code against a sub-type of Sabre\DAV\ServerPlugin such as Sabre\DAVACL\Plugin. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

186
				$acl->/** @scrutinizer ignore-call */ 
187
          checkPrivileges($path, '{DAV:}write');
Loading history...
187
			}
188
189
			$node->setPublishStatus(true);
190
191
			// iCloud sends back the 202, so we will too.
192
			$response->setStatus(202);
193
194
			// Adding this because sending a response body may cause issues,
195
			// and I wanted some type of indicator the response was handled.
196
			$response->setHeader('X-Sabre-Status', 'everything-went-well');
197
198
			// Breaking the event chain
199
			return false;
200
201
			case '{'.self::NS_CALENDARSERVER.'}unpublish-calendar' :
202
203
			// We can only deal with IShareableCalendar objects
204
			if (!$node instanceof Calendar) {
205
				return;
206
			}
207
			$this->server->transactionType = 'post-unpublish-calendar';
208
209
			// Getting ACL info
210
			$acl = $this->server->getPlugin('acl');
211
212
			// If there's no ACL support, we allow everything
213
			if ($acl) {
0 ignored issues
show
introduced by
$acl is of type Sabre\DAV\ServerPlugin, thus it always evaluated to true.
Loading history...
214
				$acl->checkPrivileges($path, '{DAV:}write');
215
			}
216
217
			$node->setPublishStatus(false);
218
219
			$response->setStatus(200);
220
221
			// Adding this because sending a response body may cause issues,
222
			// and I wanted some type of indicator the response was handled.
223
			$response->setHeader('X-Sabre-Status', 'everything-went-well');
224
225
			// Breaking the event chain
226
			return false;
227
228
		}
229
	}
230
}
231