Issues (268)

Security Analysis    not enabled

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.

code/control/LinkedinCallback.php (53 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
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 28 and the first side effect is on line 23.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * http://www.formatix.eu/en/update-linkedin-status-using-zend-oauth.html
4
 * http://www.contentwithstyle.co.uk/content/linkedin-and-zendoauth/
5
 * https://developer.linkedin.com/documents/authentication#granting
6
 *
7
 *
8
 *
9
 *
10
 *
11
 *
12
 *
13
 *
14
 *
15
 *
16
 *
17
 * see: https://developer.linkedin.com/documents/reading-data
18
 *
19
 */
20
21
if (!file_exists('Zend/Oauth.php')) {
22
    // The autoloader can skip this if LinkedinCallback is called before Linkedin/_config is included
23
    require_once dirname(dirname(dirname(__FILE__))) . '/_config.php';
24
}
25
26
//require_once  dirname(dirname(dirname(__FILE__))).'/thirdparty/linkedin/linkedin_3.3.0.class.php';
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...
27
28
class LinkedinCallback extends SocialIntegrationControllerBaseClass implements SocialIntegrationAPIInterface
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
29
{
30
31
    /**
32
     * Maximum number of followers that can be retrieved
33
     * @var Int
34
     */
35
    private static $number_of_friends_that_can_be_retrieved = 1200;
36
    public static function set_number_of_friends_that_can_be_retrieved($n)
37
    {
38
        self::$number_of_friends_that_can_be_retrieved = $s;
0 ignored issues
show
The variable $s does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
39
    }
40
    public static function get_number_of_friends_that_can_be_retrieved()
41
    {
42
        return self::$number_of_friends_that_can_be_retrieved;
43
    }
44
45
//======================================= AVAILABLE METHODS ===============================================
46
47
    /**
48
     * Standard SS variable determining what this controller can do
49
     * @var Array
50
     */
51
    public static $allowed_actions = array(
52
        'LinkedinConnect',
53
        'Connect',
54
        'Login',
55
        'FinishLinkedin',
56
        'remove',
57
        'test',
58
        'basicconcept'
59
    );
60
61
//======================================= CONFIGURATION STATIC ===============================================
62
63
64
    /**
65
     * Get from Linkedin
66
     * @var String
67
     */
68
    private static $consumer_key = null;
69
    public static function set_consumer_key($s)
70
    {
71
        self::$consumer_key = $s;
72
    }
73
    public static function get_consumer_key()
74
    {
75
        return self::$consumer_key;
76
    }
77
78
    /**
79
     * Get from Linkedin
80
     * @var String
81
     */
82
    private static $consumer_secret = null;
83
    public static function set_consumer_secret($s)
84
    {
85
        self::$consumer_secret = $s;
86
    }
87
    public static function get_consumer_secret()
88
    {
89
        return self::$consumer_secret;
90
    }
91
92
    /**
93
     * Get from Linkedin
94
     * @see: https://developer.linkedin.com/documents/authentication#granting
95
     * @var Array
96
     */
97
        private static $permission_scope =  'r_emailaddress,r_network,w_messages';
98
    public static function set_permission_scope($s)
99
    {
100
        self::$permission_scope = $s;
101
    }
102
    public static function get_permission_scope()
103
    {
104
        return self::$permission_scope;
105
    }
106
107
//======================================= CONFIGURATION NON-STATIC ===============================================
108
109
//======================================= THIRD-PARTY CONNECTION ===============================================
110
    /**
111
     * used to hold the Zend_Oauth_Consumer
112
     * we keep one for each callback
113
     * the default callback is nocallback
114
     * @var array
115
     */
116
    private static $zend_oauth_consumer_class = null;
0 ignored issues
show
The property $zend_oauth_consumer_class is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
117
118
    /**
119
     * when creating a new Zend_Oauth_Consumer
120
     * we also return the configs
121
     * To access the standard config use:
122
     * self::$zend_oauth_consumer_class_config["nocallback"];
123
     *
124
     * @var Array
125
     */
126
    private static $zend_oauth_consumer_class_config = null;
0 ignored issues
show
The property $zend_oauth_consumer_class_config is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
127
128
129
    private $options;
130
    private $consumer;
131
    private $client;
132
    private $token;
133
134
    /**
135
     * holds an instance of the Zend_Oauth_Consumer class
136
     * @return Zend_Oauth_Consumer
137
     */
138
    protected function getConsumer($callback = "nocallback")
0 ignored issues
show
getConsumer uses the super-global variable $_SESSION 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...
getConsumer uses the super-global variable $_GET 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...
139
    {
140
        if (!self::$consumer_key || !self::$consumer_secret) {
141
            user_error("You must set the following variables: LinkedinCallback::consumer_secret AND LinkedinCallback::consumer_key");
142
        }
143
        $this->options = array(
144
            'version' => '1.0',
145
            'localUrl' => Director::absoluteBaseURL().'LinkedinCallback/',
146
            'requestTokenUrl' => 'https://api.linkedin.com/uas/oauth/requestToken',
147
            'userAuthorizationUrl' => 'https://api.linkedin.com/uas/oauth/authorize',
148
            'accessTokenUrl' => 'https://api.linkedin.com/uas/oauth/accessToken',
149
            'consumerKey' => self::get_consumer_key(),
150
            'consumerSecret' => self::get_consumer_secret(),
151
        );
152
        if ($callback && $callback != "nocallback") {
153
            $this->options["callbackUrl"] = Director::absoluteBaseURL().$callback;
154
        } else {
155
            $this->options["callbackUrl"] = Director::absoluteBaseURL()."/LinkedinCallback/Connect/";
156
        }
157
        $this->consumer = new Zend_Oauth_Consumer($this->options);
158
        $token = $this->consumer->getRequestToken(array('scope' =>self::get_permission_scope()));
0 ignored issues
show
$token 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...
159
            //Session::set('LinkedinRequestToken', serialize($token));
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
160
161
        if (!isset($_SESSION ['LINKEDIN_ACCESS_TOKEN'])) {
162
            // We do not have any Access token Yet
163
            if (! empty($_GET) && count($_GET) > 1) {
164
                // But We have some parameters passed throw the URL
165
                if (!isset($_SESSION ['LINKEDIN_REQUEST_TOKEN'])) {
166
                    $_SESSION ['LINKEDIN_REQUEST_TOKEN'] = null;
167
                }
168
                // Get the LinkedIn Access Token
169
                $this->token = $this->consumer->getAccessToken($_GET, unserialize($_SESSION ['LINKEDIN_REQUEST_TOKEN']));
170
171
                // Store the LinkedIn Access Token
172
                $_SESSION ['LINKEDIN_ACCESS_TOKEN'] = serialize($this->token);
173
            } else {
174
                // We have Nothing
175
176
                // Start Requesting a LinkedIn Request Token
177
                $this->token = $this->consumer->getRequestToken(array('scope' => self::get_permission_scope()));
178
179
                // Store the LinkedIn Request Token
180
                $_SESSION ['LINKEDIN_REQUEST_TOKEN'] = serialize($this->token);
181
182
                // Redirect the Web User to LinkedIn Authentication  Page
183
                $this->consumer->redirect(array("_l" => i18n::get_locale()));
184
185
                $url = $this->consumer->getRedirectUrl();
186
                return self::curr()->redirect($url);
187
            }
188
        } else {
189
            // We've already Got a LinkedIn Access Token
190
191
            // Restore The LinkedIn Access Token
192
            $this->token = unserialize($_SESSION ['LINKEDIN_ACCESS_TOKEN']);
193
        }
194
195
        // Use HTTP Client with built-in OAuth request handling
196
        $this->client = $this->token->getHttpClient($this->options);
197
        return $this->consumer;
198
    }
199
200
    public function getResponse($url, $format = "json")
0 ignored issues
show
The parameter $url is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $format is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
201
    {
202
        // Set LinkedIn URI
203
        $this->client->setUri('https://api.linkedin.com/v1/people/~?format=json');
204
        // Set Method (GET, POST or PUT)
205
        $this->client->setMethod(Zend_Http_Client::GET);
206
        // Get Request Response
207
        $response = $this->client->request();
0 ignored issues
show
$response 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...
208
    }
209
210
211
//======================================= STATIC METHODS ===============================================
212
213
    /**
214
     * returns an array of data if there is anything and NULL if there is no information.
215
     * @ return Array | Null
216
     */
217
    public static function get_current_user()
218
    {
219
        $member = Member::currentUser();
220
        if ($member && $member->LinkedinID) {
221
            $linkedinCallback = new LinkedinCallback();
222
            if ($linkedinCallback->getConsumer()) {
223
                // Set LinkedIn URI
224
                $linkedinCallback->client->setUri('https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,picture-url)'); //				$this->client->setUri('http://api.linkedin.com/v1/people/~:(id,first-name,last-name)');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
225
                // Set Method (GET, POST or PUT)
226
                $linkedinCallback->client->setMethod(Zend_Http_Client::GET);
227
                // Get Request Response
228
                $linkedinCallback->client->setHeaders('x-li-format', 'json');
229
230
                $response = $linkedinCallback->client->request();
231
232
                $data = $response->getBody();
233
                $data = json_decode($data);
234
                return $data;
235
            }
236
        } else {
237
            return null;
238
        }
239
    }
240
241
    public static function get_updates($lastNumber = 12)
242
    {
243
        return "NOT IMPLEMENTED YET";
244
    }
245
    /**
246
     * returns true on success
247
     * @param Int | Member | String $to
248
     * @param String $message
249
     * @param String $link - link to send with message
250
     * @param Array $otherVariables - other variables used in message.
251
     * @return boolean
0 ignored issues
show
Should the return type not be integer|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
252
     */
253
    public static function send_message(
254
        $to = 0,
255
        $message,
0 ignored issues
show
Parameters which have default values should be placed at the end.

If you place a parameter with a default value before a parameter with a default value, the default value of the first parameter will never be used as it will always need to be passed anyway:

// $a must always be passed; it's default value is never used.
function someFunction($a = 5, $b) { }
Loading history...
256
        $link = "",
257
        $otherVariables = array()
258
    ) {
259
        $member = Member::currentUser();
260
        if ($member && $member->LinkedinID) {
261
            $linkedinCallback = new LinkedinCallback();
262
            if ($linkedinCallback->getConsumer()) {
263
                //TO
264
                if ($to instanceof Member) {
265
                    $to = $to->LinkedinID;
266
                }
267
                //MESSAGE
268
                $message = trim(strip_tags(stripslashes($message)));
269
                //SUBJECT
270 View Code Duplication
                if (!empty($otherVariables["Subject"])) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
                    $subject = $otherVariables["Subject"];
272
                } else {
273
                    $subject = substr($message, 0, 30);
274
                }
275
                //XML POST
276
                $body ='<?xml version=\'1.0\' encoding=\'UTF-8\'?>
277
<mailbox-item>
278
	<recipients>
279
		<recipient>
280
			<person path=\'/people/~\'/>
281
		</recipient>
282
		<recipient>
283
			<person path=\'/people/'.$to.'\'/>
284
		</recipient>
285
	</recipients>
286
	<subject>'.htmlspecialchars($subject).'</subject>
287
	<body>'.htmlspecialchars($message).' '.$link.'</body>
288
</mailbox-item>';
289
                // Set LinkedIn URI
290
                $linkedinCallback->client->setUri('https://api.linkedin.com/v1/people/~/mailbox'); //				//
291
                // Set Method (GET, POST or PUT)
292
                $linkedinCallback->client->setMethod(Zend_Http_Client::POST);
293
                //SET BODY
294
                $linkedinCallback->client->setRawData($body, 'text/xml');
295
                //SET XML
296
                $linkedinCallback->client->setHeaders('Content-Type', 'text/xml');
297
                //send it!
298
                $response = $linkedinCallback->client->request();
299
                //did it go ok?
300
                if ($response->isSuccessful()) {
301
                    return 1;
302
                }
303
            }
304
        }
305
        return false;
306
    }
307
308
    /**
309
     *
310
     * If we can not find enough followers, we add any user.
311
     *
312
     * @param Int $limit - the number of users returned, set to -1 to return maximum
313
     * @param String $search - the users searched for
0 ignored issues
show
There is no parameter named $search. Did you maybe mean $searchString?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
314
     *
315
     * @return Array (array("id" => ..., "name" => ...., "picture" => ...))
0 ignored issues
show
Should the return type not be null|array?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
316
     */
317
    public static function get_list_of_friends($limit = 12, $searchString = "")
318
    {
319
        if ($limit == -1) {
320
            $limit = self::get_number_of_friends_that_can_be_retrieved();
321
        }
322
        $finalArray = array();
323
        $member = Member::currentUser();
324
        if ($member && $member->LinkedinID) {
325
            $linkedinCallback = new LinkedinCallback();
326
            if ($linkedinCallback->getConsumer()) {
327
                $me = null;
328
                if (Director::isDev()) {
329
                    $me = self::get_current_user();
330
                }
331
                // Set LinkedIn URI
332
                $linkedinCallback->client->setUri('https://api.linkedin.com/v1/people/~/connections:(id,first-name,last-name,picture-url)'); //				//
333
                // Set Method (GET, POST or PUT)
334
                $linkedinCallback->client->setMethod(Zend_Http_Client::GET);
335
                // Get Request Response
336
                $linkedinCallback->client->setHeaders('x-li-format', 'json');
337
338
                $response = $linkedinCallback->client->request();
339
340
                $data = $response->getBody();
341
                $data = json_decode($data);
342
                if ($me) {
343
                    //adding yourself to the top of the list
344
                    array_unshift($data->values, $me);
345
                }
346
                if ($data && is_object($data) && $data->values && is_array($data->values) && count($data->values)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $data->values of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
347
                    foreach ($data->values as $key => $friend) {
348
                        if ($key > $limit) {
349
                            break;
350
                        }
351
                        if (empty($friend->firstName)) {
352
                            $friend->firstName = "";
353
                        }
354
                        if (empty($friend->lastName)) {
355
                            $friend->lastName = "";
356
                        }
357
                        if (empty($friend->pictureUrl)) {
358
                            $friend->pictureUrl = "";
359
                        }
360
                        $finalArray[$key] = array(
361
                            "id" => $friend->id,
362
                            "name" => $friend->firstName." ".$friend->lastName,
363
                            "picture" => $friend->pictureUrl
364
                        );
365
                    }
366
                }
367
            }
368
        }
369
        if (!count($finalArray)) {
370
            $finalArray = null;
371
        }
372
        return $finalArray;
373
    }
374
375
    /**
376
     * checks if a user exists
377
     * @param String $id - linkedin ID
378
     */
379
    public static function is_valid_user($id)
380
    {
381
        return true;
382
    }
383
384
//======================================= STANDARD SS METHODS ===============================================
385
386
387
388 View Code Duplication
    public function __construct()
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
389
    {
390
        if (self::$consumer_secret == null || self::$consumer_key == null) {
391
            user_error('Cannot instigate a LinkedinCallback object without a consumer secret and key', E_USER_ERROR);
392
        }
393
        parent::__construct();
394
    }
395
396
397
//======================================= CONNECT ===============================================
398
399
    /**
400
     * easy access to the connection
401
     *
402
     */
403 View Code Duplication
    public function LinkedinConnect()
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
404
    {
405
        if ($this->isAjax()) {
406
            return $this->connectUser($this->Link('FinishLinkedin'));
407
        } else {
408
            Session::set("BackURL", $this->returnURL());
409
            return $this->connectUser($this->returnURL());
410
        }
411
    }
412
413
    /**
414
     * STEP 1 of the connecting process
415
     * @param String $returnTo - the URL to return to
416
     * @param Array $extra - additional paramaters
417
     */
418
    public function connectUser($returnTo = '', array $extra = array())
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
The parameter $extra is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
419
    {
420
        $token = SecurityToken::inst();
421
        if ($returnTo) {
422
            $returnTo = $token->addToUrl($returnTo);
423
        }
424
        Session::set("BackURL", $returnTo);
425
        $callback = $this->AbsoluteLink('Connect');
426
        return self::curr()->redirect($callback);
427
    }
428
429
    /**
430
     * Connects the current user.
431
     * completes connecting process
432
     * @param SS_HTTPRequest $reg
0 ignored issues
show
There is no parameter named $reg. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
433
     */
434
    public function Connect(SS_HTTPRequest $req)
0 ignored issues
show
The parameter $req is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
435
    {
436
        //$securityToken = SecurityToken::inst();
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% 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...
437
        //if(!$securityToken->checkRequest($req)) return $this->httpError(400);
0 ignored issues
show
Unused Code Comprehensibility introduced by
80% 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...
438
        try {
439
            $this->getConsumer(); //&& /**/
440
            // Set LinkedIn URI
441
            $this->client->setUri('https://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,picture-url)'); //				$this->client->setUri('http://api.linkedin.com/v1/people/~:(id,first-name,last-name)');
0 ignored issues
show
Unused Code Comprehensibility introduced by
70% 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...
442
            // Get Request Response
443
            // Set Method (GET, POST or PUT)
444
            $this->client->setMethod(Zend_Http_Client::GET);
445
446
            $response = $this->client->request();
447
            $responseBody =  $response->getBody();
448
            $data = simplexml_load_string($responseBody);
449
            if ($data) {
450
                $this->updateUserFromLinkedinData($data);
451
            }
452
        } catch (Exception $e) {
453
            $this->httpError(500, $e->getMessage());
454
            SS_Log::log(print_r($e, 1), SS_Log::ERR);
455
        }
456
        $returnURL = $this->returnURL();
457
        return $this->redirect($returnURL);
458
    }
459
460
461 View Code Duplication
    public function FinishLinkedin($request)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
462
    {
463
        $token = SecurityToken::inst();
464
        if (!$token->checkRequest($request)) {
465
            return $this->httpError(400);
466
        }
467
        if ($this->CurrentMember()->LinkedinID) {
468
            return '<script type="text/javascript">//<![CDATA[
469
			opener.LinkedinResponse(' . \Convert::raw2json(array(
470
                'name' => $this->CurrentMember()->LinkedinName,
471
                'removeLink' => $token->addToUrl($this->Link('RemoveLinkedin')),
472
            )) . ');
473
			window.close();
474
			//]]></script>';
475
        } else {
476
            return '<script type="text/javascript">window.close();</script>';
477
        }
478
    }
479
480
481
482
483
484
//==================================== LOGIN ==============================================
485
486
    /**
487
     * Works with the login form
488
     */
489
    public function Login(SS_HTTPRequest $req)
490
    {
491
        $token = SecurityToken::inst();
492
        if (!$token->checkRequest($req)) {
493
            return $this->httpError(400);
494
        }
495
        if ($req->getVar('oauth_problem')) {
496
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.message', 'Login cancelled.');
497
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.type', 'error');
498
            return $this->redirect('Security/login#LinkedinLoginForm_LoginForm_tab');
499
        }
500
        $consumer = self::get_zend_oauth_consumer_class();
0 ignored issues
show
The method get_zend_oauth_consumer_class() does not seem to exist on object<LinkedinCallback>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
$consumer 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...
501
        //$token = Session::get('Linkedin.Request.Token');
0 ignored issues
show
Unused Code Comprehensibility introduced by
55% 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...
502
        if (is_string($token)) {
503
            $token = unserialize($token);
0 ignored issues
show
$token 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...
504
        }
505
        try {
506
            $this->getConsumer();
507
            $this->client->setUri('http://api.linkedin.com/v1/people/~:(id,first-name,last-name)');
508
            $this->client->setMethod(Zend_Http_Client::GET);
509
            $this->client->setHeaders('x-li-format', 'json');
510
            $response = $this->client->request();
511
512
            $data = $response->getBody();
513
            $data = json_decode($data);
514
            $id = $data->id;
0 ignored issues
show
$id 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...
515
            $name = "$data->firstName $data->lastName";
0 ignored issues
show
$name 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...
516
        } catch (Exception $e) {
517
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.message', $e->getMessage());
518
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.type', 'error');
519
            SS_Log::log($e, SS_Log::ERR);
520
            return $this->redirect('Security/login#LinkedinLoginForm_LoginForm_tab');
521
        }
522
        if (!is_numeric($user)) {
0 ignored issues
show
The variable $user does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
523
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.message', 'Invalid user id received from Linkedin.');
524
            Session::set('FormInfo.LinkedinLoginForm_LoginForm.formError.type', 'error');
525
            return $this->redirect('Security/login#LinkedinLoginForm_LoginForm_tab');
526
        }
527
        if ($data && $user && is_numeric($user) && $access) {
528
            $this->updateUserFromLinkedinData($user, $data, $access, Session::get('SessionForms.LinkedinLoginForm.Remember'));
0 ignored issues
show
The variable $access does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
The call to LinkedinCallback::updateUserFromLinkedinData() has too many arguments starting with $data.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
529
        }
530
        $backURL = $this->returnURL();
531
        return $this->redirect($backURL);
532
    }
533
534
535 View Code Duplication
    public function remove($request = null)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
536
    {
537
        $token = SecurityToken::inst();
538
        if (!$token->checkRequest($request)) {
539
            return $this->httpError(400);
540
        }
541
        return $this->RemoveLinkedin($request);
542
    }
543
544
545
    // ============================================== REMOVE Linkedin ========================
546
547
    public function RemoveLinkedin($request)
0 ignored issues
show
The parameter $request is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
RemoveLinkedin uses the super-global variable $_SESSION 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...
548
    {
549
        //security
550
        //remove Linkedin identification
551
        //Session::clear('Linkedin.Request.Token');
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% 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...
552
        $m = $this->CurrentMember();
553
        if ($m) {
554
            $m->LinkedinID = $m->LinkedinFirstName = $m->LinkedinLastName = $m->LinkedinPicture = $m->LinkedinEmail = null;
555
            $m->write();
556
        }
557
        unset($_SESSION ['LINKEDIN_ACCESS_TOKEN']);
558
        unset($_SESSION ['LINKEDIN_REQUEST_TOKEN']);
559
        $returnURL = $this->returnURL();
560
        $this->redirect($returnURL);
561
    }
562
563
//========================================================== HELPER FUNCTIONS =====================================
564
565
566
//========================================================== HELPER FUNCTIONS =====================================
567
568
569
570
    /**
571
     * Saves the Linkedin data to the member and logs in the member if that has not been done yet.
572
     * @param Int $user - the ID of the current twitter user
0 ignored issues
show
There is no parameter named $user. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
573
     * @param Object $twitterData - the data returned from twitter
0 ignored issues
show
There is no parameter named $twitterData. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
574
     * @param Object $access - access token
0 ignored issues
show
There is no parameter named $access. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
575
     * @param Boolean $keepLoggedIn - does the user stay logged in
0 ignored issues
show
There is no parameter named $keepLoggedIn. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
576
     * @return Member
577
     */
578
    protected function updateUserFromLinkedinData($data)
579
    {
580
        //find member
581
        $member = null;
582
        if ($data) {
583
            $member = DataObject::get_one('Member', '"LinkedinID" = \'' . Convert::raw2sql($data->id) . '\'');
584
        }
585
        if (!$member) {
586
            $member = Member::currentUser();
587
            if (!$member) {
588
                $member = new Member();
589
            }
590
        }
591 View Code Duplication
        if ($linkedinEmail = Convert::raw2sql($data->{'email-address'})) {
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
592
            $memberID = intval($member->ID)-0;
593
            $existingMember = DataObject::get_one(
594
                'Member',
595
                '("Email" = \'' . $linkedinEmail . '\' OR "LinkedinEmail" = \''.$linkedinEmail.'\') AND "Member"."ID" <> '.$memberID
596
            );
597
            if ($existingMember) {
598
                $member = $existingMember;
599
            }
600
        }
601
        $member->LinkedinID = Convert::raw2sql(strval($data->id));
602
        $member->LinkedinEmail = $linkedinEmail;
603
        $member->LinkedinPicture = Convert::raw2sql(strval($data->{'picture-url'}));
604
        $member->LinkedinFirstName = Convert::raw2sql(strval($data->{'first-name'}));
605
        $member->LinkedinLastName = Convert::raw2sql(strval($data->{'last-name'}));
606
        if (!$member->FirstName) {
607
            $member->FirstName = $member->LinkedinFirstName;
608
        }
609
        if (!$member->Surname) {
610
            $member->Surname = $member->LinkedinLastName;
611
        }
612
        $member->write();
613
        $oldMember = Member::currentUser();
614
        if ($oldMember) {
615
            if ($oldMember->ID != $member->ID) {
616
                $oldMember->logout();
617
                $member->login(true);
618
            } else {
0 ignored issues
show
This else statement is empty and can be removed.

This check looks for the else branches of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These else branches can be removed.

if (rand(1, 6) > 3) {
print "Check failed";
} else {
    //print "Check succeeded";
}

could be turned into

if (rand(1, 6) > 3) {
    print "Check failed";
}

This is much more concise to read.

Loading history...
619
                //already logged in - nothing to do.
620
            }
621
        } else {
622
            $member->login(true);
623
        }
624
        return $member;
625
    }
626
627
628
//========================================================== TESTS =====================================
629
630
    public function meondatabase()
631
    {
632
        $member = Member::currentUser();
633
        if ($member) {
634
            echo "<ul>";
635
            echo "<li>LinkedinID: ".$member->LinkedinID."</li>";
636
            echo "<li>LinkedinEmail: ".$member->LinkedinEmail."</li>";
637
            echo "<li>LinkedinFirstName: ".$member->LinkedinFirstName."</li>";
638
            echo "<li>LinkedinLastName: ".$member->LinkedinLastName."</li>";
639
            echo "<li>LinkedinPicture: <img src=\"".$member->LinkedinPicture."\" /> ".$member->LinkedinPicture."</li>";
640
            echo "</ul>";
641
        } else {
642
            echo "<h2>You are not logged in.</h2>";
643
        }
644
    }
645
646
647
648
649
    public function basicconcept()
650
    {
651
        $this->getConsumer();
652
653
        // Set LinkedIn URI
654
        $this->client->setUri('https://api.linkedin.com/v1/people/~');
655
        // Set Method (GET, POST or PUT)
656
        $this->client->setMethod(Zend_Http_Client::GET);
657
        // Get Request Response
658
        $response = $this->client->request();
659
660
        // Get the XML containing User's Profile
661
        $content =  $response->getBody();
662
663
        // Uncomment Following Line To display XML result
664
        // header('Content-Type: ' . $response->getHeader('Content-Type'));
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
665
        // echo $content;
666
        // exit;
667
668
        // Use simplexml to transform XML to a PHP Object
669
        $xml = simplexml_load_string($content);
670
671
        // Uncomment Following Line To display Simple XML Object Structure
672
         echo '<pre>';
673
        print_r($xml);
674
        echo'</pre>';
675
676
        // Display Profile Information as you wish
677
        $firstName = $xml->{'first-name'};
0 ignored issues
show
$firstName 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...
678
        $lastName = $xml->{'last-name'};
0 ignored issues
show
$lastName 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...
679
    }
680
}
681