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/backend/abstractbackend.php (5 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 - Base class for Contacts backends
4
 *
5
 * @author Thomas Tanghus
6
 * @copyright 2013-2014 Thomas Tanghus ([email protected])
7
 *
8
 * This library is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10
 * License as published by the Free Software Foundation; either
11
 * version 3 of the License, or any later version.
12
 *
13
 * This library is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17
 *
18
 * You should have received a copy of the GNU Affero General Public
19
 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
20
 *
21
 */
22
23
namespace OCA\Contacts\Backend;
24
25
use OCA\Contacts\VObject\VCard;
26
27
/**
28
 * Subclass this class for address book backends.
29
 */
30
abstract class AbstractBackend {
31
32
	/**
33
	* The following methods MUST be implemented:
34
	*
35
	* @method array getAddressBooksForUser(array $options = array())
36
	* @method array|null getAddressBook(string $addressbookid, array $options = array())
37
	* @method array getContacts(string $addressbookid, array $options = array())
38
	* @method array|null getContact(string $addressbookid, mixed $id, array $options = array())
39
	* The following methods MAY be implemented:
40
	* @method bool hasAddressBook(string $addressbookid)
41
	* @method bool updateAddressBook(string $addressbookid, array $updates, array $options = array())
42
	* @method string createAddressBook(array $properties, array $options = array())
43
	* @method bool deleteAddressBook(string $addressbookid, array $options = array())
44
	* @method int lastModifiedAddressBook(string $addressbookid)
45
	* @method array numContacts(string $addressbookid)
46
	* @method bool updateContact(string $addressbookid, string $id, VCard $contact, array $options = array())
47
	* @method string createContact(string $addressbookid, VCard $contact, array $properties)
48
	* @method bool deleteContact(string $addressbookid, string $id, array $options = array())
49
	* @method int lastModifiedContact(string $addressbookid)
50
	*/
51
52
	/**
53
	 * The name of the backend.
54
	 * @var string
55
	 */
56
	public $name;
57
58
	/**
59
	 * The current user.
60
	 * @var string
61
	 */
62
	public $userid;
63
64
	protected $possibleContactPermissions = array(
65
		\OCP\PERMISSION_CREATE 	=> 'createContact',
66
		\OCP\PERMISSION_READ	=> 'getContact',
67
		\OCP\PERMISSION_UPDATE	=> 'updateContact',
68
		\OCP\PERMISSION_DELETE 	=> 'deleteContact',
69
	);
70
71
	protected $possibleAddressBookPermissions = array(
72
		\OCP\PERMISSION_CREATE 	=> 'createAddressBook',
73
		\OCP\PERMISSION_READ	=> 'getAddressBook',
74
		\OCP\PERMISSION_UPDATE	=> 'updateAddressBook',
75
		\OCP\PERMISSION_DELETE 	=> 'deleteAddressBook',
76
	);
77
78
	/**
79
	* Sets up the backend
80
	*
81
	*/
82
	public function __construct($userid = null) {
83
		$this->userid = $userid ? $userid : \OC::$server->getUserSession()->getUser()->getUId();
84
	}
85
86
	/**
87
	* @brief Get all possible permissions for contacts based on what the backend implements.
88
	* @returns bitwise-or'ed actions
89
	*
90
	* Returns the supported actions as an int to be
91
	* compared with \OCP\PERMISSION_CREATE etc.
92
	*/
93 7 View Code Duplication
	protected function getContactPermissions() {
0 ignored issues
show
This method seems to be duplicated in 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...
94 7
		$permissions = 0;
95
96 7
		foreach ($this->possibleContactPermissions as $permission => $methodName) {
97 7
			if(method_exists($this, $methodName)) {
98 7
				$permissions |= $permission;
99 7
			}
100
101 7
		}
102
103
		//\OCP\Util::writeLog('contacts', __METHOD__.', permissions' . $permissions, \OCP\Util::DEBUG);
104 7
		return $permissions;
105
	}
106
107
	/**
108
	* @brief Get all permissions for address book based on what the backend implements.
109
	* @returns bitwise-or'ed actions
110
	*
111
	* Returns the supported actions as int to be
112
	* compared with \OCP\PERMISSION_CREATE etc.
113
	*/
114 1 View Code Duplication
	protected function getAddressBookPermissions() {
0 ignored issues
show
This method seems to be duplicated in 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...
115
116 1
		$permissions = 0;
117
118 1
		foreach ($this->possibleAddressBookPermissions as $permission => $methodName) {
119 1
			if (method_exists($this, $methodName)) {
120 1
				$permissions |= $permission;
121 1
			}
122
123 1
		}
124
125
		//\OCP\Util::writeLog('contacts', __METHOD__.', permissions' . $permissions, \OCP\Util::DEBUG);
126 1
		return $permissions;
127
	}
128
129
	/**
130
	* @brief Check if backend implements action for contacts
131
	* @param $actions bitwise-or'ed actions
132
	* @returns boolean
133
	*
134
	* Returns the supported actions as int to be
135
	* compared with \OCP\PERMISSION_CREATE etc.
136
	*/
137 7
	public function hasContactMethodFor($permission) {
138
139 7
		return (bool)($this->getContactPermissions() & $permission);
140
141
	}
142
143
	/**
144
	* @brief Check if backend implements action for contacts
145
	* @param $actions bitwise-or'ed actions
146
	* @returns boolean
147
	*
148
	* Returns the supported actions as int to be
149
	* compared with \OCP\PERMISSION_CREATE etc.
150
	*/
151 1
	public function hasAddressBookMethodFor($permission) {
152
153 1
		return (bool)($this->getAddressBookPermissions() & $permission);
154
155
	}
156
157
	/**
158
	 * Check if the backend has the address book
159
	 *
160
	 * This can be reimplemented in the backend to improve performance.
161
	 *
162
	 * @param string $addressBookId
163
	 * @return bool
164
	 */
165
	public function hasAddressBook($addressBookId) {
166
167
		return count($this->getAddressBook($addressBookId)) > 0;
168
169
	}
170
171
	/**
172
	 * Returns the number of contacts in an address book.
173
	 * Implementations can choose to override this method to either
174
	 * get the result more effectively or to return null if the backend
175
	 * cannot determine the number.
176
	 *
177
	 * @param string $addressBookId
178
	 * @return integer
179
	 */
180
	public function numContacts($addressBookId) {
181
182
		return count($this->getContacts($addressBookId));
183
184
	}
185
186
	/**
187
	 * Returns the list of addressbooks for a specific user.
188
	 *
189
	 * The returned arrays MUST contain a unique 'id' for the
190
	 * backend and a 'displayname', and it MAY contain a
191
	 * 'description'.
192
	 *
193
	 * @param array $options - Optional (backend specific options)
194
	 * @return array
195
	 */
196
	public abstract function getAddressBooksForUser(array $options = array());
197
198
	/**
199
	 * Get an addressbook's properties
200
	 *
201
	 * The returned array MUST contain string: 'displayname',string: 'backend'
202
	 * and integer: 'permissions' value using there ownCloud CRUDS constants
203
	 * (which MUST be at least \OCP\PERMISSION_READ).
204
	 * Currently the only ones supported are 'displayname' and
205
	 * 'description', but backends can implement additional.
206
	 *
207
	 * @param string $addressBookId
208
	 * @param array $options - Optional (backend specific options)
209
	 * @return array|null $properties
210
	 */
211
	public abstract function getAddressBook($addressBookId, array $options = array());
212
213
	/**
214
	 * Updates an addressbook's properties
215
	 *
216
	 * The $properties array contains the changes to be made.
217
	 *
218
	 * Currently the only ones supported are 'displayname' and
219
	 * 'description', but backends can implement additional.
220
	 *
221
	 * @param string $addressBookId
222
	 * @param array $properties
223
	 * @param array $options - Optional (backend specific options)
224
	 * @return bool
225
	public function updateAddressBook($addressBookId, array $properties, array $options = array());
226
	 */
227
228
	/**
229
	 * Creates a new address book
230
	 *
231
	 * Classes that doesn't support adding address books MUST NOT implement this method.
232
	 *
233
	 * Currently the only ones supported are 'displayname' and
234
	 * 'description', but backends can implement additional.
235
	 * 'displayname' MUST be present.
236
	 *
237
	 * @param array $properties
238
	 * @param array $options - Optional (backend specific options)
239
	 * @return string|false The ID if the newly created AddressBook or false on error.
240
	public function createAddressBook(array $properties, array $options = array());
241
	 */
242
243
	/**
244
	 * Deletes an entire address book and all its contents
245
	 *
246
	 * Classes that doesn't support deleting address books MUST NOT implement this method.
247
	 *
248
	 * @param string $addressBookId
249
	 * @param array $options - Optional (backend specific options)
250
	 * @return bool
251
	public function deleteAddressBook($addressBookId, array $options = array());
252
	 */
253
254
	/**
255
	 * @brief Get the last modification time for an address book.
256
	 *
257
	 * Must return a UNIX time stamp or null if the backend
258
	 * doesn't support it.
259
	 *
260
	 * @param string $addressBookId
261
	 * @returns int | null
262
	 */
263 4
	public function lastModifiedAddressBook($addressBookId) {
264 4
	}
265
266
	/**
267
	 * @brief 'touch' an address book.
268
	 *
269
	 * If implemented this method must mark the address books
270
	 * modification date so lastModifiedAddressBook() can be
271
	 * used to invalidate the cache.
272
	 *
273
	 * @param string $addressBookId
274
	 */
275
	public function setModifiedAddressBook($addressBookId) {
276
	}
277
278
	/**
279
	 * Returns all contacts for a specific addressbook id.
280
	 *
281
	 * The returned array MUST contain the unique ID a string value 'id', a string
282
	 * value 'displayname', a string value 'owner' and an integer 'permissions' value using there
283
	 * ownCloud CRUDS constants (which MUST be at least \OCP\PERMISSION_READ), and SHOULD
284
	 * contain the properties of the contact formatted as a vCard 3.0
285
	 * https://tools.ietf.org/html/rfc2426 mapped to 'carddata' or as an
286
	 * \OCA\Contacts\VObject\VCard object mapped to 'vcard'.
287
	 *
288
	 * Example:
289
	 *
290
	 * array(
291
	 *   0 => array('id' => '4e111fef5df', 'owner' => 'foo', 'permissions' => 1, 'displayname' => 'John Q. Public', 'vcard' => $vobject),
292
	 *   1 => array('id' => 'bbcca2d1535', 'owner' => 'bar', 'permissions' => 32, 'displayname' => 'Jane Doe', 'carddata' => $data)
293
	 * );
294
	 *
295
	 * For contacts that contain loads of data, the 'carddata' or 'vcard' MAY be omitted
296
	 * as it can be fetched later.
297
	 *
298
	 * The following options are supported in the $options array:
299
	 *
300
	 * - 'limit': An integer value for the number of contacts to fetch in each call.
301
	 * - 'offset': The offset to start at.
302
	 * - 'omitdata': Whether to fetch the entire carddata or vcard.
303
	 *
304
	 * @param string $addressBookId
305
	 * @param array $options - Optional options
306
	 * @return array
307
	 */
308
	public abstract function getContacts($addressBookId, array $options = array());
309
310
	/**
311
	 * Returns a specfic contact.
312
	 *
313
	 * Same as getContacts except that either 'carddata' or 'vcard' is mandatory.
314
	 *
315
	 * @param string $addressBookId
316
	 * @param string $id
317
	 * @param array $options - Optional options
318
	 * @return array|null
319
	 */
320
	public abstract function getContact($addressBookId, $id, array $options = array());
321
322
	/**
323
	 * Creates a new contact
324
	 *
325
	 * Classes that doesn't support adding contacts MUST NOT implement this method.
326
	 *
327
	 * @param string $addressBookId
328
	 * @param VCard $contact
329
	 * @param array $options - Optional options
330
	 * @return string|bool The identifier for the new contact or false on error.
331
	public function createContact($addressbookid, $contact, array $options = array());
332
	 */
333
334
	/**
335
	 * Updates a contact
336
	 *
337
	 * Classes that doesn't support updating contacts MUST NOT implement this method.
338
	 *
339
	 * @param string $addressBookId
340
	 * @param mixed $id
341
	 * @param VCard $contact
342
	 * @param array $options - Optional options
343
	 * @return bool
344
	public function updateContact($addressbookid, $id, $carddata, array $options = array());
345
	 */
346
347
	/**
348
	 * Deletes a contact
349
	 *
350
	 * Classes that doesn't support deleting contacts MUST NOT implement this method.
351
	 *
352
	 * @param string $addressBookId
353
	 * @param mixed $id
354
	 * @param array $options - Optional options
355
	 * @return bool
356
	public function deleteContact($addressbookid, $id, array $options = array());
357
	 */
358
359
	/**
360
	 * @brief Get the last modification time for a contact.
361
	 *
362
	 * Must return a UNIX time stamp or null if the backend
363
	 * doesn't support it.
364
	 *
365
	 * @param string $addressBookId
366
	 * @param mixed $id
367
	 * @returns int | null
368
	 */
369
	public function lastModifiedContact($addressBookId, $id) {
370
	}
371
	
372
	/**
373
	 * Creates a unique key for inserting into oc_preferences.
374
	 * As IDs can have any length and the key field is limited to 64 chars,
375
	 * the IDs are transformed to the first 8 chars of their md5 hash.
376
	 * 
377
	 * @param string $addressBookId.
0 ignored issues
show
There is no parameter named $addressBookId.. Did you maybe mean $addressBookId?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
378
	 * @param string $contactId.
0 ignored issues
show
There is no parameter named $contactId.. Did you maybe mean $contactId?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
379
	 * @throws \BadMethodCallException
380
	 * @return string
381
	 */
382 4
	protected function combinedKey($addressBookId = null, $contactId = null) {
383 4
		$key = $this->name;
384 4
		if (!is_null($addressBookId)) {
385
386 4
			$key .= '_' . substr(md5($addressBookId), 0, 8);
387
388 4
			if (!is_null($contactId)) {
389
				$key .= '_' . substr(md5($contactId), 0, 8);
390
			}
391
392 4
		} else if (!is_null($contactId)) {
393
394
			throw new \BadMethodCallException(
395
				__METHOD__ . ' cannot be called with a contact ID but no address book ID'
396
			);
397
398
		}
399 4
		return $key;
400
	}
401
402
	/**
403
	 * @brief Query whether a backend or an address book is active
404
	 * @param string $addressBookId If null it checks whether the backend is activated.
405
	 * @return boolean
406
	 */
407 4
	public function isActive($addressBookId = null) {
408
409 4
		$key = $this->combinedKey($addressBookId);
410 4
		$key = 'active_' . $key;
411
412 4
		return !!(\OC::$server->getConfig()->getUserValue($this->userid, 'contacts', $key, 1));
413
	}
414
415
	/**
416
	 * @brief Activate a backend or an address book
417
	 * @param bool $active
418
	 * @param string $addressBookId If null it activates the backend.
419
	 * @return boolean
420
	 */
421
	public function setActive($active, $addressBookId = null) {
422
423
		$key = $this->combinedKey($addressBookId);
424
		$key = 'active_' . $key;
425
426
		$this->setModifiedAddressBook($addressBookId);
427
		return \OCP\Config::setUserValue($this->userid, 'contacts', $key, (int)$active);
428
	}
429
430
	/**
431
	 * @brief get all the preferences for the addressbook
432
	 * @return array Format array('param1' => 'value', 'param2' => 'value')
433
	 */
434
	public function getPreferences($addressBookId) {
435
436
		$key = 'prefs_' . $this->combinedKey($addressBookId);
437
438
		$data = \OCP\Config::getUserValue($this->userid, 'contacts', $key, false);
439
		return $data ? json_decode($data, true) : array();
440
	}
441
	
442
	/**
443
	 * @brief sets the preferences for the addressbook given in parameter
444
	 * @param array the preferences, format array('param1' => 'value', 'param2' => 'value')
445
	 * @return boolean
446
	 */
447 View Code Duplication
	public function setPreferences($addressbookid, array $params) {
0 ignored issues
show
This method seems to be duplicated in 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...
448
		$key = 'prefs_' . $this->combinedKey($addressbookid);
449
450
		$data = json_encode($params);
451
		return $data
452
			? \OCP\Config::setUserValue($this->userid, 'contacts', $key, $data)
453
			: false;
454
	}
455
	
456
	/**
457
	 * @param string $addressbookid
458
	 */
459
	public function removePreferences($addressbookid) {
460
		$key = $this->combinedKey($addressbookid);
461
		$key = 'prefs_' . $key;
462
		\OC::$server->getConfig()->deleteUserValue( $this->userid, 'contacts', $key );
463
		
464
	}
465
}
466