GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (149)

Security Analysis    no request data  

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

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

lib/CardDAV-PHP/carddav.php (10 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php 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
Documentation Bug introduced by
It seems like parse_url($this->url) can also be of type false. However, the property $url_parts is declared as type array. Maybe add an additional type check?

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 the id property of an instance of the Account 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.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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 $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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.

Loading history...
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.

Loading history...
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.

Loading history...
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 composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

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.

Loading history...
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 composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

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.

Loading history...
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 composer.json/composer.lock file if available to determine the classes, and functions that are defined by your dependencies.

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.

Loading history...
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.

Loading history...
770