Completed
Push — master ( 64a4da...21cb6b )
by Thomas
07:39
created

Server   C

Complexity

Total Complexity 10

Size/Duplication

Total Lines 177
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 44

Importance

Changes 3
Bugs 0 Features 0
Metric Value
dl 0
loc 177
rs 5
c 3
b 0
f 0
wmc 10
lcom 1
cbo 44

2 Methods

Rating   Name   Duplication   Size   Complexity  
D __construct() 0 167 9
A exec() 0 3 1
1
<?php
2
/**
3
 * @author Arthur Schiwon <[email protected]>
4
 * @author Christoph Wurst <[email protected]>
5
 * @author Georg Ehrke <[email protected]>
6
 * @author Lukas Reschke <[email protected]>
7
 * @author Roeland Jago Douma <[email protected]>
8
 * @author Thomas Müller <[email protected]>
9
 * @author Vincent Petry <[email protected]>
10
 *
11
 * @copyright Copyright (c) 2016, ownCloud GmbH.
12
 * @license AGPL-3.0
13
 *
14
 * This code is free software: you can redistribute it and/or modify
15
 * it under the terms of the GNU Affero General Public License, version 3,
16
 * as published by the Free Software Foundation.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21
 * GNU Affero General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU Affero General Public License, version 3,
24
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
25
 *
26
 */
27
namespace OCA\DAV;
28
29
use OCA\DAV\CalDAV\Schedule\IMipPlugin;
30
use OCA\DAV\CardDAV\ImageExportPlugin;
31
use OCA\DAV\Connector\Sabre\Auth;
32
use OCA\DAV\Connector\Sabre\BlockLegacyClientPlugin;
33
use OCA\DAV\Connector\Sabre\CommentPropertiesPlugin;
34
use OCA\DAV\Connector\Sabre\CopyEtagHeaderPlugin;
35
use OCA\DAV\Connector\Sabre\DavAclPlugin;
36
use OCA\DAV\Connector\Sabre\DummyGetResponsePlugin;
37
use OCA\DAV\Connector\Sabre\FakeLockerPlugin;
38
use OCA\DAV\Connector\Sabre\FilesPlugin;
39
use OCA\DAV\Connector\Sabre\FilesReportPlugin;
40
use OCA\DAV\Connector\Sabre\SharesPlugin;
41
use OCA\DAV\DAV\PublicAuth;
42
use OCA\DAV\Connector\Sabre\QuotaPlugin;
43
use OCA\DAV\Files\BrowserErrorPagePlugin;
44
use OCA\DAV\Files\CustomPropertiesBackend;
45
use OCA\DAV\SystemTag\SystemTagPlugin;
46
use OCP\IRequest;
47
use OCP\SabrePluginEvent;
48
use Sabre\CardDAV\VCFExportPlugin;
49
use Sabre\DAV\Auth\Plugin;
50
use OCA\DAV\Connector\Sabre\TagsPlugin;
51
use OCA\DAV\AppInfo\PluginManager;
52
53
class Server {
54
55
	/** @var IRequest */
56
	private $request;
57
58
	public function __construct(IRequest $request, $baseUri) {
59
		$this->request = $request;
60
		$this->baseUri = $baseUri;
0 ignored issues
show
Bug introduced by
The property baseUri does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
61
		$logger = \OC::$server->getLogger();
62
		$mailer = \OC::$server->getMailer();
63
		$dispatcher = \OC::$server->getEventDispatcher();
64
65
		$root = new RootCollection();
66
		$this->server = new \OCA\DAV\Connector\Sabre\Server($root);
0 ignored issues
show
Bug introduced by
The property server does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
67
68
		// Backends
69
		$authBackend = new Auth(
70
			\OC::$server->getSession(),
71
			\OC::$server->getUserSession(),
72
			\OC::$server->getRequest(),
73
			\OC::$server->getTwoFactorAuthManager()
74
		);
75
76
		// Set URL explicitly due to reverse-proxy situations
77
		$this->server->httpRequest->setUrl($this->request->getRequestUri());
78
		$this->server->setBaseUri($this->baseUri);
79
80
		$this->server->addPlugin(new BlockLegacyClientPlugin(\OC::$server->getConfig()));
81
		$authPlugin = new Plugin();
82
		$authPlugin->addBackend(new PublicAuth());
83
		$this->server->addPlugin($authPlugin);
84
85
		// allow setup of additional auth backends
86
		$event = new SabrePluginEvent($this->server);
87
		$dispatcher->dispatch('OCA\DAV\Connector\Sabre::authInit', $event);
88
89
		// because we are throwing exceptions this plugin has to be the last one
90
		$authPlugin->addBackend($authBackend);
91
92
		// debugging
93
		if(\OC::$server->getConfig()->getSystemValue('debug', false)) {
94
			$this->server->addPlugin(new \Sabre\DAV\Browser\Plugin());
95
		} else {
96
			$this->server->addPlugin(new DummyGetResponsePlugin());
97
		}
98
99
		$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\ExceptionLoggerPlugin('webdav', $logger));
100
		$this->server->addPlugin(new \OCA\DAV\Connector\Sabre\LockPlugin());
101
		$this->server->addPlugin(new \Sabre\DAV\Sync\Plugin());
102
103
		// acl
104
		$acl = new DavAclPlugin();
105
		$acl->principalCollectionSet = [
106
			'principals/users', 'principals/groups'
107
		];
108
		$acl->defaultUsernamePath = 'principals/users';
0 ignored issues
show
Bug introduced by
The property defaultUsernamePath does not seem to exist in OCA\DAV\Connector\Sabre\DavAclPlugin.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
109
		$this->server->addPlugin($acl);
110
111
		// calendar plugins
112
		$this->server->addPlugin(new \OCA\DAV\CalDAV\Plugin());
113
		$this->server->addPlugin(new \Sabre\CalDAV\ICSExportPlugin());
114
		$this->server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());
115
		$this->server->addPlugin(new IMipPlugin($mailer, $logger));
116
		$this->server->addPlugin(new \Sabre\CalDAV\Subscriptions\Plugin());
117
		$this->server->addPlugin(new \Sabre\CalDAV\Notifications\Plugin());
118
		$this->server->addPlugin(new DAV\Sharing\Plugin($authBackend, \OC::$server->getRequest()));
119
		$this->server->addPlugin(new \OCA\DAV\CalDAV\Publishing\PublishPlugin(
120
			\OC::$server->getConfig(),
121
			\OC::$server->getURLGenerator()
122
		));
123
124
		// addressbook plugins
125
		$this->server->addPlugin(new \OCA\DAV\CardDAV\Plugin());
126
		$this->server->addPlugin(new VCFExportPlugin());
127
		$this->server->addPlugin(new ImageExportPlugin(\OC::$server->getLogger()));
128
129
		// system tags plugins
130
		$this->server->addPlugin(new SystemTagPlugin(
131
			\OC::$server->getSystemTagManager(),
132
			\OC::$server->getGroupManager(),
133
			\OC::$server->getUserSession()
134
		));
135
136
		$this->server->addPlugin(new CopyEtagHeaderPlugin());
137
138
		// Some WebDAV clients do require Class 2 WebDAV support (locking), since
139
		// we do not provide locking we emulate it using a fake locking plugin.
140
		if($request->isUserAgent([
141
			'/WebDAVFS/',
142
			'/Microsoft Office OneNote 2013/',
143
		])) {
144
			$this->server->addPlugin(new FakeLockerPlugin());
145
		}
146
147
		if (BrowserErrorPagePlugin::isBrowserRequest($request)) {
148
			$this->server->addPlugin(new BrowserErrorPagePlugin());
149
		}
150
151
		// wait with registering these until auth is handled and the filesystem is setup
152
		$this->server->on('beforeMethod', function () use ($root) {
153
			// custom properties plugin must be the last one
154
			$userSession = \OC::$server->getUserSession();
155
			$user = $userSession->getUser();
156
			if (!is_null($user)) {
157
				$view = \OC\Files\Filesystem::getView();
158
				$this->server->addPlugin(
159
					new FilesPlugin(
160
						$this->server->tree,
161
						\OC::$server->getConfig(),
162
						$this->request,
163
						false,
164
						!\OC::$server->getConfig()->getSystemValue('debug', false)
165
					)
166
				);
167
168
				$this->server->addPlugin(
169
					new \Sabre\DAV\PropertyStorage\Plugin(
170
						new CustomPropertiesBackend(
171
							$this->server->tree,
172
							\OC::$server->getDatabaseConnection(),
173
							\OC::$server->getUserSession()->getUser()
0 ignored issues
show
Bug introduced by
It seems like \OC::$server->getUserSession()->getUser() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
174
						)
175
					)
176
				);
177
				if (!is_null($view)) {
178
					$this->server->addPlugin(
179
						new QuotaPlugin($view));
180
				}
181
				$this->server->addPlugin(
182
					new TagsPlugin(
183
						$this->server->tree, \OC::$server->getTagManager()
184
					)
185
				);
186
				// TODO: switch to LazyUserFolder
187
				$userFolder = \OC::$server->getUserFolder();
188
				$this->server->addPlugin(new SharesPlugin(
189
					$this->server->tree,
190
					$userSession,
191
					$userFolder,
0 ignored issues
show
Bug introduced by
It seems like $userFolder defined by \OC::$server->getUserFolder() on line 187 can be null; however, OCA\DAV\Connector\Sabre\...esPlugin::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
192
					\OC::$server->getShareManager()
193
				));
194
				$this->server->addPlugin(new CommentPropertiesPlugin(
195
					\OC::$server->getCommentsManager(),
196
					$userSession
197
				));
198
				if (!is_null($view)) {
199
					$this->server->addPlugin(new FilesReportPlugin(
200
						$this->server->tree,
201
						$view,
202
						\OC::$server->getSystemTagManager(),
203
						\OC::$server->getSystemTagObjectMapper(),
204
						\OC::$server->getTagManager(),
205
						$userSession,
206
						\OC::$server->getGroupManager(),
207
						$userFolder
0 ignored issues
show
Bug introduced by
It seems like $userFolder defined by \OC::$server->getUserFolder() on line 187 can be null; however, OCA\DAV\Connector\Sabre\...rtPlugin::__construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
208
					));
209
				}
210
			}
211
212
			// register plugins from apps
213
			$pluginManager = new PluginManager(
214
				\OC::$server,
215
				\OC::$server->getAppManager()
216
			);
217
			foreach ($pluginManager->getAppPlugins() as $appPlugin) {
0 ignored issues
show
Bug introduced by
The expression $pluginManager->getAppPlugins() of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
218
				$this->server->addPlugin($appPlugin);
219
			}
220
			foreach ($pluginManager->getAppCollections() as $appCollection) {
0 ignored issues
show
Bug introduced by
The expression $pluginManager->getAppCollections() of type null|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
221
				$root->addChild($appCollection);
222
			}
223
		});
224
	}
225
226
	public function exec() {
227
		$this->server->exec();
228
	}
229
}
230