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 - Contact object |
||
4 | * |
||
5 | * @author Thomas Tanghus |
||
6 | * @copyright 2012-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; |
||
24 | |||
25 | use Exception; |
||
26 | use Sabre\VObject\Property; |
||
27 | use OCA\Contacts\Utils\Properties; |
||
28 | |||
29 | /** |
||
30 | * Subclass this class or implement IPIMObject interface for PIM objects |
||
31 | */ |
||
32 | |||
33 | class Contact extends VObject\VCard implements IPIMObject { |
||
34 | |||
35 | /** |
||
36 | * The name of the object type in this case VCARD. |
||
37 | * |
||
38 | * This is used when serializing the object. |
||
39 | * |
||
40 | * @var string |
||
41 | */ |
||
42 | public $name = 'VCARD'; |
||
43 | |||
44 | /** |
||
45 | * @brief language object |
||
46 | * |
||
47 | * @var \OCP\IL10N |
||
48 | */ |
||
49 | public static $l10n; |
||
50 | |||
51 | protected $props = array(); |
||
52 | |||
53 | /** |
||
54 | * Create a new Contact object |
||
55 | * |
||
56 | * @param AddressBook $parent |
||
57 | * @param Backend\AbstractBackend $backend |
||
58 | * @param mixed $data |
||
59 | */ |
||
60 | 7 | public function __construct($parent, $backend, $data = null) { |
|
61 | 7 | parent::__construct('VCARD'); |
|
62 | |||
63 | 7 | self::$l10n = $parent::$l10n; |
|
64 | //\OCP\Util::writeLog('contacts', __METHOD__ . ' , data: ' . print_r($data, true), \OCP\Util::DEBUG); |
||
65 | 7 | $this->props['parent'] = $parent; |
|
66 | 7 | $this->props['backend'] = $backend; |
|
67 | 7 | $this->props['retrieved'] = false; |
|
68 | 7 | $this->props['saved'] = false; |
|
69 | |||
70 | 7 | if (!is_null($data)) { |
|
71 | 7 | if ($data instanceof VObject\VCard) { |
|
72 | 3 | View Code Duplication | foreach ($data->children as $child) { |
73 | 3 | if($child->name === 'VERSION' || $child->name === 'PRODID') { |
|
74 | 3 | parent::__set($child->name, $child); |
|
0 ignored issues
–
show
|
|||
75 | 3 | } else { |
|
76 | 3 | $this->add($child); |
|
77 | } |
||
78 | 3 | } |
|
79 | 3 | $this->setRetrieved(true); |
|
80 | 7 | } elseif (is_array($data)) { |
|
81 | 6 | foreach ($data as $key => $value) { |
|
82 | switch ($key) { |
||
83 | 6 | case 'id': |
|
84 | 6 | $this->props['id'] = $value; |
|
85 | 6 | break; |
|
86 | 6 | case 'permissions': |
|
87 | 6 | $this->props['permissions'] = $value; |
|
88 | 6 | break; |
|
89 | 6 | case 'lastmodified': |
|
90 | 2 | $this->props['lastmodified'] = $value; |
|
91 | 2 | break; |
|
92 | 6 | case 'uri': |
|
93 | 2 | $this->props['uri'] = $value; |
|
94 | 2 | break; |
|
95 | 6 | case 'carddata': |
|
96 | 6 | $this->props['carddata'] = $value; |
|
97 | 6 | $this->retrieve(); |
|
98 | 6 | break; |
|
99 | 6 | case 'vcard': |
|
100 | $this->props['vcard'] = $value; |
||
101 | $this->retrieve(); |
||
102 | break; |
||
103 | 6 | case 'displayname': |
|
104 | 6 | case 'fullname': |
|
105 | 6 | if(is_string($value)) { |
|
106 | 6 | $this->props['displayname'] = $value; |
|
107 | 6 | $this->FN = $value; |
|
108 | // Set it to saved again as we're not actually changing anything |
||
109 | 6 | $this->setSaved(); |
|
110 | 6 | } |
|
111 | 6 | break; |
|
112 | } |
||
113 | 6 | } |
|
114 | 6 | } |
|
115 | 7 | } |
|
116 | 7 | } |
|
117 | |||
118 | /** |
||
119 | * @return array|null |
||
120 | */ |
||
121 | 2 | public function getMetaData() { |
|
122 | 2 | if (!$this->hasPermission(\OCP\Constants::PERMISSION_READ)) { |
|
123 | throw new Exception(self::$l10n->t('You do not have permissions to see this contact'), 403); |
||
124 | } |
||
125 | 2 | if (!isset($this->props['displayname'])) { |
|
126 | if (!$this->retrieve()) { |
||
127 | \OCP\Util::writeLog('contacts', __METHOD__.' error reading: '.print_r($this->props, true), \OCP\Util::ERROR); |
||
128 | return null; |
||
129 | } |
||
130 | } |
||
131 | return array( |
||
132 | 2 | 'id' => $this->getId(), |
|
133 | 2 | 'displayname' => $this->getDisplayName(), |
|
134 | 2 | 'permissions' => $this->getPermissions(), |
|
135 | 2 | 'lastmodified' => $this->lastModified(), |
|
136 | 2 | 'owner' => $this->getOwner(), |
|
137 | 2 | 'parent' => $this->getParent()->getId(), |
|
138 | 2 | 'backend' => $this->getBackend()->name, |
|
139 | 2 | ); |
|
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get a unique key combined of backend name, address book id and contact id. |
||
144 | * |
||
145 | * @return string |
||
146 | */ |
||
147 | public function combinedKey() { |
||
148 | return $this->getBackend()->name . '::' . $this->getParent()->getId() . '::' . $this->getId(); |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * @return string|null |
||
153 | */ |
||
154 | 2 | public function getOwner() { |
|
155 | 2 | return isset($this->props['owner']) |
|
156 | 2 | ? $this->props['owner'] |
|
157 | 2 | : $this->getParent()->getOwner(); |
|
158 | } |
||
159 | |||
160 | /** |
||
161 | * @return string|null |
||
162 | */ |
||
163 | 8 | public function getId() { |
|
164 | 8 | return isset($this->props['id']) ? $this->props['id'] : null; |
|
165 | } |
||
166 | |||
167 | /** |
||
168 | * @return string|null |
||
169 | */ |
||
170 | 5 | public function getDisplayName() { |
|
171 | 5 | if (!$this->hasPermission(\OCP\Constants::PERMISSION_READ)) { |
|
172 | throw new Exception(self::$l10n->t('You do not have permissions to see this contact'), 403); |
||
173 | } |
||
174 | 5 | return isset($this->props['displayname']) |
|
175 | 5 | ? $this->props['displayname'] |
|
176 | 5 | : (isset($this->FN) ? $this->FN : null); |
|
177 | } |
||
178 | |||
179 | /** |
||
180 | * @return string|null |
||
181 | */ |
||
182 | public function getURI() { |
||
183 | return isset($this->props['uri']) ? $this->props['uri'] : null; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * @return string |
||
188 | * TODO: Cache result. |
||
189 | */ |
||
190 | public function getETag() { |
||
191 | $this->retrieve(); |
||
192 | return md5($this->serialize()); |
||
193 | } |
||
194 | |||
195 | /** |
||
196 | * If this object is part of a collection return a reference |
||
197 | * to the parent object, otherwise return null. |
||
198 | * @return IPIMObject|null |
||
199 | */ |
||
200 | 7 | public function getParent() { |
|
201 | 7 | return $this->props['parent']; |
|
202 | } |
||
203 | |||
204 | 3 | public function getBackend() { |
|
205 | 3 | return $this->props['backend']; |
|
206 | } |
||
207 | |||
208 | /** CRUDS permissions (Create, Read, Update, Delete, Share) |
||
209 | * |
||
210 | * @return integer |
||
211 | */ |
||
212 | 6 | public function getPermissions() { |
|
213 | 6 | return isset($this->props['permissions']) |
|
214 | 6 | ? $this->props['permissions'] |
|
215 | 6 | : $this->getParent()->getPermissions(); |
|
216 | } |
||
217 | |||
218 | /** |
||
219 | * @param integer $permission |
||
220 | * @return integer |
||
221 | */ |
||
222 | 6 | public function hasPermission($permission) { |
|
223 | 6 | return $this->getPermissions() & $permission; |
|
224 | } |
||
225 | |||
226 | /** |
||
227 | * Save the address book data to backend |
||
228 | * FIXME |
||
229 | * |
||
230 | * @param array $data |
||
231 | * @return bool |
||
232 | */ |
||
233 | /* public function update(array $data) { |
||
234 | |||
235 | foreach($data as $key => $value) { |
||
236 | switch($key) { |
||
237 | case 'displayname': |
||
238 | $this->addressBookInfo['displayname'] = $value; |
||
239 | break; |
||
240 | case 'description': |
||
241 | $this->addressBookInfo['description'] = $value; |
||
242 | break; |
||
243 | } |
||
244 | } |
||
245 | return $this->props['backend']->updateContact( |
||
246 | $this->getParent()->getId(), |
||
247 | $this->getId(), |
||
248 | $this |
||
249 | ); |
||
250 | } |
||
251 | */ |
||
252 | /** |
||
253 | * Delete the data from backend |
||
254 | * |
||
255 | * FIXME: Should be removed as it could leave the parent with a dataless object. |
||
256 | * |
||
257 | * @return bool |
||
258 | */ |
||
259 | public function delete() { |
||
260 | if (!$this->hasPermission(\OCP\Constants::PERMISSION_DELETE)) { |
||
261 | throw new Exception(self::$l10n->t('You do not have permissions to delete this contact'), 403); |
||
262 | } |
||
263 | return $this->props['backend']->deleteContact( |
||
264 | $this->getParent()->getId(), |
||
265 | $this->getId() |
||
266 | ); |
||
267 | } |
||
268 | |||
269 | /** |
||
270 | * Save the contact data to backend |
||
271 | * |
||
272 | * @return bool |
||
273 | */ |
||
274 | 3 | public function save($force = false) { |
|
275 | 3 | if (!$this->hasPermission(\OCP\Constants::PERMISSION_UPDATE)) { |
|
276 | throw new Exception(self::$l10n->t('You do not have permissions to update this contact'), 403); |
||
277 | } |
||
278 | 3 | if ($this->isSaved() && !$force) { |
|
279 | \OCP\Util::writeLog('contacts', __METHOD__.' Already saved: ' . print_r($this->props, true), \OCP\Util::DEBUG); |
||
280 | return true; |
||
281 | } |
||
282 | |||
283 | 3 | if (isset($this->FN)) { |
|
284 | 3 | $this->props['displayname'] = (string)$this->FN; |
|
285 | 3 | } |
|
286 | |||
287 | 3 | if ($this->getId()) { |
|
288 | if (!$this->getBackend()->hasContactMethodFor(\OCP\Constants::PERMISSION_UPDATE)) { |
||
289 | throw new Exception(self::$l10n->t('The backend for this contact does not support updating it'), 501); |
||
290 | } |
||
291 | if ($this->getBackend() |
||
292 | ->updateContact( |
||
293 | $this->getParent()->getId(), |
||
294 | $this->getId(), |
||
295 | $this |
||
296 | ) |
||
297 | ) { |
||
298 | $this->props['lastmodified'] = time(); |
||
299 | $this->setSaved(true); |
||
300 | return true; |
||
301 | } else { |
||
302 | return false; |
||
303 | } |
||
304 | } else { |
||
305 | 3 | if (!$this->getBackend()->hasContactMethodFor(\OCP\Constants::PERMISSION_CREATE)) { |
|
306 | throw new Exception(self::$l10n->t('This backend does not support adding contacts'), 501); |
||
307 | } |
||
308 | 3 | $this->props['id'] = $this->getBackend()->createContact( |
|
309 | 3 | $this->getParent()->getId(), $this |
|
310 | 3 | ); |
|
311 | 3 | $this->setSaved(true); |
|
312 | 3 | return $this->getId() !== false; |
|
313 | } |
||
314 | } |
||
315 | |||
316 | /** |
||
317 | * Get the data from the backend |
||
318 | * FIXME: Clean this up and make sure the logic is OK. |
||
319 | * |
||
320 | * @return bool |
||
321 | */ |
||
322 | 7 | public function retrieve() { |
|
323 | 6 | if ($this->isRetrieved()) { |
|
324 | //\OCP\Util::writeLog('contacts', __METHOD__. ' children', \OCP\Util::DEBUG); |
||
325 | 6 | return true; |
|
326 | } else { |
||
327 | 6 | $data = null; |
|
328 | 6 | if(isset($this->props['vcard']) |
|
329 | 6 | && $this->props['vcard'] instanceof VObject\VCard) { |
|
330 | foreach($this->props['vcard']->children() as $child) { |
||
331 | if($child->name === 'VERSION' || $child->name === 'PRODID') { |
||
332 | parent::__set($child->name, $child); |
||
333 | } else { |
||
334 | $this->add($child); |
||
335 | } |
||
336 | if($child->name === 'FN') { |
||
337 | $this->props['displayname'] |
||
338 | = strtr($child->getValue(), array('\,' => ',', '\;' => ';', '\\\\' => '\\')); |
||
339 | } |
||
340 | } |
||
341 | $this->setRetrieved(true); |
||
342 | $this->setSaved(true); |
||
343 | //$this->children = $this->props['vcard']->children(); |
||
344 | unset($this->props['vcard']); |
||
345 | return true; |
||
346 | 6 | } elseif (!isset($this->props['carddata'])) { |
|
347 | 4 | $result = $this->props['backend']->getContact( |
|
348 | 4 | $this->getParent()->getId(), |
|
349 | 4 | $this->getId() |
|
350 | 4 | ); |
|
351 | 4 | if ($result) { |
|
352 | 4 | if (isset($result['vcard']) |
|
353 | 4 | && $result['vcard'] instanceof VObject\VCard) { |
|
354 | View Code Duplication | foreach ($result['vcard']->children() as $child) { |
|
355 | if($child->name === 'VERSION' || $child->name === 'PRODID') { |
||
356 | parent::__set($child->name, $child); |
||
0 ignored issues
–
show
It seems like you call parent on a different method (
__set() instead of retrieve() ). Are you sure this is correct? If so, you might want to change this to $this->__set() .
This check looks for a call to a parent method whose name is different than the method from which it is called. Consider the following code: class Daddy
{
protected function getFirstName()
{
return "Eidur";
}
protected function getSurName()
{
return "Gudjohnsen";
}
}
class Son
{
public function getFirstName()
{
return parent::getSurname();
}
}
The ![]() |
|||
357 | } else { |
||
358 | $this->add($child); |
||
359 | } |
||
360 | } |
||
361 | $this->setRetrieved(true); |
||
362 | return true; |
||
363 | 4 | } elseif (isset($result['carddata'])) { |
|
364 | // Save internal values |
||
365 | 4 | $data = $result['carddata']; |
|
366 | 4 | $this->props['carddata'] = $result['carddata']; |
|
367 | 4 | $this->props['lastmodified'] = isset($result['lastmodified']) |
|
368 | 4 | ? $result['lastmodified'] |
|
369 | 4 | : null; |
|
370 | 4 | $this->props['displayname'] = $result['displayname']; |
|
371 | 4 | $this->props['permissions'] = $result['permissions']; |
|
372 | 4 | } else { |
|
373 | \OCP\Util::writeLog('contacts', __METHOD__ |
||
374 | . ' Could not get vcard or carddata: ' |
||
375 | . $this->getId() |
||
376 | . print_r($result, true), \OCP\Util::DEBUG); |
||
377 | return false; |
||
378 | } |
||
379 | 4 | } else { |
|
380 | \OCP\Util::writeLog('contacts', __METHOD__.' Error getting contact: ' . $this->getId(), \OCP\Util::DEBUG); |
||
381 | } |
||
382 | 7 | } elseif (isset($this->props['carddata'])) { |
|
383 | 2 | $data = $this->props['carddata']; |
|
384 | 2 | } |
|
385 | try { |
||
386 | 6 | $obj = \Sabre\VObject\Reader::read( |
|
387 | 6 | $data, |
|
388 | \Sabre\VObject\Reader::OPTION_IGNORE_INVALID_LINES |
||
389 | 6 | ); |
|
390 | 6 | if ($obj) { |
|
391 | 6 | View Code Duplication | foreach ($obj->children as $child) { |
392 | 6 | if($child->name === 'VERSION' || $child->name === 'PRODID') { |
|
393 | 6 | parent::__set($child->name, $child); |
|
394 | 6 | } else { |
|
395 | 6 | $this->add($child); |
|
396 | } |
||
397 | 6 | } |
|
398 | 6 | $this->setRetrieved(true); |
|
399 | 6 | $this->setSaved(true); |
|
400 | 6 | } else { |
|
401 | \OCP\Util::writeLog('contacts', __METHOD__.' Error reading: ' . print_r($data, true), \OCP\Util::DEBUG); |
||
402 | return false; |
||
403 | } |
||
404 | 6 | } catch (Exception $e) { |
|
405 | \OCP\Util::writeLog('contacts', __METHOD__ . |
||
406 | ' Error parsing carddata for: ' . $this->getId() . ' ' . $e->getMessage(), |
||
407 | \OCP\Util::ERROR); |
||
408 | return false; |
||
409 | } |
||
410 | } |
||
411 | 6 | return true; |
|
412 | } |
||
413 | |||
414 | /** |
||
415 | * Get the PHOTO or LOGO |
||
416 | * |
||
417 | * @return \OCP\Image|null |
||
418 | */ |
||
419 | public function getPhoto() { |
||
420 | $image = new \OCP\Image(); |
||
421 | |||
422 | if (isset($this->PHOTO)) { |
||
423 | $photo = $this->PHOTO; |
||
424 | } elseif (isset($this->LOGO)) { |
||
425 | $photo = $this->LOGO; |
||
426 | } else { |
||
427 | return null; |
||
428 | } |
||
429 | |||
430 | $photovalue = $photo->getValue(); |
||
431 | |||
432 | if ( $photo instanceof \Sabre\VObject\Property\Uri && substr($photovalue, 0, 5) === 'data:' ) { |
||
0 ignored issues
–
show
The class
Sabre\VObject\Property\Uri does not exist. Did you forget a USE statement, or did you not list all dependencies?
This error could be the result of: 1. Missing dependenciesPHP Analyzer uses your Are you sure this class is defined by one of your dependencies, or did you maybe
not list a dependency in either the 2. Missing use statementPHP does not complain about undefined classes in if ($x instanceof DoesNotExist) {
// Do something.
}
If you have not tested against this specific condition, such errors might go unnoticed. ![]() |
|||
433 | $mimeType = substr($photovalue, 5, strpos($photovalue, ',')-5); |
||
434 | if (strpos($mimeType, ';')) { |
||
435 | $mimeType = substr($mimeType,0,strpos($mimeType, ';')); |
||
0 ignored issues
–
show
$mimeType 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 ![]() |
|||
436 | } |
||
437 | |||
438 | $photovalue = substr($photovalue, strpos($photovalue,',')+1); |
||
439 | |||
440 | if ($image->loadFromBase64($photovalue)) { |
||
0 ignored issues
–
show
|
|||
441 | return $image; |
||
0 ignored issues
–
show
|
|||
442 | } |
||
443 | } elseif ($image->loadFromData($photovalue)) { |
||
444 | return $image; |
||
445 | } |
||
446 | |||
447 | return null; |
||
448 | } |
||
449 | |||
450 | /** |
||
451 | * Set the contact photo. |
||
452 | * |
||
453 | * @param \OCP\Image $photo |
||
454 | */ |
||
455 | public function setPhoto(\OCP\Image $photo) { |
||
456 | // For vCard 3.0 the type must be e.g. JPEG or PNG |
||
457 | // For version 4.0 the full mimetype should be used. |
||
458 | // https://tools.ietf.org/html/rfc2426#section-3.1.4 |
||
459 | if (isset($this->PHOTO)) { |
||
460 | $this->remove('PHOTO'); |
||
461 | } |
||
462 | if (strval($this->VERSION) === '4.0') { |
||
463 | $type = $photo->mimeType(); |
||
464 | $this->add('PHOTO', 'data:'.$type.';base64,'.base64_encode($photo->data())); |
||
465 | } else { |
||
466 | $type = explode('/', $photo->mimeType()); |
||
467 | $type = strtoupper(array_pop($type)); |
||
468 | $this->add('PHOTO', $photo->data(), ['ENCODING' => 'b', 'TYPE' => $type]); |
||
469 | } |
||
470 | $this->setSaved(false); |
||
471 | |||
472 | return true; |
||
473 | } |
||
474 | |||
475 | /** |
||
476 | * Get a property index in the contact by the checksum of its serialized value |
||
477 | * |
||
478 | * @param string $checksum An 8 char m5d checksum. |
||
479 | * @return integer Property by reference |
||
480 | * @throws Exception with error code 404 if the property is not found. |
||
481 | */ |
||
482 | public function getPropertyIndexByChecksum($checksum) { |
||
483 | $this->retrieve(); |
||
484 | $idx = 0; |
||
485 | View Code Duplication | foreach ($this->children as $i => &$property) { |
|
486 | if (substr(md5($property->serialize()), 0, 8) == $checksum ) { |
||
487 | return $idx; |
||
488 | } |
||
489 | $idx += 1; |
||
490 | } |
||
491 | throw new Exception(self::$l10n->t('Property not found'), 404); |
||
492 | } |
||
493 | |||
494 | /** |
||
495 | * Get a property by the checksum of its serialized value |
||
496 | * |
||
497 | * @param string $checksum An 8 char m5d checksum. |
||
498 | * @return \Sabre\VObject\Property Property by reference |
||
499 | * @throws Exception with error code 404 if the property is not found. |
||
500 | */ |
||
501 | public function getPropertyByChecksum($checksum) { |
||
502 | $this->retrieve(); |
||
503 | View Code Duplication | foreach ($this->children as $i => &$property) { |
|
504 | if (substr(md5($property->serialize()), 0, 8) == $checksum ) { |
||
505 | return $property; |
||
506 | } |
||
507 | } |
||
508 | throw new Exception(self::$l10n->t('Property not found'), 404); |
||
509 | } |
||
510 | |||
511 | /** |
||
512 | * Delete a property by the checksum of its serialized value |
||
513 | * It is up to the caller to call ->save() |
||
514 | * |
||
515 | * @param string $checksum An 8 char m5d checksum. |
||
516 | * @throws @see getPropertyByChecksum |
||
517 | */ |
||
518 | public function unsetPropertyByChecksum($checksum) { |
||
519 | $idx = $this->getPropertyIndexByChecksum($checksum); |
||
520 | unset($this->children[$idx]); |
||
521 | $this->setSaved(false); |
||
522 | } |
||
523 | |||
524 | /** |
||
525 | * Set a property by the checksum of its serialized value |
||
526 | * It is up to the caller to call ->save() |
||
527 | * |
||
528 | * @param string $checksum An 8 char m5d checksum. |
||
529 | * @param string $name Property name |
||
530 | * @param mixed $value |
||
531 | * @param array $parameters |
||
532 | * @throws @see getPropertyByChecksum |
||
533 | * @return string new checksum |
||
534 | */ |
||
535 | public function setPropertyByChecksum($checksum, $name, $value, $parameters=array()) { |
||
536 | if ($checksum === 'new') { |
||
537 | $property = $this->createProperty($name); |
||
538 | $this->add($property); |
||
539 | } else { |
||
540 | $property = $this->getPropertyByChecksum($checksum); |
||
541 | } |
||
542 | switch ($name) { |
||
543 | case 'EMAIL': |
||
544 | case 'CLOUD': |
||
545 | $value = strtolower($value); |
||
546 | $property->setValue($value); |
||
547 | break; |
||
548 | case 'ADR': |
||
549 | if(is_array($value)) { |
||
550 | $property->setParts($value); |
||
551 | } else { |
||
552 | $property->setValue($value); |
||
553 | } |
||
554 | break; |
||
555 | case 'IMPP': |
||
556 | if (is_null($parameters) || !isset($parameters['X-SERVICE-TYPE'])) { |
||
557 | throw new \InvalidArgumentException(self::$l10n->t(' Missing IM parameter for: ') . $name. ' ' . $value, 412); |
||
558 | } |
||
559 | $serviceType = $parameters['X-SERVICE-TYPE']; |
||
560 | if (is_array($serviceType)) { |
||
561 | $serviceType = $serviceType[0]; |
||
562 | } |
||
563 | $impp = Utils\Properties::getIMOptions($serviceType); |
||
564 | if (is_null($impp)) { |
||
565 | throw new \UnexpectedValueException(self::$l10n->t('Unknown IM: ') . $serviceType, 415); |
||
566 | } |
||
567 | $value = $impp['protocol'] . ':' . $value; |
||
568 | $property->setValue($value); |
||
569 | break; |
||
570 | View Code Duplication | default: |
|
571 | \OCP\Util::writeLog('contacts', __METHOD__.' adding: '.$name. ' ' . $value, \OCP\Util::DEBUG); |
||
572 | $property->setValue($value); |
||
573 | break; |
||
574 | } |
||
575 | $this->setParameters($property, $parameters, true); |
||
576 | $this->setSaved(false); |
||
577 | return substr(md5($property->serialize()), 0, 8); |
||
578 | } |
||
579 | |||
580 | /** |
||
581 | * Set a property by the property name. |
||
582 | * It is up to the caller to call ->save() |
||
583 | * |
||
584 | * @param string $name Property name |
||
585 | * @param mixed $value |
||
586 | * @param array $parameters |
||
587 | * @return bool |
||
588 | 2 | */ |
|
589 | public function setPropertyByName($name, $value, $parameters=array()) { |
||
590 | // TODO: parameters are ignored for now. |
||
591 | switch ($name) { |
||
592 | case 'BDAY': |
||
593 | try { |
||
594 | $date = New \DateTime($value); |
||
595 | } catch(Exception $e) { |
||
596 | \OCP\Util::writeLog('contacts', |
||
597 | __METHOD__.' DateTime exception: ' . $e->getMessage(), |
||
598 | \OCP\Util::ERROR |
||
599 | ); |
||
600 | return false; |
||
601 | } |
||
602 | $value = $date->format('Y-m-d'); |
||
603 | $this->BDAY = $value; |
||
604 | $this->BDAY->add('VALUE', 'DATE'); |
||
605 | //\OCP\Util::writeLog('contacts', __METHOD__.' BDAY: '.$this->BDAY->serialize(), \OCP\Util::DEBUG); |
||
606 | 2 | break; |
|
607 | case 'CATEGORIES': |
||
608 | case 'N': |
||
609 | case 'ORG': |
||
610 | $property = $this->select($name); |
||
611 | 2 | if (count($property) === 0) { |
|
612 | $property = $this->createProperty($name); |
||
613 | $this->add($property); |
||
614 | View Code Duplication | } elseif (count($property) > 1) { |
|
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. ![]() |
|||
615 | \OCP\Util::writeLog('contacts', |
||
616 | __METHOD__.' more than one property for ' . $name, |
||
617 | \OCP\Util::ERROR |
||
618 | 2 | ); |
|
619 | return false; |
||
620 | } else { |
||
621 | // select returns an array... |
||
622 | $property = array_shift($property); |
||
623 | } |
||
624 | if (($name === 'N') && !is_array($value)) { |
||
625 | $value = explode(';', (string)$value); |
||
626 | } |
||
627 | if (is_array($value)) { |
||
628 | $property->setParts($value); |
||
629 | } else { |
||
630 | $property->setValue($value); |
||
631 | } |
||
632 | break; |
||
633 | View Code Duplication | default: |
|
634 | \OCP\Util::writeLog('contacts', __METHOD__.' adding: '.$name. ' ' . $value, \OCP\Util::DEBUG); |
||
635 | $this->{$name} = $value; |
||
636 | break; |
||
637 | } |
||
638 | $this->setSaved(false); |
||
639 | return true; |
||
640 | } |
||
641 | |||
642 | protected function setParameters($property, $parameters, $reset = false) { |
||
643 | if (!$parameters) { |
||
644 | return; |
||
645 | } |
||
646 | |||
647 | if ($reset) { |
||
648 | $property->parameters = array(); |
||
649 | } |
||
650 | //debug('Setting parameters: ' . print_r($parameters, true)); |
||
651 | foreach ($parameters as $key => $parameter) { |
||
652 | //debug('Adding parameter: ' . $key); |
||
653 | if (is_array($parameter)) { |
||
654 | foreach ($parameter as $val) { |
||
655 | if (is_array($val)) { |
||
656 | foreach ($val as $val2) { |
||
657 | if (trim($key) && trim($val2)) { |
||
658 | //debug('Adding parameter: '.$key.'=>'.print_r($val2, true)); |
||
659 | $property->add($key, strip_tags($val2)); |
||
660 | } |
||
661 | } |
||
662 | } else { |
||
663 | if (trim($key) && trim($val)) { |
||
664 | //debug('Adding parameter: '.$key.'=>'.print_r($val, true)); |
||
665 | $property->add($key, strip_tags($val)); |
||
666 | } |
||
667 | } |
||
668 | } |
||
669 | } else { |
||
670 | if (trim($key) && trim($parameter)) { |
||
671 | //debug('Adding parameter: '.$key.'=>'.print_r($parameter, true)); |
||
672 | $property->add($key, strip_tags($parameter)); |
||
673 | } |
||
674 | } |
||
675 | } |
||
676 | } |
||
677 | 2 | ||
678 | 2 | public function lastModified() { |
|
679 | if (!isset($this->props['lastmodified']) && !$this->isRetrieved()) { |
||
680 | $this->retrieve(); |
||
681 | 2 | } |
|
682 | 2 | return isset($this->props['lastmodified']) |
|
683 | 2 | ? $this->props['lastmodified'] |
|
684 | : null; |
||
685 | } |
||
686 | |||
687 | /** |
||
688 | * Merge in data from a multi-dimentional array |
||
689 | * |
||
690 | * NOTE: The data has actually already been merged client side! |
||
691 | * NOTE: The only properties coming from the web client are the ones |
||
692 | * defined in \OCA\Contacts\Utils\Properties::$indexProperties and |
||
693 | * UID is skipped for obvious reasons, and PHOTO is currently not updated. |
||
694 | * The data array has this structure: |
||
695 | * |
||
696 | * array( |
||
697 | * 'EMAIL' => array(array('value' => '[email protected]', 'parameters' = array('TYPE' => array('HOME','VOICE')))) |
||
698 | * ); |
||
699 | * @param array $data |
||
700 | * @return bool |
||
701 | */ |
||
702 | public function mergeFromArray(array $data) { |
||
703 | foreach ($data as $name => $properties) { |
||
704 | if (in_array($name, array('PHOTO', 'UID'))) { |
||
705 | continue; |
||
706 | } |
||
707 | View Code Duplication | if (!is_array($properties)) { |
|
708 | \OCP\Util::writeLog('contacts', __METHOD__.' not an array?: ' .$name. ' '.print_r($properties, true), \OCP\Util::DEBUG); |
||
709 | } |
||
710 | if (in_array($name, Utils\Properties::$multiProperties)) { |
||
711 | unset($this->{$name}); |
||
712 | } |
||
713 | foreach ($properties as $parray) { |
||
714 | \OCP\Util::writeLog('contacts', __METHOD__.' adding: ' .$name. ' '.print_r($parray['value'], true) . ' ' . print_r($parray['parameters'], true), \OCP\Util::DEBUG); |
||
715 | if (in_array($name, Utils\Properties::$multiProperties)) { |
||
716 | // TODO: wrap in try/catch, check return value |
||
717 | $this->setPropertyByChecksum('new', $name, $parray['value'], $parray['parameters']); |
||
718 | } else { |
||
719 | // TODO: Check return value |
||
720 | if (!isset($this->{$name})) { |
||
721 | $this->setPropertyByName($name, $parray['value'], $parray['parameters']); |
||
722 | } |
||
723 | } |
||
724 | } |
||
725 | } |
||
726 | $this->setSaved(false); |
||
727 | return true; |
||
728 | } |
||
729 | 3 | ||
730 | 3 | public function __get($key) { |
|
731 | if (!$this->isRetrieved()) { |
||
732 | $this->retrieve(); |
||
733 | } |
||
734 | 3 | ||
735 | return parent::__get($key); |
||
736 | } |
||
737 | 3 | ||
738 | 3 | public function __isset($key) { |
|
739 | if (!$this->isRetrieved()) { |
||
740 | $this->retrieve(); |
||
741 | } |
||
742 | 3 | ||
743 | return parent::__isset($key); |
||
744 | } |
||
745 | 6 | ||
746 | 6 | public function __set($key, $value) { |
|
747 | 4 | if (!$this->isRetrieved()) { |
|
748 | 4 | $this->retrieve(); |
|
749 | 6 | } |
|
750 | 6 | parent::__set($key, $value); |
|
751 | 6 | if ($key === 'FN') { |
|
752 | 6 | $this->props['displayname'] = $value; |
|
753 | 6 | } |
|
754 | 6 | $this->setSaved(false); |
|
755 | } |
||
756 | |||
757 | public function __unset($key) { |
||
758 | if (!$this->isRetrieved()) { |
||
759 | $this->retrieve(); |
||
760 | } |
||
761 | parent::__unset($key); |
||
762 | if ($key === 'PHOTO') { |
||
763 | Properties::cacheThumbnail( |
||
764 | $this->getBackend()->name, |
||
765 | $this->getParent()->getId(), |
||
766 | $this->getId(), |
||
767 | null, |
||
768 | $this, |
||
769 | array('remove' => true) |
||
770 | ); |
||
771 | } |
||
772 | $this->setSaved(false); |
||
773 | } |
||
774 | |||
775 | /** |
||
776 | * @param boolean $state |
||
777 | 7 | */ |
|
778 | 7 | public function setRetrieved($state) { |
|
779 | 7 | $this->props['retrieved'] = $state; |
|
780 | } |
||
781 | 7 | ||
782 | 7 | public function isRetrieved() { |
|
783 | return $this->props['retrieved']; |
||
784 | } |
||
785 | 7 | ||
786 | 7 | public function setSaved($state = true) { |
|
787 | 7 | $this->props['saved'] = $state; |
|
788 | } |
||
789 | 3 | ||
790 | 3 | public function isSaved() { |
|
791 | return $this->props['saved']; |
||
792 | } |
||
793 | |||
794 | /** |
||
795 | * Generate an event to show in the calendar |
||
796 | * |
||
797 | * @return \Sabre\VObject\Component\VCalendar|null |
||
798 | */ |
||
799 | public function getBirthdayEvent() { |
||
800 | if (!isset($this->BDAY)) { |
||
801 | return null; |
||
802 | } |
||
803 | $birthday = $this->BDAY; |
||
804 | if ((string)$birthday) { |
||
805 | $title = str_replace('{name}', |
||
806 | strtr((string)$this->FN, array('\,' => ',', '\;' => ';')), |
||
807 | App::$l10n->t('{name}\'s Birthday') |
||
808 | ); |
||
809 | try { |
||
810 | $date = new \DateTime($birthday); |
||
811 | } catch(Exception $e) { |
||
812 | return null; |
||
813 | } |
||
814 | $vCal = new \Sabre\VObject\Component\VCalendar(); |
||
815 | $vCal->VERSION = '2.0'; |
||
816 | $vEvent = $vCal->createComponent('VEVENT'); |
||
817 | $vEvent->add('DTSTART'); |
||
818 | $vEvent->DTSTART->setDateTime( |
||
819 | $date |
||
820 | ); |
||
821 | $vEvent->DTSTART['VALUE'] = 'DATE'; |
||
822 | $vEvent->add('DTEND'); |
||
823 | $date->add(new \DateInterval('P1D')); |
||
824 | $vEvent->DTEND->setDateTime( |
||
825 | $date |
||
826 | ); |
||
827 | $vEvent->DTEND['VALUE'] = 'DATE'; |
||
828 | $lm = new \DateTime('@' . $this->lastModified()); |
||
829 | $lm->setTimeZone(new \DateTimeZone('UTC')); |
||
830 | $vEvent->DTSTAMP->setDateTime($lm); |
||
831 | $vEvent->{'UID'} = $this->UID; |
||
832 | $vEvent->{'RRULE'} = 'FREQ=YEARLY'; |
||
833 | $vEvent->{'SUMMARY'} = $title . ' (' . $date->format('Y') . ')'; |
||
834 | $vEvent->{'TRANSP'} = 'TRANSPARENT'; |
||
835 | $appInfo = \OCP\App::getAppInfo('contacts'); |
||
836 | $appVersion = \OCP\App::getAppVersion('contacts'); |
||
837 | $vCal->PRODID = '-//ownCloud//NONSGML '.$appInfo['name'].' '.$appVersion.'//EN'; |
||
838 | $vCal->add($vEvent); |
||
839 | return $vCal; |
||
840 | } |
||
841 | |||
842 | return null; |
||
843 | } |
||
844 | |||
845 | } |
||
846 |
This check looks for a call to a parent method whose name is different than the method from which it is called.
Consider the following code:
The
getFirstName()
method in theSon
calls the wrong method in the parent class.