Issues (493)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

lib/carddav/backend.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * ownCloud - Addressbook
4
 *
5
 * @author Jakob Sack
6
 * @author Thomas Tanghus
7
 * @copyright 2011 Jakob Sack [email protected]
8
 * @copyright 2012-2014 Thomas Tanghus ([email protected])
9
 *
10
 * This library is free software; you can redistribute it and/or
11
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
12
 * License as published by the Free Software Foundation; either
13
 * version 3 of the License, or any later version.
14
 *
15
 * This library 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
21
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 */
24
25
namespace OCA\Contacts\CardDAV;
26
27
use OCA\Contacts;
28
use \Sabre\DAV\PropPatch;
29
30
/**
31
 * This class exchanges data between SabreDav and the Address book backends.
32
 *
33
 * Address book IDs are a combination of the backend name and the ID it has
34
 * in that backend. For your own address books it can be e.g 'local::1' for
35
 * an address book shared with you it could be 'shared::2' an so forth.
36
 */
37
class Backend extends \Sabre\CardDAV\Backend\AbstractBackend {
38
39
	public function __construct($backends) {
40
		$this->backends = $backends;
41
	}
42
43
	/**
44
	 * Returns the list of addressbooks for a specific user.
45
	 *
46
	 * @param string $principaluri
47
	 * @return array
48
	 */
49
	public function getAddressBooksForUser($principaluri) {
50
51
		$app = new Contacts\App();
52
		$userAddressBooks = array();
53
		foreach($this->backends as $backendName) {
54
			$backend = $app->getBackend($backendName);
55
			$addressBooks = $backend->getAddressBooksForUser();
56
57
			if (is_array($addressBooks)) {
58
				foreach($addressBooks as $addressBook) {
59
					if($addressBook['owner'] != \OC::$server->getUserSession()->getUser()->getUId()) {
60
						$addressBook['uri'] = $addressBook['uri'] . '_shared_by_' . $addressBook['owner'];
61
						$addressBook['displayname'] = $addressBook['displayname'];
62
					}
63
					$userAddressBooks[] = array(
64
						'id'  => $backend->name . '::' . $addressBook['id'],
65
						'uri' => $addressBook['uri'],
66
						'principaluri' => 'principals/'.$addressBook['owner'],
67
						'{DAV:}displayname' => $addressBook['displayname'],
68
						'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}addressbook-description'
69
								=> $addressBook['description'],
70
						'{http://calendarserver.org/ns/}getctag' => $addressBook['lastmodified'],
71
						'{' . \Sabre\CardDAV\Plugin::NS_CARDDAV . '}supported-address-data' =>
72
							new \Sabre\CardDAV\Property\SupportedAddressData(),
73
					);
74
				}
75
			}
76
		}
77
78
		return $userAddressBooks;
79
	}
80
81
82
	/**
83
	 * Updates an addressbook's properties
84
	 *
85
	 * See \Sabre\DAV\IProperties for a description of the mutations array, as
86
	 * well as the return value.
87
	 *
88
	 * @param mixed $addressbookid
89
	 * @see \Sabre\DAV\IProperties::updateProperties
90
	 * @return bool|array
91
	 */
92
	public function updateAddressBook($addressbookid, PropPatch $propPatch) {
93
		$changes = array();
94
95
		$mutations = $propPatch->getRemainingMutations();
96
97 View Code Duplication
		foreach($mutations as $property=>$newvalue) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
98
			switch($property) {
99
				case '{DAV:}displayname' :
100
					$changes['displayname'] = $newvalue;
101
					break;
102
				case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV
103
						. '}addressbook-description' :
104
					$changes['description'] = $newvalue;
105
					break;
106
				default :
107
					// If any unsupported values were being updated, we must
108
					// let the entire request fail.
109
					return false;
110
			}
111
		}
112
113
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
114
		return $backend->updateAddressBook($id, $changes);
115
116
	}
117
118
	/**
119
	 * Creates a new address book
120
	 *
121
	 * @param string $principaluri
122
	 * @param string $uri Just the 'basename' of the url.
123
	 * @param array $properties
124
	 * @return void
125
	 */
126
	public function createAddressBook($principaluri, $uri, array $properties) {
127
128 View Code Duplication
		foreach($properties as $property => $newvalue) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
130
			switch($property) {
131
				case '{DAV:}displayname' :
132
					$properties['displayname'] = $newvalue;
133
					break;
134
				case '{' . \Sabre\CardDAV\Plugin::NS_CARDDAV
135
						. '}addressbook-description' :
136
					$properties['description'] = $newvalue;
137
					break;
138
				default :
139
					throw new \Sabre\DAV\Exception\BadRequest('Unknown property: '
140
						. $property);
141
			}
142
143
		}
144
145
		$properties['uri'] = $uri;
146
147
		$app = new Contacts\App();
148
		$backend = $app->getBackend('local');
149
150
		$backend->createAddressBook($properties);
151
	}
152
153
	/**
154
	 * Deletes an entire addressbook and all its contents
155
	 *
156
	 * @param mixed $addressbookid
157
	 * @return void
158
	 */
159
	public function deleteAddressBook($addressbookid) {
160
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
161
		$backend->deleteAddressBook($id);
162
	}
163
164
	/**
165
	 * Returns the last modified date if the backend supports it.
166
	 *
167
	 * @param mixed $addressbookid
168
	 * @return void
169
	 */
170
	public function lastModifiedAddressBook($addressbookid) {
171
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
172
		return $backend->lastModifiedAddressBook($id);
173
	}
174
175
	/**
176
	 * Returns all cards for a specific addressbook id.
177
	 *
178
	 * @param mixed $addressbookid
179
	 * @return array
180
	 */
181
	public function getCards($addressbookid) {
182
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
183
		$contacts = $backend->getContacts($id);
184
185
		$cards = array();
186
		foreach($contacts as $contact) {
187
			$cards[] = array(
188
				'id' => $contact['id'],
189
				//'carddata' => $i['carddata'],
190
				'size' => strlen($contact['carddata']),
191
				'etag' => '"' . md5($contact['carddata']) . '"',
192
				'uri' => $contact['uri'],
193
				'lastmodified' => $contact['lastmodified'] );
194
		}
195
196
		return $cards;
197
	}
198
199
	/**
200
	 * Returns a specfic card
201
	 *
202
	 * @param mixed $addressbookid
203
	 * @param string $carduri
204
	 * @return array
205
	 */
206
	public function getCard($addressbookid, $carduri) {
207
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
208
		try {
209
			$contact = $backend->getContact($id, array('uri' => urldecode($carduri)));
210
		} catch(\Exception $e) {
211
			//throw new \Sabre\DAV\Exception\NotFound($e->getMessage());
212
			\OCP\Util::writeLog('contacts', __METHOD__.', Exception: '. $e->getMessage(), \OCP\Util::DEBUG);
213
			return false;
214
		}
215
		if(is_array($contact) ) {
216
			$contact['etag'] = '"' . md5($contact['carddata']) . '"';
217
			return $contact;
218
		}
219
		//throw new \Sabre\DAV\Exception('Error retrieving the card');
220
		return false;
221
	}
222
223
	/**
224
	 * Creates a new card
225
	 *
226
	 * We don't return an Etag as the carddata can have been modified
227
	 * by Plugin::validate()
228
	 *
229
	 * @see Plugin::validate()
230
	 * @param mixed $addressbookid
231
	 * @param string $carduri
232
	 * @param string $carddata
233
	 * @return string|null
234
	 */
235
	public function createCard($addressbookid, $carduri, $carddata) {
236
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
237
		$backend->createContact($id, $carddata, array('uri' => $carduri));
238
	}
239
240
	/**
241
	 * Updates a card
242
	 *
243
	 * @param mixed $addressbookid
244
	 * @param string $carduri
245
	 * @param string $carddata
246
	 * @return null
247
	 */
248
	public function updateCard($addressbookid, $carduri, $carddata) {
249
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
250
		$backend->updateContact($id, array('uri' => $carduri,), $carddata);
251
	}
252
253
	/**
254
	 * Deletes a card
255
	 *
256
	 * @param mixed $addressbookid
257
	 * @param string $carduri
258
	 * @return bool
259
	 */
260
	public function deleteCard($addressbookid, $carduri) {
261
		list($id, $backend) = $this->getBackendForAddressBook($addressbookid);
262
		return $backend->deleteContact($id, array('uri' => $carduri));
263
	}
264
265
	/**
266
	 * @brief gets the userid from a principal path
267
	 * @param string $principaluri
268
	 * @return string
269
	 */
270
	public function userIDByPrincipal($principaluri) {
271
		list(, $userid) = \Sabre\DAV\URLUtil::splitPath($principaluri);
272
		return $userid;
273
	}
274
275
	/**
276
	 * Get the backend for an address book
277
	 *
278
	 * @param mixed $addressbookid
279
	 * @return array(string, \OCA\Contacts\Backend\AbstractBackend)
0 ignored issues
show
The doc-type array(string, could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
280
	 */
281
	public function getBackendForAddressBook($addressbookid) {
282
		list($backendName, $id) = explode('::', $addressbookid);
283
		$app = new Contacts\App();
284
		$backend = $app->getBackend($backendName);
285
		if($backend->name === $backendName && $backend->hasAddressBook($id)) {
286
			return array($id, $backend);
287
		}
288
		throw new \Sabre\DAV\Exception\NotFound('Backend not found: ' . $addressbookid);
289
	}
290
}
291