This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
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 Nicolas Mora |
||
6 | * @copyright 2013 Nicolas Mora ([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 | use Sabre\VObject\Reader; |
||
27 | use OCA\Contacts\Connector\LdapConnector; |
||
28 | |||
29 | /** |
||
30 | * Subclass this class for Cantacts backends |
||
31 | */ |
||
32 | |||
33 | class Ldap extends AbstractBackend { |
||
34 | |||
35 | /** |
||
36 | * The name of the backend. |
||
37 | * @var string |
||
38 | */ |
||
39 | public $name='ldap'; |
||
40 | private $ldapConnection = null; |
||
41 | private $connector = null; |
||
42 | |||
43 | /** |
||
44 | * The cached address books. |
||
45 | * @var array[] |
||
46 | */ |
||
47 | public $addressbooks; |
||
48 | |||
49 | /** |
||
50 | * @brief validates and sets the ldap parameters |
||
51 | * @param $ldapParams array containing the parameters |
||
52 | * return boolean |
||
53 | */ |
||
54 | public function setLdapParams($aid) { |
||
55 | $tmp = $this->getPreferences($aid); |
||
56 | if ($tmp != false) { |
||
57 | $this->ldapParams = (array)$tmp; |
||
0 ignored issues
–
show
|
|||
58 | $this->connector = new LdapConnector($this->ldapParams['ldap_vcard_connector']); |
||
59 | return true; |
||
60 | } else { |
||
61 | return false; |
||
62 | } |
||
63 | } |
||
64 | |||
65 | |||
66 | /** |
||
67 | * @brief creates the ldap connection, then binds it according to the parameters previously given |
||
68 | * @return boolean connexion status |
||
69 | */ |
||
70 | public function ldapCreateAndBindConnection() { |
||
71 | if (!self::ldapIsConnected() && $this->ldapParams != null) { |
||
72 | // ldap connect |
||
73 | $this->ldapConnection = ldap_connect($this->ldapParams['ldapurl']); |
||
74 | ldap_set_option($this->ldapConnection, LDAP_OPT_REFERRALS, 0); |
||
75 | ldap_set_option($this->ldapConnection, LDAP_OPT_PROTOCOL_VERSION, 3); |
||
76 | if ($this->ldapConnection) { |
||
77 | // ldap bind |
||
78 | if ($this->ldapParams['ldapanonymous'] == 1) { |
||
79 | $ldapbind = ldap_bind($this->ldapConnection); |
||
80 | } else { |
||
81 | $ldapbind = ldap_bind($this->ldapConnection, $this->ldapParams['ldapuser'], base64_decode($this->ldapParams['ldappass'])); |
||
82 | } |
||
83 | return $ldapbind; |
||
84 | } |
||
85 | return false; |
||
86 | } |
||
87 | return self::ldapIsConnected(); |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * @brief close the current connection |
||
92 | * @return boolean|null closing success |
||
93 | */ |
||
94 | public function ldapCloseConnection() { |
||
95 | if (self::ldapIsConnected()) { |
||
96 | ldap_unbind($this->ldapConnection); |
||
97 | $this->ldapConnection = null; |
||
98 | return true; |
||
99 | } |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * |
||
104 | */ |
||
105 | public function ldapIsConnected() { |
||
106 | return ($this->ldapConnection != null); |
||
107 | } |
||
108 | |||
109 | /** |
||
110 | * @brief search a list in ldap server |
||
111 | * @param $ldapbasedn the base dn |
||
112 | * @param $bindsearch the search filter |
||
113 | * @param $entries the ldap entries to reach |
||
114 | * @param $start the starting point |
||
115 | * @param $num the number of entries to return |
||
116 | * @return array|false |
||
117 | */ |
||
118 | public function ldapFindMultiple($ldapbasedn, $bindsearch, $entriesName, $start=null, $num=null) { |
||
0 ignored issues
–
show
The variable $ldap_results is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $LdapEntries is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
119 | if (($entriesName != null) && self::ldapCreateAndBindConnection() && $ldapbasedn != null && $bindsearch != null) { |
||
120 | |||
121 | if ($start==null) { |
||
122 | $start=0; |
||
0 ignored issues
–
show
$start is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
123 | } |
||
124 | |||
125 | if ($num==null) { |
||
126 | $num=PHP_INT_MAX; |
||
0 ignored issues
–
show
$num is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
127 | } |
||
128 | |||
129 | $pageSize = isset($this->ldapParams['ldappagesize'])?$this->ldapParams['ldappagesize']:"20"; |
||
130 | |||
131 | $cookie = ''; |
||
132 | |||
133 | $entries = array(); |
||
134 | |||
135 | $cpt=0; |
||
136 | |||
137 | \OC_Log::write('contacts_ldap', __METHOD__." - search what $ldapbasedn, $bindsearch $pageSize", \OC_Log::DEBUG); |
||
138 | do { |
||
139 | |||
140 | ldap_control_paged_result($this->ldapConnection, $pageSize, true, $cookie); |
||
141 | $ldap_results = ldap_search ($this->ldapConnection, $ldapbasedn, $bindsearch, $entriesName); |
||
142 | |||
143 | $LdapEntries = ldap_get_entries ($this->ldapConnection, $ldap_results); |
||
144 | |||
145 | for ($i=0; $i<$LdapEntries['count']; $i++) { |
||
146 | $entries[] = $LdapEntries[$i]; |
||
147 | } |
||
148 | ldap_control_paged_result_response($this->ldapConnection, $ldap_results, $cookie); |
||
149 | |||
150 | $cpt++; |
||
151 | } while($cookie !== null && $cookie != '' && $cpt < 10); |
||
152 | |||
153 | $entries['count'] = count($entries); |
||
154 | |||
155 | return $entries; |
||
156 | |||
157 | self::ldapCloseConnection(); |
||
0 ignored issues
–
show
self::ldapCloseConnection(); does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
158 | } |
||
159 | return false; |
||
160 | } |
||
161 | |||
162 | |||
163 | /** |
||
164 | * @brief search one contact in ldap server |
||
165 | * @param $ldapbasedn the base dn |
||
166 | * @param $bindsearch the search filter |
||
167 | * @param $entries the ldap entries to reach |
||
168 | * @param $start the starting point |
||
169 | * @param $num the number of entries to return |
||
170 | * @return array|false |
||
171 | */ |
||
172 | public function ldapFindOne($ldapbasedn, $bindsearch, $entries, $start=null, $num=null) { |
||
0 ignored issues
–
show
The variable $ldap_results is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
173 | if (($entries != null) && self::ldapCreateAndBindConnection() && $ldapbasedn != null && $bindsearch != null) { |
||
174 | |||
175 | if ($start==null) { |
||
176 | $start=0; |
||
0 ignored issues
–
show
$start is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
177 | } |
||
178 | |||
179 | if ($num==null) { |
||
180 | $num=PHP_INT_MAX; |
||
0 ignored issues
–
show
$num is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
181 | } |
||
182 | \OC_Log::write('contacts_ldap', __METHOD__." - search $ldapbasedn, $bindsearch ", \OC_Log::DEBUG); |
||
183 | |||
184 | $ldap_results = @ldap_search ($this->ldapConnection, $ldapbasedn, $bindsearch, $entries); |
||
185 | if ($ldap_results) { |
||
186 | $entries = ldap_get_entries ($this->ldapConnection, $ldap_results); |
||
187 | if ($entries['count'] > 0) { |
||
188 | return $entries[0]; |
||
189 | } else { |
||
190 | return false; |
||
191 | } |
||
192 | } |
||
193 | |||
194 | self::ldapCloseConnection(); |
||
195 | } |
||
196 | return false; |
||
197 | } |
||
198 | |||
199 | /** |
||
200 | * @brief adds a new ldap entry |
||
201 | * @param string $ldapDN the new DN (must be unique) |
||
202 | * @param $ldapValues the ldif values |
||
203 | * @return boolean insert status |
||
204 | */ |
||
205 | public function ldapAdd($ldapDN, $ldapValues) { |
||
206 | if (self::ldapIsConnected()) { |
||
207 | return @ldap_add($this->ldapConnection, $ldapDN, $ldapValues); |
||
208 | } |
||
209 | return false; |
||
210 | } |
||
211 | |||
212 | /** |
||
213 | * @brief modify a ldap entry |
||
214 | * @param string $ldapDN the DN (must exists) |
||
215 | * @param $ldapValues the ldif values |
||
216 | * @return boolean modify status |
||
217 | */ |
||
218 | public function ldapUpdate($ldapDN, $ldapValues) { |
||
219 | if (self::ldapIsConnected()) { |
||
220 | return @ldap_modify($this->ldapConnection, $ldapDN, $ldapValues); |
||
221 | } |
||
222 | return false; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * @brief delete a ldap entry |
||
227 | * @param string $ldapDN the DN (must exists) |
||
228 | * @return boolean delete status |
||
229 | */ |
||
230 | public function ldapDelete($ldapDN) { |
||
231 | if (self::ldapIsConnected()) { |
||
232 | ldap_delete($this->ldapConnection, $ldapDN); |
||
233 | return true; |
||
234 | } |
||
235 | return false; |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Sets up the backend |
||
240 | * |
||
241 | */ |
||
242 | public function __construct( |
||
243 | $userid = null, |
||
244 | $addressBooksTableName = '*PREFIX*contacts_ldap_addressbooks' |
||
0 ignored issues
–
show
|
|||
245 | ) { |
||
246 | $this->userid = $userid ? $userid : \OC::$server->getUserSession()->getUser()->getUId(); |
||
247 | $this->addressbooks = array(); |
||
248 | } |
||
249 | |||
250 | /** |
||
251 | * Returns the list of active addressbooks for a specific user. |
||
252 | * |
||
0 ignored issues
–
show
|
|||
253 | * @return array |
||
254 | */ |
||
255 | public function getAddressBooksForUser(array $options = array()) { |
||
256 | $addressbookidList = $this->getAddressbookList(); |
||
257 | foreach($addressbookidList as $addressbookid) { |
||
258 | $this->addressbooks[] = self::getAddressBook($addressbookid); |
||
259 | } |
||
260 | return $this->addressbooks; |
||
261 | } |
||
262 | |||
263 | /** |
||
264 | * Get an addressbook's properties |
||
265 | * |
||
266 | * The returned array MUST contain 'displayname' and an integer 'permissions' |
||
267 | * value using there ownCloud CRUDS constants (which MUST be at least |
||
268 | * \OCP\PERMISSION_READ). |
||
269 | * Currently the only ones supported are 'displayname' and |
||
270 | * 'description', but backends can implement additional. |
||
271 | * |
||
272 | * @param string $addressbookid |
||
273 | * @return array $properties |
||
274 | */ |
||
275 | public function getAddressBook($addressbookid, array $options = array()) { |
||
276 | //\OC_Log::write('contacts', __METHOD__.' id: ' |
||
277 | // . $addressbookid, \OC_Log::DEBUG); |
||
278 | if($this->addressbooks && isset($this->addressbooks[$addressbookid])) { |
||
0 ignored issues
–
show
The expression
$this->addressbooks of type array[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
279 | //print(__METHOD__ . ' ' . __LINE__ .' addressBookInfo: ' . print_r($this->addressbooks[$addressbookid], true)); |
||
280 | return $this->addressbooks[$addressbookid]; |
||
281 | } |
||
282 | // Hmm, not found. Lets query the db. |
||
283 | $preferences = self::getPreferences($addressbookid); |
||
284 | if (count($preferences) > 0) { |
||
285 | $preferences['id'] = (string)$addressbookid; |
||
286 | $preferences['backend'] = $this->name; |
||
287 | $preferences['owner'] = $this->userid; |
||
288 | $preferences['permissions'] = \OCP\PERMISSION_ALL; |
||
289 | $preferences['lastmodified'] = self::lastModifiedAddressBook($addressbookid); |
||
0 ignored issues
–
show
Are you sure the assignment to
$preferences['lastmodified'] is correct as self::lastModifiedAddressBook($addressbookid) (which targets OCA\Contacts\Backend\Abs...stModifiedAddressBook() ) seems to always return null.
This check looks for function or method calls that always return null and whose return value is assigned to a variable. class A
{
function getObject()
{
return null;
}
}
$a = new A();
$object = $a->getObject();
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||
290 | |||
291 | // remove the ldappassword from the return value if exists |
||
292 | if (isset($preferences['ldappass']) && (isset($options['getpwd']) && !$options['getpwd'])) { |
||
293 | unset($preferences['ldappass']); |
||
294 | } |
||
295 | |||
296 | return $preferences; |
||
297 | } else { |
||
298 | return array(); |
||
299 | } |
||
300 | } |
||
301 | |||
302 | /** |
||
303 | * Test if the address book exists |
||
304 | * @return bool |
||
305 | */ |
||
306 | public function hasAddressBook($addressbookid) { |
||
307 | if($this->addressbooks && isset($this->addressbooks[$addressbookid])) { |
||
0 ignored issues
–
show
The expression
$this->addressbooks of type array[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent. Consider making the comparison explicit by using ![]() |
|||
308 | return true; |
||
309 | } |
||
310 | return count($this->getAddressBook($addressbookid)) > 0; |
||
311 | } |
||
312 | |||
313 | /** |
||
314 | * Updates an addressbook's properties |
||
315 | * |
||
316 | * The $properties array contains the changes to be made. |
||
317 | * |
||
318 | * Currently the only ones supported are 'displayname' and |
||
319 | * 'description', but backends can implement additional. |
||
320 | * |
||
321 | * @param string $addressbookid |
||
322 | * @param array $properties |
||
323 | * @return string|false The ID if the modified AddressBook or false on error. |
||
324 | */ |
||
325 | public function updateAddressBook($addressbookid, array $properties, array $options = array()) { |
||
326 | if ($this->hasAddressBook($addressbookid)) { |
||
327 | // Addressbook exists, modify it through the create function |
||
328 | if (isset($properties['ldappassmodified']) && $properties['ldappassmodified'] != 'true') { |
||
329 | // If password hasn't changed, get it from the preferences |
||
330 | $addrbook = $this->getAddressBook($addressbookid, array('getpwd' => true)); |
||
331 | $properties['ldappass'] = base64_decode($addrbook['ldappass']); |
||
332 | } |
||
333 | return $this->setAddressBook($properties, $options); |
||
334 | } else { |
||
335 | return false; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | /** |
||
340 | * Creates a new address book |
||
341 | * |
||
342 | * Currently the only ones supported are 'displayname' and |
||
343 | * 'description', but backends can implement additional. |
||
344 | * 'displayname' MUST be present. |
||
345 | * |
||
346 | * @param array $properties |
||
347 | * @return string|false The ID if the newly created AddressBook or false on error. |
||
348 | */ |
||
349 | public function createAddressBook(array $properties, array $options = array()) { |
||
350 | if (!isset($properties['uri']) || $this->hasAddressBook($properties['uri'])) { |
||
351 | return false; |
||
352 | } else { |
||
353 | return $this->setAddressBook($properties, $options); |
||
354 | } |
||
355 | } |
||
356 | |||
357 | /* |
||
358 | * Sets the parameters for a new or existing addressbook |
||
359 | * |
||
360 | * @param array $properties |
||
361 | * @return string|false The ID if the newly created AddressBook or false on error. |
||
362 | */ |
||
363 | public function setAddressBook(array $properties, array $options = array()) { |
||
0 ignored issues
–
show
|
|||
364 | if (count($properties) === 0) { |
||
365 | return false; |
||
366 | } |
||
367 | if (isset($properties['displayname']) && $properties['displayname'] != '' && |
||
368 | isset($properties['uri']) && $properties['uri'] != '' && |
||
369 | isset($properties['ldapurl']) && $properties['ldapurl'] != '' && |
||
370 | isset($properties['ldappagesize']) && $properties['ldappagesize'] != '' && |
||
371 | isset($properties['ldapbasednsearch']) && $properties['ldapbasednsearch'] != '' && |
||
372 | isset($properties['ldapfilter']) && $properties['ldapfilter'] != '' && |
||
373 | isset($properties['ldapvcardconnector']) && |
||
374 | isset($properties['ldapanonymous']) && |
||
375 | ($properties['ldapanonymous']=='true' |
||
376 | || ($properties['ldapanonymous']=='false' |
||
377 | && isset($properties['ldapuser']) && $properties['ldapuser'] != '' |
||
378 | && isset($properties['ldappass']) && $properties['ldappass'] != '' |
||
379 | ) |
||
380 | ) && |
||
381 | isset($properties['ldapreadonly']) && |
||
382 | ($properties['ldapreadonly']=='true' |
||
383 | || ($properties['ldapreadonly']=='false' |
||
384 | && isset($properties['ldapbasednmodify']) && $properties['ldapbasednmodify'] != '' |
||
385 | ) |
||
386 | ) |
||
387 | ) { |
||
388 | $addressbookSettings = array(); |
||
389 | $addressbookSettings['uri'] = $properties['uri']; |
||
390 | $addressbookSettings['displayname'] = $properties['displayname']; |
||
391 | $addressbookSettings['description'] = $properties['description']; |
||
392 | $addressbookSettings['ldapurl'] = $properties['ldapurl']; |
||
393 | $addressbookSettings['ldapanonymous'] = ($properties['ldapanonymous']=='true'); |
||
394 | $addressbookSettings['ldapreadonly'] = ($properties['ldapreadonly']=='true'); |
||
395 | $addressbookSettings['ldapuser'] = ($properties['ldapanonymous']=='false')?$properties['ldapuser']:""; |
||
396 | $addressbookSettings['ldappass'] = ($properties['ldapanonymous']=='false')?base64_encode($properties['ldappass']):""; |
||
397 | $addressbookSettings['ldappagesize'] = $properties['ldappagesize']; |
||
398 | $addressbookSettings['ldapbasednsearch'] = $properties['ldapbasednsearch']; |
||
399 | $addressbookSettings['ldapfilter'] = $properties['ldapfilter']; |
||
400 | $addressbookSettings['ldapbasednmodify'] = ($properties['ldapanonymous']=='false')?$properties['ldapbasednmodify']:""; |
||
401 | $addressbookSettings['ldapconnectorid'] = $properties['ldapvcardconnector']; |
||
402 | |||
403 | if ($properties['ldapvcardconnector'] != '') { |
||
404 | $prefix = "backend_ldap_"; |
||
405 | $suffix = "_connector.xml"; |
||
406 | $path = __DIR__ . "/../../formats/"; |
||
407 | if (file_exists( $path.$prefix.$properties['ldapvcardconnector'].$suffix )) { |
||
408 | $addressbookSettings['ldap_vcard_connector'] = file_get_contents ( $path.$prefix.$properties['ldapvcardconnector'].$suffix ); |
||
409 | } |
||
410 | } else { |
||
411 | $addressbookSettings['ldap_vcard_connector'] = $properties['ldapvcardconnectorvalue']; |
||
412 | } |
||
413 | |||
414 | $addressbookList = $this->getAddressbookList(); |
||
415 | if (!in_array($properties['uri'], $addressbookList)) { |
||
416 | $addressbookList[] = $properties['uri']; |
||
417 | $this->setAddressbookList($addressbookList); |
||
418 | } |
||
419 | $this->setPreferences($properties['uri'], $addressbookSettings); |
||
420 | $this->setActive(1, $properties['uri']); |
||
0 ignored issues
–
show
1 is of type integer , but the function expects a boolean .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
421 | return $properties['uri']; |
||
422 | } |
||
423 | return false; |
||
424 | } |
||
425 | |||
426 | /** |
||
427 | * Deletes an entire addressbook and all its contents |
||
428 | * |
||
429 | * @param string $addressbookid |
||
430 | * @return bool |
||
431 | */ |
||
432 | public function deleteAddressBook($addressbookid, array $options = array()) { |
||
0 ignored issues
–
show
|
|||
433 | //$addressbook = self::getAddressBook($addressbookid); |
||
434 | $addressbookList = $this->getAddressbookList(); |
||
435 | $toRemove = array_search($addressbookid, $addressbookList); |
||
436 | if (is_int($toRemove)) { |
||
437 | unset($addressbookList[$toRemove]); |
||
438 | $addressbookList = array_values($addressbookList); |
||
439 | $this->setAddressbookList($addressbookList); |
||
440 | } |
||
441 | |||
442 | self::removePreferences($addressbookid); |
||
443 | |||
444 | // TODO: use backend settings |
||
445 | return true; |
||
446 | } |
||
447 | |||
448 | /** |
||
449 | * Returns all contacts for a specific addressbook id. |
||
450 | * |
||
451 | * The returned array MUST contain the unique ID of the contact mapped to 'id', a |
||
452 | * displayname mapped to 'displayname' and an integer 'permissions' value using there |
||
453 | * ownCloud CRUDS constants (which MUST be at least \OCP\PERMISSION_READ), and SHOULD |
||
454 | * contain the properties of the contact formatted as a vCard 3.0 |
||
455 | * https://tools.ietf.org/html/rfc2426 mapped to 'carddata' or as an |
||
456 | * \OCA\Contacts\VObject\VCard object mapped to 'vcard'. |
||
457 | * |
||
458 | * Example: |
||
459 | * |
||
460 | * array( |
||
461 | * 0 => array('id' => '4e111fef5df', 'permissions' => 1, 'displayname' => 'John Q. Public', 'vcard' => $object), |
||
462 | * 1 => array('id' => 'bbcca2d1535', 'permissions' => 32, 'displayname' => 'Jane Doe', 'carddata' => $data) |
||
463 | * ); |
||
464 | * |
||
465 | * For contacts that contain loads of data, the 'carddata' or 'vcard' MAY be omitted |
||
466 | * as it can be fetched later. |
||
467 | * |
||
468 | * TODO: Some sort of ETag? |
||
469 | * |
||
470 | * @param string $addressbookid |
||
471 | * @return array |
||
472 | */ |
||
473 | public function getContacts($addressbookid, array $options = array()) { |
||
0 ignored issues
–
show
The variable $id_array is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $one_id is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $a_card is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
474 | $backtrace = debug_backtrace(); |
||
475 | $trace=array(); |
||
476 | foreach ($backtrace as $elt) { |
||
477 | foreach ($elt as $key => $line) { |
||
478 | if ($key == "file" || $key == "line") { |
||
479 | $trace[] = $line; |
||
480 | } |
||
481 | } |
||
482 | } |
||
483 | |||
484 | $cards = array(); |
||
485 | $vcards = array(); |
||
0 ignored issues
–
show
$vcards is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
486 | if(is_array($addressbookid) && count($addressbookid)) { |
||
487 | $id_array = $addressbookid; |
||
488 | } elseif(is_int($addressbookid) || is_string($addressbookid)) { |
||
489 | $id_array = array($addressbookid); |
||
490 | } else { |
||
491 | \OC_Log::write('contacts_ldap', __METHOD__.'. Addressbook id(s) argument is empty: '. print_r($id, true), \OC_Log::DEBUG); |
||
0 ignored issues
–
show
|
|||
492 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type declared by the abstract method OCA\Contacts\Backend\AbstractBackend::getContacts of type array .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
493 | } |
||
494 | |||
495 | foreach ($id_array as $one_id) { |
||
496 | if (self::setLdapParams($one_id)) { |
||
497 | //OCP\Util::writeLog('contacts_ldap', __METHOD__.' Connector OK', \OC_Log::DEBUG); |
||
498 | $info = self::ldapFindMultiple( |
||
499 | $this->ldapParams['ldapbasednsearch'], |
||
500 | $this->ldapParams['ldapfilter'], |
||
501 | $this->connector->getLdapEntries(), |
||
502 | isset($options['offset']) ? $options['offset'] : null, |
||
503 | isset($options['limit']) ? $options['limit'] : null |
||
504 | ); |
||
505 | for ($i=0; $i<$info["count"]; $i++) { |
||
506 | $a_card = $this->connector->ldapToVCard($info[$i]); |
||
507 | $cards[] = self::getSabreFormatCard($addressbookid, $a_card); |
||
508 | } |
||
509 | //OCP\Util::writeLog('contacts_ldap', __METHOD__.' counts '.count($cards), \OC_Log::DEBUG); |
||
510 | } |
||
511 | } |
||
512 | return $cards; |
||
513 | } |
||
514 | |||
515 | /** |
||
516 | * Returns a specfic contact. |
||
517 | * |
||
518 | * Same as getContacts except that either 'carddata' or 'vcard' is mandatory. |
||
519 | * |
||
520 | * @param string $addressbookid |
||
521 | * @param mixed $ids |
||
522 | * @return array|bool |
||
523 | */ |
||
524 | public function getContact($addressbookid, $ids, array $options = array()) { |
||
0 ignored issues
–
show
The variable $a_ids is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
525 | if (!is_array($ids)) { |
||
526 | $a_ids = array($ids); |
||
527 | } else { |
||
528 | $a_ids = $ids; |
||
529 | } |
||
530 | |||
531 | $cards = array(); |
||
0 ignored issues
–
show
$cards is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
532 | $toReturn = false; |
||
0 ignored issues
–
show
$toReturn is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
533 | if (self::setLdapParams($addressbookid)) { |
||
534 | foreach ($a_ids as $id) { |
||
535 | $cid = str_replace(".vcf", "", $id); |
||
536 | if (ldap_explode_dn(base64_decode($cid),0) == false) { |
||
537 | $ldifEntry = $this->connector->getLdifEntry("X-URI", null); |
||
538 | $filter = ""; |
||
0 ignored issues
–
show
$filter is not used, you could remove the assignment.
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently. $myVar = 'Value';
$higher = false;
if (rand(1, 6) > 3) {
$higher = true;
} else {
$higher = false;
}
Both the ![]() |
|||
539 | if (isset($ldifEntry[0]['unassigned'])) { |
||
540 | $filter = $this->connector->getUnassignedVCardProperty() . "=X-URI:" . $cid ."*"; |
||
541 | } else { |
||
542 | $filter = $ldifEntry[0]['name'] . "=" . $cid ."*"; |
||
543 | } |
||
544 | $card = self::ldapFindOne($this->ldapParams['ldapbasednsearch'], |
||
545 | $filter, |
||
546 | $this->connector->getLdapEntries()); |
||
547 | } else { |
||
548 | $card = self::ldapFindOne(base64_decode($cid), |
||
549 | $this->ldapParams['ldapfilter'], |
||
550 | $this->connector->getLdapEntries()); |
||
551 | } |
||
552 | } |
||
553 | if ($card != null) { |
||
554 | return self::getSabreFormatCard($addressbookid, $this->connector->ldapToVCard($card)); |
||
0 ignored issues
–
show
The variable
$card does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
555 | } |
||
556 | } |
||
557 | return false; |
||
0 ignored issues
–
show
The return type of
return false; (false ) is incompatible with the return type declared by the abstract method OCA\Contacts\Backend\AbstractBackend::getContact of type array|null .
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design. Let’s take a look at an example: class Author {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
abstract class Post {
public function getAuthor() {
return 'Johannes';
}
}
class BlogPost extends Post {
public function getAuthor() {
return new Author('Johannes');
}
}
class ForumPost extends Post { /* ... */ }
function my_function(Post $post) {
echo strtoupper($post->getAuthor());
}
Our function ![]() |
|||
558 | } |
||
559 | |||
560 | /** |
||
561 | * @brief construct a vcard in Sabre format |
||
562 | * @param integer $aid Addressbook Id |
||
563 | * @param OC_VObject $vcard VCard |
||
564 | * @return array |
||
565 | */ |
||
566 | public static function getSabreFormatCard($aid, $vcard) { |
||
0 ignored issues
–
show
The variable $FN is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $UID is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $REV is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() The variable $URI is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
567 | /* |
||
568 | * array return format : |
||
569 | * array( 'id' => 'bbcca2d1535', |
||
570 | * 'permissions' => 32, |
||
571 | * 'displayname' => 'Jane Doe', |
||
572 | * 'carddata' => $data) |
||
573 | */ |
||
574 | $FN = (string)$vcard->FN; |
||
575 | $UID = (string)$vcard->UID; |
||
576 | $REV = (string)$vcard->REV; |
||
577 | if (isset($vcard->{'X-URI'})) { |
||
578 | $URI = (string)$vcard->{'X-URI'}; |
||
579 | } else if (isset($vcard->UID)) { |
||
580 | $URI = (string)$vcard->UID.'.vcf'; |
||
581 | } else { |
||
582 | $URI = (string)$vcard->{'X-LDAP-DN'}; |
||
583 | } |
||
584 | return array('id' => $UID, |
||
585 | 'permissions' => \OCP\PERMISSION_ALL, |
||
586 | 'displayname' => $FN, |
||
587 | 'carddata' => $vcard->serialize(), |
||
588 | 'uri' => $URI, |
||
589 | 'lastmodified' => $REV); |
||
590 | } |
||
591 | |||
592 | /** |
||
593 | * Creates a new contact |
||
594 | * |
||
595 | * @param string $addressbookid |
||
596 | * @return string|bool The identifier for the new contact or false on error. |
||
597 | */ |
||
598 | public function createContact($addressbookid, $contact, array $options = array()) { |
||
599 | |||
600 | $uri = isset($options['uri']) ? $options['uri'] : null; |
||
601 | |||
602 | $datetime = new \DateTime; |
||
603 | $contact->REV = $datetime->format(\DateTime::W3C); |
||
604 | |||
605 | // 2014/02/13 Sometimes, a card is created without a name (I don't like that)... |
||
606 | if (!isset($contact->N)) { |
||
607 | $generated = "nocn-".rand(0, 65535); |
||
608 | $contact->N = $generated; |
||
609 | $contact->FN = $generated; |
||
610 | } |
||
611 | |||
612 | View Code Duplication | if(!$contact instanceof VCard) { |
|
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. ![]() |
|||
613 | try { |
||
614 | $contact = Reader::read($contact); |
||
615 | } catch(\Exception $e) { |
||
616 | \OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR); |
||
617 | return false; |
||
618 | } |
||
619 | } |
||
620 | |||
621 | try { |
||
622 | $contact->validate(VCard::REPAIR|VCard::UPGRADE); |
||
0 ignored issues
–
show
It seems like
$contact is not always an object, but can also be of type null . Maybe add an additional type check?
If a variable is not always an object, we recommend to add an additional type check to ensure your method call is safe: function someFunction(A $objectMaybe = null)
{
if ($objectMaybe instanceof A) {
$objectMaybe->doSomething();
}
}
![]() |
|||
623 | } catch (\Exception $e) { |
||
624 | OCP\Util::writeLog('contacts', __METHOD__ . ' ' . |
||
625 | 'Error validating vcard: ' . $e->getMessage(), \OCP\Util::ERROR); |
||
626 | return false; |
||
627 | } |
||
628 | |||
629 | self::setLdapParams($addressbookid); |
||
630 | |||
631 | self::ldapCreateAndBindConnection(); |
||
632 | $newDN = $this->connector->getLdapId() . "=" . $contact->FN . "," . $this->ldapParams['ldapbasednmodify']; |
||
633 | $contact->{'X-LDAP-DN'} = base64_encode($newDN); |
||
634 | if ($uri!=null) { |
||
635 | $contact->{'X-URI'} = $uri; |
||
636 | } else { |
||
637 | $contact->{'X-URI'} = $contact->{'UID'}.".vcf"; |
||
638 | } |
||
639 | |||
640 | $ldifEntries = $this->connector->VCardToLdap($contact); |
||
0 ignored issues
–
show
$contact is of type object<Sabre\VObject\Com...Sabre\VObject\Property> , but the function expects a object<OCA\Contacts\Connector\VCard> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
641 | |||
642 | // Inserts the new card |
||
643 | $cardId = self::ldapAdd($newDN, $ldifEntries); |
||
644 | if ($cardId) { |
||
645 | self::ldapCloseConnection(); |
||
646 | return $contact->UID; |
||
647 | } else { |
||
648 | self::ldapCloseConnection(); |
||
649 | return false; |
||
650 | } |
||
651 | } |
||
652 | |||
653 | /** |
||
654 | * Updates a contact |
||
655 | * |
||
656 | * @param string $addressbookid |
||
657 | * @param mixed $id |
||
658 | * @param string $carddata |
||
659 | * @return bool |
||
660 | */ |
||
661 | public function updateContact($addressbookid, $id, $carddata, array $options = array()) { |
||
0 ignored issues
–
show
The variable $a_ids is not named in camelCase.
This check marks variable names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() |
|||
662 | View Code Duplication | if(!$carddata instanceof VCard) { |
|
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. ![]() |
|||
663 | try { |
||
664 | $vcard = \Sabre\VObject\Reader::read($carddata); |
||
665 | } catch(\Exception $e) { |
||
666 | \OCP\Util::writeLog('contacts', __METHOD__.', exception: '.$e->getMessage(), \OCP\Util::ERROR); |
||
667 | return false; |
||
668 | } |
||
669 | } else { |
||
670 | $vcard = $carddata; |
||
671 | } |
||
672 | |||
673 | try { |
||
674 | $vcard->validate(VCard::REPAIR|VCard::UPGRADE); |
||
675 | } catch (\Exception $e) { |
||
676 | OCP\Util::writeLog('contacts', __METHOD__ . ' ' . |
||
677 | 'Error validating vcard: ' . $e->getMessage(), \OCP\Util::ERROR); |
||
678 | return false; |
||
679 | } |
||
680 | //$vcard->REV = (new \DateTime)->format(\DateTime::W3C); |
||
681 | |||
682 | if (!is_array($id)) { |
||
683 | $a_ids = array($id); |
||
684 | } else { |
||
685 | $a_ids = $id; |
||
686 | } |
||
687 | |||
688 | self::setLdapParams($addressbookid); |
||
689 | self::ldapCreateAndBindConnection(); |
||
690 | $ldifEntries = $this->connector->VCardToLdap($vcard); |
||
0 ignored issues
–
show
$vcard is of type object<Sabre\VObject\Com...Sabre\VObject\Property> , but the function expects a object<OCA\Contacts\Connector\VCard> .
It seems like the type of the argument is not accepted by the function/method which you are calling. In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug. We suggest to add an explicit type cast like in the following example: function acceptsInteger($int) { }
$x = '123'; // string "123"
// Instead of
acceptsInteger($x);
// we recommend to use
acceptsInteger((integer) $x);
![]() |
|||
691 | foreach ($a_ids as $cid) { |
||
692 | // Never EVER modify an Ldap:dn nor a VCard:UID |
||
693 | if (isset($vcard->{'X-LDAP-DN'})) { |
||
694 | $dn = base64_decode($vcard->{'X-LDAP-DN'}); |
||
695 | } else { |
||
696 | // A little bit complicated but hopefully, we won't often go into this |
||
697 | $tmpCard = self::getContact($addressbookid, array($cid)); |
||
698 | $tmpVCard = \Sabre\VObject\Reader::read($tmpCard['carddata']); |
||
699 | $dn = base64_decode($tmpVCard->{'X-LDAP-DN'}); |
||
700 | } |
||
701 | // Updates the existing card |
||
702 | $ldifSource = self::ldapFindOne($dn, $this->ldapParams['ldapfilter'], $this->connector->getLdapEntries()); |
||
703 | $this->connector->insertEmptyEntries($ldifSource, $ldifEntries); |
||
704 | $result = self::ldapUpdate($dn, $ldifEntries); |
||
705 | } |
||
706 | self::ldapCloseConnection(); |
||
707 | return $result; |
||
0 ignored issues
–
show
The variable
$result does not seem to be defined for all execution paths leading up to this point.
If you define a variable conditionally, it can happen that it is not defined for all execution paths. Let’s take a look at an example: function myFunction($a) {
switch ($a) {
case 'foo':
$x = 1;
break;
case 'bar':
$x = 2;
break;
}
// $x is potentially undefined here.
echo $x;
}
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined. Available Fixes
![]() |
|||
708 | } |
||
709 | |||
710 | /** |
||
711 | * Deletes a contact |
||
712 | * |
||
713 | * @param string $addressbookid |
||
714 | * @param mixed $id |
||
715 | * @return bool |
||
716 | */ |
||
717 | public function deleteContact($addressbookid, $id, array $options = array()) { |
||
0 ignored issues
–
show
|
|||
718 | self::setLdapParams($addressbookid); |
||
719 | self::ldapCreateAndBindConnection(); |
||
720 | if (is_array($id)) { |
||
721 | $card = self::getContact($addressbookid, $id); |
||
722 | } else { |
||
723 | $card = self::getContact($addressbookid, array($id)); |
||
724 | } |
||
725 | if ($card) { |
||
726 | $vcard = \Sabre\VObject\Reader::read($card['carddata']); |
||
727 | $decodedId = base64_decode($vcard->{'X-LDAP-DN'}); |
||
728 | // Deletes the existing card |
||
729 | $result = self::ldapDelete($decodedId); |
||
730 | self::ldapCloseConnection(); |
||
731 | return $result; |
||
732 | } else { |
||
733 | return false; |
||
734 | } |
||
735 | } |
||
736 | |||
737 | /** |
||
738 | * @brief Get the last modification time for a contact. |
||
739 | * |
||
740 | * Must return a UNIX time stamp or null if the backend |
||
741 | * doesn't support it. |
||
742 | * |
||
743 | * @param string $addressbookid |
||
744 | * @param mixed $id |
||
745 | * @returns int | null |
||
746 | */ |
||
747 | public function lastModifiedContact($addressbookid, $id) { |
||
748 | $contact = getContact($addressbookid, $id); |
||
749 | if ($contact != null) { |
||
750 | return $contact['lastmodified']; |
||
751 | } else { |
||
752 | return null; |
||
753 | } |
||
754 | } |
||
755 | |||
756 | /** |
||
757 | * @brief sets the list of ldap addressbooks in the preferences |
||
758 | * with the list given in parameter |
||
759 | * @param the new list |
||
760 | * @returns result|false |
||
761 | */ |
||
762 | View Code Duplication | protected function setAddressbookList(array $addressbookList) { |
|
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. ![]() |
|||
763 | $key = $this->name . "_list"; |
||
764 | $data = json_encode($addressbookList); |
||
765 | |||
766 | return $data |
||
767 | ? \OCP\Config::setUserValue($this->userid, 'contacts', $key, $data) |
||
768 | : false; |
||
769 | } |
||
770 | |||
771 | /** |
||
772 | * @brief gets the list of ldap addressbooks in the preferences |
||
773 | * returns array() |
||
774 | */ |
||
775 | protected function getAddressbookList() { |
||
776 | $key = $this->name . "_list"; |
||
777 | $data = \OCP\Config::getUserValue($this->userid, 'contacts', $key, false); |
||
778 | |||
779 | return $data ? json_decode($data) : array(); |
||
780 | } |
||
781 | |||
782 | public function getSearchProvider($addressbook) { |
||
783 | return new \OCA\Contacts\AddressbookProvider($addressbook); |
||
784 | } |
||
785 | } |
||
786 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: