Completed
Push — master ( 23153f...eb881d )
by Angus
03:14
created

Gravatar::reset()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php defined('BASEPATH') OR exit('No direct script access allowed.');
2
3
/**
4
 * Gravatar Library for CodeIgniter
5
 *
6
 * @author Ivan Tcholakov <[email protected]>, 2015 - 2016
7
 * @author Ryan Marshall <[email protected]>, 2011 - 2015, @link http://irealms.co.uk
8
 *
9
 * Code repository: @link https://github.com/ivantcholakov/Codeigniter-Gravatar
10
 *
11
 * @version 1.1.1
12
 *
13
 * @license The MIT License (MIT)
14
 * @link http://opensource.org/licenses/MIT
15
 */
16
17
// Gravatar pofile error results.
18
defined('GRAVATAR_NO_ERROR') OR define('GRAVATAR_NO_ERROR', 0);
19
defined('GRAVATAR_CANT_CONNECT') OR define('GRAVATAR_CANT_CONNECT', 1);
20
defined('GRAVATAR_INVALID_EMAIL') OR define('GRAVATAR_INVALID_EMAIL', 2);
21
defined('GRAVATAR_PROFILE_DOES_NOT_EXIST') OR define('GRAVATAR_PROFILE_DOES_NOT_EXIST', 3);
22
defined('GRAVATAR_INCORRECT_FORMAT') OR define('GRAVATAR_INCORRECT_FORMAT', 4);
23
24
class Gravatar {
25
26
    protected $defaults;
27
28
    protected $gravatar_base_url;
29
    protected $gravatar_secure_base_url;
30
    protected $gravatar_image_extension;
31
    protected $gravatar_image_size;
32
    protected $gravatar_default_image;
33
    protected $gravatar_force_default_image;
34
    protected $gravatar_rating ;
35
    protected $gravatar_useragent;
36
37
    protected $last_error = GRAVATAR_NO_ERROR;
38
39
    protected $is_https;
40
    protected $curl_exists;
41
    protected $allow_url_fopen;
42
43
    public function __construct($config = array()) {
44
45
        $this->defaults = array(
46
            'gravatar_base_url' => 'http://www.gravatar.com/',
47
            'gravatar_secure_base_url' => 'https://secure.gravatar.com/',
48
            'gravatar_image_extension' => '.png',
49
            'gravatar_image_size' => 80,
50
            'gravatar_default_image' => '',
51
            'gravatar_force_default_image' => false,
52
            'gravatar_rating' => '',
53
            'gravatar_useragent' => 'PHP Gravatar Library',
54
        );
55
56
        $this->is_https = $this->is_https();
57
        $this->curl_exists = function_exists('curl_init');
58
        $allow_url_fopen = @ini_get('allow_url_fopen');
59
        $allow_url_fopen = $allow_url_fopen === false || in_array(strtolower($allow_url_fopen), array('on', 'true', '1'));
60
        $this->allow_url_fopen = $allow_url_fopen;
61
62
        if (!is_array($config)) {
63
            $config = array();
64
        }
65
66
        $this->defaults = array_merge($this->defaults, $config);
67
        $this->initialize($this->defaults);
68
    }
69
70
    public function initialize($config = array()) {
71
72
        if (!is_array($config)) {
73
            $config = array();
74
        }
75
76
        foreach ($config as $key => $value) {
77
            $this->{$key} = $value;
78
        }
79
80
        $this->gravatar_base_url = (string) $this->gravatar_base_url;
81
        $this->gravatar_secure_base_url = (string) $this->gravatar_secure_base_url;
82
        $this->gravatar_image_extension = (string) $this->gravatar_image_extension;
83
84
        $this->gravatar_image_size = (int) $this->gravatar_image_size;
85
86
        if ($this->gravatar_image_size <= 0) {
87
            $this->gravatar_image_size = 80;
88
        }
89
90
        $this->gravatar_default_image = (string) $this->gravatar_default_image;
91
        $this->gravatar_force_default_image = !empty($this->gravatar_force_default_image);
92
        $this->gravatar_rating = (string) $this->gravatar_rating;
93
        $this->gravatar_useragent = (string) $this->gravatar_useragent;
94
95
        return $this;
96
    }
97
98
    public function reset() {
99
100
        $this->initialize($this->defaults);
101
102
        return $this;
103
    }
104
105
    public function get_defaults() {
106
107
        return $this->defaults;
108
    }
109
110
    /**
111
     * Creates a URL for requesting a Gravatar image.
112
     * @link http://en.gravatar.com/site/implement/images/
113
     *
114
     * @param   string      $email                  A registered email.
115
     * @param   int         $size                   The requested size of the avarar in pixels (a square image).
116
     * @param   string      $default_image          The fallback image option: '', '404', 'mm', 'identicon', 'monsterid', 'wavatar', 'retro', 'blank'.
117
     * @param   bool        $force_default_image    Enforces the fallback image to be shown.
118
     * @param   string      $rating                 The level of allowed self-rate of the avatar: '', 'g' (default), 'pg', 'r', 'x'.
119
     * @return  string                              Returns the URL of the avatar to be requested.
120
     *
121
     * When optional parameters are not set, their default values are taken
122
     * from the configuration file application/config/gravatar.php
123
     */
124
    public function get($email, $size = null, $default_image = null, $force_default_image = null, $rating = null) {
125
126
        $url = ($this->is_https ? $this->gravatar_secure_base_url : $this->gravatar_base_url).'avatar/'.$this->create_hash($email).$this->gravatar_image_extension;
127
128
        $query = array();
129
130
        $size = (int) $size;
131
132
        if ($size <= 0) {
133
            $size = $this->gravatar_image_size;
134
        }
135
136
        if ($size > 0) {
137
            $query['s'] = $size;
138
        }
139
140
        if (isset($default_image)) {
141
            $default_image = (string) $default_image;
142
        } else {
143
            $default_image = $this->gravatar_default_image;
144
        }
145
146
        if ($default_image != '') {
147
            $query['d'] = $default_image;
148
        }
149
150
        if (isset($force_default_image)) {
151
            $force_default_image = !empty($force_default_image);
152
        } else {
153
            $force_default_image = $this->gravatar_force_default_image;
154
        }
155
156
        if ($force_default_image) {
157
            $query['f'] = 'y';
158
        }
159
160
        if (isset($rating)) {
161
            $rating = (string) $rating;
162
        } else {
163
            $rating = $this->gravatar_rating;
164
        }
165
166
        if ($rating != '') {
167
            $query['r'] = $rating;
168
        }
169
170
        if (!empty($query)) {
171
            $url = $url.'?'.http_build_query($query);
172
        }
173
174
        return $url;
175
    }
176
177
    /**
178
     * Executes a request for Gravatar profile data and returns it as a multidimensional array.
179
     * @link https://en.gravatar.com/site/implement/profiles/
180
     *
181
     * @param   string      $email          A registered email.
182
     * @return  array/null                  Received profile data.
0 ignored issues
show
Documentation introduced by
The doc-type array/null could not be parsed: Unknown type name "array/null" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
183
     */
184
    public function get_profile_data($email) {
185
186
        $result = $this->execute_profile_request($email, 'php');
187
188
        if ($this->last_error != GRAVATAR_NO_ERROR) {
189
            return null;
190
        }
191
192
        $result = @ unserialize($result);
193
194
        if ($result === false) {
195
196
            $this->last_error = GRAVATAR_INCORRECT_FORMAT;
197
            return null;
198
        }
199
200
        if (!is_array($result)) {
201
202
            $this->last_error = GRAVATAR_PROFILE_DOES_NOT_EXIST;
203
            return null;
204
        }
205
206
        if (!isset($result['entry']) || !isset($result['entry'][0])) {
207
208
            $this->last_error = GRAVATAR_INCORRECT_FORMAT;
209
            return null;
210
        }
211
212
        return $result['entry'][0];
213
    }
214
215
    /**
216
     * Executes a request for Gravatar profile data and returns raw received response.
217
     * @link https://en.gravatar.com/site/implement/profiles/
218
     *
219
     * @param   string      $email      A registered email.
220
     * @param   string      $format     '', 'json', 'xml', 'php', 'vcf', 'qr'.
221
     * @return  string/null             Received profile raw data.
0 ignored issues
show
Documentation introduced by
The doc-type string/null could not be parsed: Unknown type name "string/null" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
222
     */
223
    public function execute_profile_request($email, $format = null) {
224
225
        $this->last_error = GRAVATAR_NO_ERROR;
226
227
        if (function_exists('valid_email')) {
228
229
            if (!valid_email($email)) {
0 ignored issues
show
Deprecated Code introduced by
The function valid_email() has been deprecated with message: 3.0.0 Use PHP's filter_var() instead

This function has been deprecated. The supplier of the file has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed from the class and what other function to use instead.

Loading history...
230
231
                $this->last_error = GRAVATAR_INVALID_EMAIL;
232
                return null;
233
            }
234
235
        } else {
236
237
            if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
238
239
                $this->last_error = GRAVATAR_INVALID_EMAIL;
240
                return null;
241
            }
242
        }
243
244
        $format = trim($format);
245
246
        if ($format != '') {
247
            $format = '.'.ltrim($format, '.');
248
        }
249
250
        $result = null;
0 ignored issues
show
Unused Code introduced by
$result 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...
251
252
        if ($this->curl_exists) {
253
254
            $url = $this->gravatar_secure_base_url.$this->create_hash($email).$format;
255
256
            $ch = curl_init();
257
258
            $options = array(
259
                CURLOPT_USERAGENT, $this->gravatar_useragent,
260
                CURLOPT_RETURNTRANSFER => true,
261
                CURLOPT_POST => true,
262
                CURLOPT_POSTFIELDS => array(),
263
                CURLOPT_URL => $url,
264
                CURLOPT_TIMEOUT => 3,
265
            );
266
267
            if (!ini_get('safe_mode') && !ini_get('open_basedir')) {
268
                $options[CURLOPT_FOLLOWLOCATION] = true;
269
            }
270
271
            curl_setopt_array($ch, $options);
272
273
            $result = curl_exec($ch);
274
275
            $code = @ curl_getinfo($ch, CURLINFO_HTTP_CODE);
276
277
            @ curl_close($ch);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
278
279
            if ($code != 200) {
280
281
                $this->last_error = GRAVATAR_CANT_CONNECT;
282
                return null;
283
            }
284
285
        } elseif ($this->allow_url_fopen) {
286
287
            $url = $this->gravatar_base_url.$this->create_hash($email).$format;
288
289
            $options = array(
290
                'http' => array(
291
                    'method' => 'GET',
292
                    'useragent' => $this->gravatar_useragent,
293
                ),
294
            );
295
296
            $context = stream_context_create($options);
297
298
            $result = @ file_get_contents($url, false, $context);
299
300
        } else {
301
302
            $this->last_error = GRAVATAR_CANT_CONNECT;
303
            return null;
304
        }
305
306
        if ($result === false) {
307
308
            $this->last_error = GRAVATAR_CANT_CONNECT;
309
            return null;
310
        }
311
312
        return $result;
313
    }
314
315
    /**
316
     * Returns the error code as a result of the last profile request operation.
317
     *
318
     * @return int          GRAVATAR_NO_ERROR - the last operation was successfull,
319
     *                      other returned value indicates failure.
320
     */
321
    public function last_error() {
322
323
        return $this->last_error;
324
    }
325
326
    /**
327
     * Creates a hash value from a provided e-mail address.
328
     * @link https://en.gravatar.com/site/implement/hash/
329
     *
330
     * @param   string      $email      A registered email.
331
     * @return  string/null             The hash for accessing the avatar or profile data.
0 ignored issues
show
Documentation introduced by
The doc-type string/null could not be parsed: Unknown type name "string/null" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
332
     */
333
    public function create_hash($email) {
334
335
        return md5(strtolower(trim($email)));
336
    }
337
338
    protected function is_https() {
0 ignored issues
show
Coding Style introduced by
is_https uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

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

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
339
340
        if (function_exists('is_https')) {
341
            return is_https();
342
        }
343
344
        if (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
345
            return true;
346
        } elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') {
347
            return true;
348
        } elseif (!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') {
349
            return true;
350
        }
351
352
        return false;
353
    }
354
355
    //--------------------------------------------------------------------------
356
    // The following original methods are kept here for backward compatibility.
357
    // Consider them as deprecated.
358
    //--------------------------------------------------------------------------
359
360
361
    /**
362
     * Set the email to be used, converting it into an md5 hash as required by gravatar.com
363
     *
364
     * @param string $email
365
     *
366
     * @return string|null Email hash or if email didn't validate then return NULL
367
     *
368
     * @deprecated
369
     */
370
    public function set_email($email)
371
    {
372
        $email = trim(strtolower($email));
373
374
        if ( ! filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE)
375
        {
376
            return md5($email);
377
        }
378
379
        return NULL;
380
    }
381
382
    /**
383
     * get_gravatar_url
384
     *
385
     * @see http://en.gravatar.com/site/implement/images/ for available options
386
     *
387
     * @param string $rating defaults to g
388
     * @param string $size defaults to 80
389
     * @param string $default_image default sets can be found on the above link
390
     * @param boolean $secure set to TRUE if a secure url is required
391
     *
392
     * @return string gratavar url
393
     *
394
     * @deprecated
395
     */
396
    public function get_gravatar($email, $rating = NULL, $size = NULL, $default_image = NULL, $secure = NULL)
397
    {
398
        $hash = $this->set_email($email);
0 ignored issues
show
Deprecated Code introduced by
The method Gravatar::set_email() has been deprecated.

This method has been deprecated.

Loading history...
399
400
        if ($hash === NULL)
401
        {
402
            // $hash has to be set to a value so the gravatar site can return a default image
403
            $hash = 'invalid_email';
404
        }
405
406
        $query_string = NULL;
407
        $options = array();
408
409
        if ($rating !== NULL)
410
        {
411
            $options['r'] = $rating;
412
        }
413
414
        if ($size !== NULL)
415
        {
416
            $options['s'] = $size;
417
        }
418
419
        if ($default_image !== NULL)
420
        {
421
            $options['d'] = urlencode($default_image);
422
        }
423
424
        if (count($options) > 0)
425
        {
426
            $query_string = '?'. http_build_query($options);
427
        }
428
429
        if ($secure !== NULL)
430
        {
431
            $base = $this->gravatar_secure_base_url;
432
        }
433
        else
434
        {
435
            $base = $this->gravatar_base_url;
436
        }
437
438
        return $base .'avatar/'. $hash . $query_string;
439
    }
440
441
    /**
442
     * Grab the full profile data for a given email from gravatar.com in xml format
443
     *
444
     * @param string $email
445
     * @param string fetch_method defaults to file, 'curl' is the other option
446
     *
447
     * @return object|null $xml->entry on success, NULL on an error
448
     *
449
     * @deprecated
450
     */
451
    public function get_profile($email, $fetch_method = 'file')
452
    {
453
        $hash = $this->set_email($email);
0 ignored issues
show
Deprecated Code introduced by
The method Gravatar::set_email() has been deprecated.

This method has been deprecated.

Loading history...
454
455
        if ($hash === NULL)
456
        {
457
            // A hash value of NULL will return no xml so the method returns NULL
458
            return NULL;
459
        }
460
461
        libxml_use_internal_errors(TRUE);
462
463
        if ($fetch_method === 'file')
464
        {
465
            if (ini_get('allow_url_fopen') == FALSE)
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing ini_get('allow_url_fopen') of type string to the boolean FALSE. If you are specifically checking for an empty string, consider using the more explicit === '' instead.
Loading history...
466
            {
467
                return NULL;
468
            }
469
470
            $str = file_get_contents($this->gravatar_base_url . $hash .'.xml');
471
        }
472
473
        if ($fetch_method === 'curl')
474
        {
475
            if ( ! function_exists('curl_init'))
476
            {
477
                return NULL;
478
            }
479
480
            $ch = curl_init();
481
            $options = array(
482
                CURLOPT_RETURNTRANSFER => TRUE,
483
                CURLOPT_POST => TRUE,
484
                CURLOPT_URL => $this->gravatar_secure_base_url . $hash .'.xml',
485
                CURLOPT_TIMEOUT => 3
486
            );
487
            curl_setopt_array($ch, $options);
488
            $str = curl_exec($ch);
489
        }
490
491
        $xml = simplexml_load_string($str);
0 ignored issues
show
Bug introduced by
The variable $str does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
492
493
        if ($xml === FALSE)
494
        {
495
            $errors = array();
496
            foreach(libxml_get_errors() as $error)
497
            {
498
                $errors[] = $error->message.'\n';
499
            }
500
            $error_string = implode('\n', $errors);
501
            throw new Exception('Failed loading XML\n'. $error_string);
502
        }
503
        else
504
        {
505
            return $xml->entry;
506
        }
507
    }
508
509
}
510