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 namespace CardDavPHP; |
||
2 | |||
3 | /** |
||
4 | * CardDAV PHP |
||
5 | * |
||
6 | * Simple CardDAV query |
||
7 | * -------------------- |
||
8 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
9 | * $carddav->setAuth('username', 'password'); |
||
10 | * echo $carddav->get(); |
||
11 | * |
||
12 | * |
||
13 | * Simple vCard query |
||
14 | * ------------------ |
||
15 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
16 | * $carddav->setAuth('username', 'password'); |
||
17 | * echo $carddav->getVcard('0126FFB4-2EB74D0A-302EA17F'); |
||
18 | * |
||
19 | * |
||
20 | * XML vCard query |
||
21 | * ------------------ |
||
22 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
23 | * $carddav->setAuth('username', 'password'); |
||
24 | * echo $carddav->getXmlVcard('0126FFB4-2EB74D0A-302EA17F'); |
||
25 | * |
||
26 | * |
||
27 | * Check CardDAV server connection |
||
28 | * ------------------------------- |
||
29 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
30 | * $carddav->setAuth('username', 'password'); |
||
31 | * var_dump($carddav->checkConnection()); |
||
32 | * |
||
33 | * |
||
34 | * CardDAV delete query |
||
35 | * -------------------- |
||
36 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
37 | * $carddav->setAuth('username', 'password'); |
||
38 | * $carddav->delete('0126FFB4-2EB74D0A-302EA17F'); |
||
39 | * |
||
40 | * |
||
41 | * CardDAV add query |
||
42 | * -------------------- |
||
43 | * $vcard = 'BEGIN:VCARD |
||
44 | * VERSION:3.0 |
||
45 | * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b |
||
46 | * FN:Christian Putzke |
||
47 | * N:Christian;Putzke;;; |
||
48 | * EMAIL;TYPE=OTHER:[email protected] |
||
49 | * END:VCARD'; |
||
50 | * |
||
51 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
52 | * $carddav->setAuth('username', 'password'); |
||
53 | * $vcard_id = $carddav->add($vcard); |
||
54 | * |
||
55 | * |
||
56 | * CardDAV update query |
||
57 | * -------------------- |
||
58 | * $vcard = 'BEGIN:VCARD |
||
59 | * VERSION:3.0 |
||
60 | * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b |
||
61 | * FN:Christian Putzke |
||
62 | * N:Christian;Putzke;;; |
||
63 | * EMAIL;TYPE=OTHER:[email protected] |
||
64 | * END:VCARD'; |
||
65 | * |
||
66 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
67 | * $carddav->setAuth('username', 'password'); |
||
68 | * $carddav->update($vcard, '0126FFB4-2EB74D0A-302EA17F'); |
||
69 | * |
||
70 | * |
||
71 | * CardDAV debug |
||
72 | * ------------- |
||
73 | * $carddav = new CardDavBackend('https://davical.example.com/user/contacts/'); |
||
74 | * $carddav->enableDebug(); |
||
75 | * $carddav->setAuth('username', 'password'); |
||
76 | * $carddav->get(); |
||
77 | * var_dump($carddav->getDebug()); |
||
78 | * |
||
79 | * |
||
80 | * CardDAV server list |
||
81 | * ------------------- |
||
82 | * DAViCal: https://example.com/{resource|principal|username}/{collection}/ |
||
83 | * Apple Addressbook Server: https://example.com/addressbooks/users/{resource|principal|username}/{collection}/ |
||
84 | * memotoo: https://sync.memotoo.com/cardDAV/ |
||
85 | * SabreDAV: https://example.com/addressbooks/{resource|principal|username}/{collection}/ |
||
86 | * ownCloud: https://example.com/apps/contacts/carddav.php/addressbooks/{resource|principal|username}/{collection}/ |
||
87 | * SOGo: https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/ |
||
88 | * Google (direct): https://google.com/m8/carddav/principals/__uids__/{username}/lists/default/ |
||
89 | * |
||
90 | * |
||
91 | * @author Christian Putzke <[email protected]> |
||
92 | * @copyright Christian Putzke |
||
93 | * @link http://www.graviox.de/ |
||
94 | * @link https://twitter.com/cputzke/ |
||
95 | * @since 24.05.2015 |
||
96 | * @version 0.7 |
||
97 | * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later |
||
98 | * |
||
99 | */ |
||
100 | |||
101 | class CardDavBackend |
||
102 | { |
||
103 | /** |
||
104 | * CardDAV PHP Version |
||
105 | * |
||
106 | * @constant string |
||
107 | */ |
||
108 | const VERSION = '0.7'; |
||
109 | |||
110 | /** |
||
111 | * User agent displayed in http requests |
||
112 | * |
||
113 | * @constant string |
||
114 | */ |
||
115 | const USERAGENT = 'CardDAV PHP/'; |
||
116 | |||
117 | /** |
||
118 | * CardDAV server url |
||
119 | * |
||
120 | * @var string |
||
121 | */ |
||
122 | private $url = null; |
||
123 | |||
124 | /** |
||
125 | * CardDAV server url_parts |
||
126 | * |
||
127 | * @var array |
||
128 | */ |
||
129 | private $url_parts = null; |
||
130 | |||
131 | /** |
||
132 | * VCard File URL Extension |
||
133 | * |
||
134 | * @var string |
||
135 | */ |
||
136 | private $url_vcard_extension = '.vcf'; |
||
137 | |||
138 | /** |
||
139 | * Authentication string |
||
140 | * |
||
141 | * @var string |
||
142 | */ |
||
143 | private $auth = null; |
||
144 | |||
145 | /** |
||
146 | * Authentication: username |
||
147 | * |
||
148 | * @var string |
||
149 | */ |
||
150 | private $username = null; |
||
151 | |||
152 | /** |
||
153 | * Authentication: password |
||
154 | * |
||
155 | * @var string |
||
156 | */ |
||
157 | private $password = null; |
||
158 | |||
159 | /** |
||
160 | * Characters used for vCard id generation |
||
161 | * |
||
162 | * @var array |
||
163 | */ |
||
164 | private $vcard_id_chars = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'); |
||
165 | |||
166 | /** |
||
167 | * CardDAV server connection (curl handle) |
||
168 | * |
||
169 | * @var resource |
||
170 | */ |
||
171 | private $curl; |
||
172 | |||
173 | /** |
||
174 | * Follow redirects (Location Header) |
||
175 | * |
||
176 | * @var boolean |
||
177 | */ |
||
178 | private $follow_redirects = true; |
||
179 | |||
180 | /** |
||
181 | * Maximum redirects to follow |
||
182 | * |
||
183 | * @var integer |
||
184 | */ |
||
185 | private $follow_redirects_count = 3; |
||
186 | |||
187 | /** |
||
188 | * Debug on or off |
||
189 | * |
||
190 | * @var boolean |
||
191 | */ |
||
192 | private $debug = false; |
||
193 | |||
194 | /** |
||
195 | * All available debug information |
||
196 | * |
||
197 | * @var array |
||
198 | */ |
||
199 | private $debug_information = array(); |
||
200 | |||
201 | /** |
||
202 | * Exception codes |
||
203 | */ |
||
204 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET = 1000; |
||
205 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD = 1001; |
||
206 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD = 1002; |
||
207 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE = 1003; |
||
208 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD = 1004; |
||
209 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE = 1005; |
||
210 | const EXCEPTION_MALFORMED_XML_RESPONSE = 1006; |
||
211 | const EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID = 1007; |
||
212 | |||
213 | |||
214 | /** |
||
215 | * Constructor |
||
216 | * Sets the CardDAV server url |
||
217 | * |
||
218 | * @param string $url CardDAV server url |
||
219 | */ |
||
220 | public function __construct($url = null) |
||
221 | { |
||
222 | if ($url !== null) { |
||
223 | $this->setUrl($url); |
||
224 | } |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * Sets debug information |
||
229 | * |
||
230 | * @param array $debug_information Debug information |
||
231 | * @return void |
||
232 | */ |
||
233 | public function setDebug(array $debug_information) |
||
234 | { |
||
235 | $this->debug_information[] = $debug_information; |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Sets the CardDAV server url |
||
240 | * |
||
241 | * @param string $url CardDAV server url |
||
242 | * @return void |
||
243 | */ |
||
244 | public function setUrl($url) |
||
245 | { |
||
246 | $this->url = $url; |
||
247 | |||
248 | if (substr($this->url, -1, 1) !== '/') { |
||
249 | $this->url = $this->url . '/'; |
||
250 | } |
||
251 | |||
252 | $this->url_parts = parse_url($this->url); |
||
0 ignored issues
–
show
|
|||
253 | |||
254 | // workaround for providers that don't use the default .vcf extension |
||
255 | if (strpos($this->url, "google.com")) |
||
256 | { |
||
257 | $this->setVcardExtension(""); |
||
258 | } |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * Sets the CardDAV vcard url extension |
||
263 | * |
||
264 | * Most providers do requests handling Vcards with .vcf, however |
||
265 | * this isn't always the case and some providers (such as Google) |
||
266 | * returned a 404 if the .vcf extension is used - or the other |
||
267 | * way around, returning 404 unless .vcf is used. |
||
268 | * |
||
269 | * Both approaches are technically correct, see rfc635 |
||
270 | * http://tools.ietf.org/html/rfc6352 |
||
271 | * |
||
272 | * |
||
273 | * @param string $extension File extension |
||
274 | * @return void |
||
275 | */ |
||
276 | public function setVcardExtension($extension) |
||
277 | { |
||
278 | $this->url_vcard_extension = $extension; |
||
279 | } |
||
280 | |||
281 | /** |
||
282 | * Sets authentication information |
||
283 | * |
||
284 | * @param string $username CardDAV server username |
||
285 | * @param string $password CardDAV server password |
||
286 | * @return void |
||
287 | */ |
||
288 | public function setAuth($username, $password) |
||
289 | { |
||
290 | $this->username = $username; |
||
291 | $this->password = $password; |
||
292 | $this->auth = $username . ':' . $password; |
||
293 | } |
||
294 | |||
295 | /** |
||
296 | * Sets wether to follow redirects and if yes how often |
||
297 | * |
||
298 | * @param boolean $follow_redirects |
||
299 | * @param integer $follow_redirects_count |
||
300 | * @return void |
||
301 | */ |
||
302 | public function setFollowRedirects($follow_redirects, $follow_redirects_count = 3) |
||
303 | { |
||
304 | $this->follow_redirects = $follow_redirects && $follow_redirects_count > 0; |
||
305 | $this->follow_redirects_count = $follow_redirects_count > 0 ? $follow_redirects_count : 0; |
||
306 | } |
||
307 | |||
308 | /** |
||
309 | * Gets all available debug information |
||
310 | * |
||
311 | * @return array $this->debug_information All available debug information |
||
312 | */ |
||
313 | public function getDebug() |
||
314 | { |
||
315 | return $this->debug_information; |
||
316 | } |
||
317 | |||
318 | /** |
||
319 | * Gets all vCards including additional information from the CardDAV server |
||
320 | * |
||
321 | * @param boolean $include_vcards Include vCards within the response (simplified only) |
||
322 | * @param boolean $raw Get response raw or simplified |
||
323 | * @return string Raw or simplified XML response |
||
324 | */ |
||
325 | public function get($include_vcards = true, $raw = false) |
||
326 | { |
||
327 | // for owncloud&co. Doesn't work with OpenXchange/Appsuite |
||
328 | $result = $this->query($this->url, 'PROPFIND'); |
||
329 | |||
330 | // for OpenXchange/Appsuite |
||
331 | $content = '<?xml version="1.0" encoding="UTF-8" ?><D:sync-collection xmlns:D="DAV:" xmlns:C="urn:ietf:params:xml:ns:carddav"><D:sync-token></D:sync-token><D:prop><D:getcontenttype/><D:getetag/><D:allprop/><C:address-data><C:allprop/></C:address-data></D:prop><C:filter/></D:sync-collection>'; |
||
0 ignored issues
–
show
$content 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 ![]() |
|||
332 | $content_type = 'application/xml'; |
||
0 ignored issues
–
show
$content_type 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 ![]() |
|||
333 | //$result = $this->query($this->url, 'REPORT', $content, $content_type); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
64% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
334 | |||
335 | // DEBUG: print the response of the carddav-server |
||
336 | //print_r($result); |
||
337 | |||
338 | switch ($result['http_code']) |
||
339 | { |
||
340 | case 200: |
||
341 | case 207: |
||
342 | if ($raw === true) { |
||
343 | return $result['response']; |
||
344 | } else { |
||
345 | return $this->simplify($result['response'], $include_vcards); |
||
346 | } |
||
347 | } |
||
348 | |||
349 | throw new \Exception( |
||
350 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}.", |
||
351 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET |
||
352 | ); |
||
353 | |||
354 | } |
||
355 | |||
356 | /** |
||
357 | * Gets a clean vCard from the CardDAV server |
||
358 | * |
||
359 | * @param string $vcard_id vCard id on the CardDAV server |
||
360 | * @return string vCard (text/vcard) |
||
361 | */ |
||
362 | public function getVcard($vcard_id) |
||
363 | { |
||
364 | $vcard_id = str_replace($this->url_vcard_extension, null, $vcard_id); |
||
365 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'GET'); |
||
366 | |||
367 | // DEBUG: print the response of the carddav-server |
||
368 | // print_r($result); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
369 | |||
370 | switch ($result['http_code']) |
||
371 | { |
||
372 | case 404: |
||
373 | $altResult = $this->query($this->url . $vcard_id , 'GET'); |
||
374 | // DEBUG: print the response of the carddav-server |
||
375 | // print_r($altResult); |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
67% of this comment could be valid code. Did you maybe forget this after debugging?
Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it. The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production. This check looks for comments that seem to be mostly valid code and reports them. ![]() |
|||
376 | switch ($altResult['http_code']) |
||
377 | { |
||
378 | case 200: |
||
379 | case 207: |
||
380 | print "Ignoring given Vcard Extension (".$this->url_vcard_extension.")" . PHP_EOL. "."; |
||
381 | $this->setVcardExtension(""); |
||
382 | return $altResult['response']; |
||
383 | } |
||
384 | throw new \Exception( |
||
385 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}:{$result['response']}:{$vcard_id}.", |
||
386 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD |
||
387 | ); |
||
388 | |||
389 | case 200: |
||
390 | case 207: |
||
391 | print "."; |
||
392 | return $result['response']; |
||
393 | } |
||
394 | |||
395 | throw new \Exception( |
||
396 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}:{$result['response']}:{$vcard_id}.", |
||
397 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD |
||
398 | ); |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * Gets a vCard + XML from the CardDAV Server |
||
403 | * |
||
404 | * @param string $vcard_id vCard id on the CardDAV Server |
||
405 | * @return string Raw or simplified vCard (text/xml) |
||
406 | */ |
||
407 | public function getXmlVcard($vcard_id) |
||
408 | { |
||
409 | $vcard_id = str_replace($this->url_vcard_extension, null, $vcard_id); |
||
410 | |||
411 | $xml = new XMLWriter(); |
||
412 | $xml->openMemory(); |
||
413 | $xml->setIndent(4); |
||
414 | $xml->startDocument('1.0', 'utf-8'); |
||
415 | $xml->startElement('C:addressbook-multiget'); |
||
416 | $xml->writeAttribute('xmlns:D', 'DAV:'); |
||
417 | $xml->writeAttribute('xmlns:C', 'urn:ietf:params:xml:ns:carddav'); |
||
418 | $xml->startElement('D:prop'); |
||
419 | $xml->writeElement('D:getetag'); |
||
420 | $xml->writeElement('D:getlastmodified'); |
||
421 | $xml->endElement(); |
||
422 | $xml->writeElement('D:href', $this->url_parts['path'] . $vcard_id . $this->url_vcard_extension); |
||
423 | $xml->endElement(); |
||
424 | $xml->endDocument(); |
||
425 | |||
426 | $result = $this->query($this->url, 'REPORT', $xml->outputMemory(), 'text/xml'); |
||
427 | |||
428 | switch ($result['http_code']) |
||
429 | { |
||
430 | case 200: |
||
431 | case 207: |
||
432 | return $this->simplify($result['response'], true); |
||
433 | |||
434 | } |
||
435 | |||
436 | throw new \Exception( |
||
437 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}.", |
||
438 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD |
||
439 | ); |
||
440 | } |
||
441 | |||
442 | /** |
||
443 | * Enables the debug mode |
||
444 | * |
||
445 | * @return void |
||
446 | */ |
||
447 | public function enableDebug() |
||
448 | { |
||
449 | $this->debug = true; |
||
450 | } |
||
451 | |||
452 | /** |
||
453 | * Checks if the CardDAV server is reachable |
||
454 | * |
||
455 | * @return boolean |
||
456 | */ |
||
457 | public function checkConnection() |
||
458 | { |
||
459 | $result = $this->query($this->url, 'OPTIONS'); |
||
460 | |||
461 | if ($result['http_code'] === 200) { |
||
462 | return true; |
||
463 | } else { |
||
464 | return false; |
||
465 | } |
||
466 | } |
||
467 | |||
468 | /** |
||
469 | * Cleans the vCard |
||
470 | * |
||
471 | * @param string $vcard vCard |
||
472 | * @return string $vcard vCard |
||
473 | */ |
||
474 | private function cleanVcard($vcard) |
||
475 | { |
||
476 | $vcard = str_replace("\t", null, $vcard); |
||
477 | |||
478 | return $vcard; |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * Deletes an entry from the CardDAV server |
||
483 | * |
||
484 | * @param string $vcard_id vCard id on the CardDAV server |
||
485 | * @return boolean |
||
486 | */ |
||
487 | public function delete($vcard_id) |
||
488 | { |
||
489 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'DELETE'); |
||
490 | |||
491 | switch ($result['http_code']) |
||
492 | { |
||
493 | case 204: |
||
494 | return true; |
||
495 | } |
||
496 | |||
497 | throw new \Exception( |
||
498 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}.", |
||
499 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE |
||
500 | ); |
||
501 | } |
||
502 | |||
503 | /** |
||
504 | * Adds an entry to the CardDAV server |
||
505 | * |
||
506 | * @param string $vcard vCard |
||
507 | * @param string $vcard_id vCard id on the CardDAV server |
||
508 | * @return string The new vCard id |
||
509 | */ |
||
510 | public function add($vcard, $vcard_id = null) |
||
511 | { |
||
512 | if ($vcard_id === null) { |
||
513 | $vcard_id = $this->generateVcardId(); |
||
514 | } |
||
515 | $vcard = $this->cleanVcard($vcard); |
||
516 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'PUT', $vcard, 'text/vcard'); |
||
517 | |||
518 | switch($result['http_code']) |
||
519 | { |
||
520 | case 201: |
||
521 | return $vcard_id; |
||
522 | } |
||
523 | |||
524 | throw new \Exception( |
||
525 | "Woops, something's gone wrong! The CardDAV server returned the http status code {$result['http_code']}.", |
||
526 | self::EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD |
||
527 | ); |
||
528 | } |
||
529 | |||
530 | /** |
||
531 | * Updates an entry to the CardDAV server |
||
532 | * |
||
533 | * @param string $vcard vCard |
||
534 | * @param string $vcard_id vCard id on the CardDAV server |
||
535 | * @return boolean |
||
536 | */ |
||
537 | public function update($vcard, $vcard_id) |
||
538 | { |
||
539 | try { |
||
540 | return $this->add($vcard, $vcard_id); |
||
541 | } catch (Exception $e) { |
||
0 ignored issues
–
show
The class
CardDavPHP\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
542 | throw new \Exception($e->getMessage(), self::EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE); |
||
543 | } |
||
544 | } |
||
545 | |||
546 | /** |
||
547 | * Simplify CardDAV XML response |
||
548 | * |
||
549 | * @param string $response CardDAV XML response |
||
550 | * @param boolean $include_vcards Include vCards or not |
||
551 | * @return string Simplified CardDAV XML response |
||
552 | */ |
||
553 | private function simplify($response, $include_vcards = true) |
||
554 | { |
||
555 | $response = $this->cleanResponse($response); |
||
556 | |||
557 | try { |
||
558 | $xml = new \SimpleXMLElement($response); |
||
559 | } catch (Exception $e) { |
||
0 ignored issues
–
show
The class
CardDavPHP\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
560 | throw new \Exception( |
||
561 | "The XML response seems to be malformed and can't be simplified!", |
||
562 | self::EXCEPTION_MALFORMED_XML_RESPONSE, |
||
563 | $e |
||
564 | ); |
||
565 | } |
||
566 | |||
567 | $simplified_xml = new \XMLWriter(); |
||
568 | $simplified_xml->openMemory(); |
||
569 | $simplified_xml->setIndent(4); |
||
570 | |||
571 | $simplified_xml->startDocument('1.0', 'utf-8'); |
||
572 | $simplified_xml->startElement('response'); |
||
573 | |||
574 | if (!empty($xml->response)) { |
||
575 | foreach ($xml->response as $response) { |
||
576 | if ((preg_match('/vcard/', $response->propstat->prop->getcontenttype) || preg_match('/vcf/', $response->href)) && |
||
577 | !$response->propstat->prop->resourcetype->collection) { |
||
578 | $id = basename($response->href); |
||
579 | $id = str_replace($this->url_vcard_extension, null, $id); |
||
580 | |||
581 | try { |
||
582 | $vcardData = $this->getVcard($id); |
||
583 | if (!empty($id)) { |
||
584 | $simplified_xml->startElement('element'); |
||
585 | $simplified_xml->writeElement('id', $id); |
||
586 | $simplified_xml->writeElement('etag', str_replace('"', null, $response->propstat->prop->getetag)); |
||
587 | $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); |
||
588 | |||
589 | if ($include_vcards === true) { |
||
590 | $simplified_xml->writeElement('vcard', $vcardData); |
||
591 | } |
||
592 | $simplified_xml->endElement(); |
||
593 | } |
||
594 | } catch (\Exception $e) { |
||
595 | print("Error fetching vCard: {$id}: {$e->getMessage()}\n"); |
||
596 | } |
||
597 | } elseif (preg_match('/unix-directory/', $response->propstat->prop->getcontenttype)) { |
||
598 | if (isset($response->propstat->prop->href)) { |
||
599 | $href = $response->propstat->prop->href; |
||
600 | } elseif (isset($response->href)) { |
||
601 | $href = $response->href; |
||
602 | } else { |
||
603 | $href = null; |
||
604 | } |
||
605 | |||
606 | $url = str_replace($this->url_parts['path'], null, $this->url) . $href; |
||
607 | $simplified_xml->startElement('addressbook_element'); |
||
608 | $simplified_xml->writeElement('display_name', $response->propstat->prop->displayname); |
||
609 | $simplified_xml->writeElement('url', $url); |
||
610 | $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); |
||
611 | $simplified_xml->endElement(); |
||
612 | } |
||
613 | } |
||
614 | } |
||
615 | |||
616 | $simplified_xml->endElement(); |
||
617 | $simplified_xml->endDocument(); |
||
618 | |||
619 | return $simplified_xml->outputMemory(); |
||
620 | } |
||
621 | |||
622 | /** |
||
623 | * Cleans CardDAV XML response |
||
624 | * |
||
625 | * @param string $response CardDAV XML response |
||
626 | * @return string $response Cleaned CardDAV XML response |
||
627 | */ |
||
628 | private function cleanResponse($response) |
||
629 | { |
||
630 | $response = utf8_encode($response); |
||
631 | $response = str_replace('D:', null, $response); |
||
632 | $response = str_replace('d:', null, $response); |
||
633 | $response = str_replace('C:', null, $response); |
||
634 | $response = str_replace('c:', null, $response); |
||
635 | |||
636 | return $response; |
||
637 | } |
||
638 | |||
639 | /** |
||
640 | * Curl initialization |
||
641 | * |
||
642 | * @return void |
||
643 | */ |
||
644 | public function curlInit() |
||
645 | { |
||
646 | if (empty($this->curl)) { |
||
647 | $this->curl = curl_init(); |
||
648 | curl_setopt($this->curl, CURLOPT_HEADER, true); |
||
649 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false); |
||
650 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); |
||
651 | curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); |
||
652 | curl_setopt($this->curl, CURLOPT_USERAGENT, self::USERAGENT.self::VERSION); |
||
653 | |||
654 | if ($this->auth !== null) { |
||
655 | curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); |
||
656 | curl_setopt($this->curl, CURLOPT_USERPWD, $this->auth); |
||
657 | } |
||
658 | |||
659 | /* allow to follow redirects if activated */ |
||
660 | curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, $this->follow_redirects); |
||
661 | if ($this->follow_redirects) |
||
662 | { |
||
663 | curl_setopt($this->curl, CURLOPT_MAXREDIRS, $this->follow_redirects_count); |
||
664 | } |
||
665 | } |
||
666 | } |
||
667 | |||
668 | /** |
||
669 | * Query the CardDAV server via curl and returns the response |
||
670 | * |
||
671 | * @param string $url CardDAV server URL |
||
672 | * @param string $method HTTP method like (OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE) |
||
673 | * @param string $content Content for CardDAV queries |
||
674 | * @param string $content_type Set content type |
||
675 | * @return array Raw CardDAV Response and http status code |
||
676 | */ |
||
677 | private function query($url, $method, $content = null, $content_type = null) |
||
678 | { |
||
679 | $this->curlInit(); |
||
680 | |||
681 | curl_setopt($this->curl, CURLOPT_URL, $url); |
||
682 | curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); |
||
683 | |||
684 | if ($content !== null) { |
||
685 | curl_setopt($this->curl, CURLOPT_POST, true); |
||
686 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content); |
||
687 | } else { |
||
688 | curl_setopt($this->curl, CURLOPT_POST, false); |
||
689 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, null); |
||
690 | } |
||
691 | |||
692 | if ($content_type !== null) { |
||
693 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Content-type: '.$content_type, 'Depth: 1')); |
||
694 | } else { |
||
695 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Depth: 1')); |
||
696 | } |
||
697 | |||
698 | $complete_response = curl_exec($this->curl); |
||
699 | $header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE); |
||
700 | $http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); |
||
701 | $header = trim(substr($complete_response, 0, $header_size)); |
||
702 | $response = substr($complete_response, $header_size); |
||
703 | |||
704 | $return = array( |
||
705 | 'response' => $response, |
||
706 | 'http_code' => $http_code |
||
707 | ); |
||
708 | |||
709 | if ($this->debug === true) { |
||
710 | $debug = $return; |
||
711 | $debug['url'] = $url; |
||
712 | $debug['method'] = $method; |
||
713 | $debug['content'] = $content; |
||
714 | $debug['content_type'] = $content_type; |
||
715 | $debug['header'] = $header; |
||
716 | $this->setDebug($debug); |
||
717 | } |
||
718 | |||
719 | return $return; |
||
720 | } |
||
721 | |||
722 | /** |
||
723 | * Returns a valid and unused vCard id |
||
724 | * |
||
725 | * @return string $vcard_id Valid vCard id |
||
726 | */ |
||
727 | private function generateVcardId() |
||
728 | { |
||
729 | $vcard_id = null; |
||
730 | |||
731 | for ($number = 0; $number <= 25; $number ++) { |
||
732 | if ($number == 8 || $number == 17) { |
||
733 | $vcard_id .= '-'; |
||
734 | } else { |
||
735 | $vcard_id .= $this->vcard_id_chars[mt_rand(0, (count($this->vcard_id_chars) - 1))]; |
||
736 | } |
||
737 | } |
||
738 | |||
739 | try { |
||
740 | $carddav = new CardDavBackend($this->url); |
||
741 | $carddav->setAuth($this->username, $this->password); |
||
742 | |||
743 | $result = $carddav->query($this->url . $vcard_id . $this->url_vcard_extension, 'GET'); |
||
744 | |||
745 | if ($result['http_code'] !== 404) { |
||
746 | $vcard_id = $this->generateVcardId(); |
||
747 | } |
||
748 | |||
749 | return $vcard_id; |
||
750 | } catch (Exception $e) { |
||
0 ignored issues
–
show
The class
CardDavPHP\Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?
Scrutinizer analyzes your It seems like the listed class was neither found in your dependencies, nor was it found in the analyzed files in your repository. If you are using some other form of dependency management, you might want to disable this analysis. ![]() |
|||
751 | throw new \Exception($e->getMessage(), self::EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID); |
||
752 | } |
||
753 | } |
||
754 | |||
755 | /** |
||
756 | * Destructor |
||
757 | * Close curl connection if it's open |
||
758 | * |
||
759 | * @return void |
||
760 | */ |
||
761 | public function __destruct() |
||
762 | { |
||
763 | if (!empty($this->curl)) { |
||
764 | curl_close($this->curl); |
||
765 | } |
||
766 | } |
||
767 | } |
||
768 | |||
769 | ?> |
||
0 ignored issues
–
show
It is not recommended to use PHP's closing tag
?> in files other than templates.
Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore. A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever. ![]() |
|||
770 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.