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.

control/SocialIntegrationControllerBaseClass.php (16 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
2
3
4
abstract class SocialIntegrationControllerBaseClass extends Controller
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...
5
{
6
7
    /**
8
     * default profile pic in case none is available
9
     * @var String
10
     */
11
    private static $default_avatar = "http://placeholder.it/32x32";
12
    public static function get_default_avatar()
13
    {
14
        return self::$default_avatar;
15
    }
16
    public static function set_default_avatar($s)
17
    {
18
        self::$default_avatar = $s;
19
    }
20
21
    /**
22
     * tells us if a class is a Social Integration API class (e.g. Facebook, Twiiter, etc....)
23
     * @param String $className
24
     * @return Boolean
25
     */
26
    public static function is_social_integration_api_class($className)
27
    {
28
        if (class_exists($className)) {
29
            $arrayOfInterfacesItImplements = class_implements($className);
30
            if (is_array($arrayOfInterfacesItImplements) && in_array("SocialIntegrationAPIInterface", $arrayOfInterfacesItImplements)) {
31
                return true;
32
            }
33
        }
34
        return false;
35
    }
36
37
38
    /**
39
     * one stop shop button
40
     * @return Object (
41
     *   IsConnected,
42
     *   IsLoggedIn,
43
     *   Link,
44
     *   ConnectedName,
45
     *   ConnectedImageURL
46
     * )
47
     */
48
    public static function get_login_button($backURL = "", $member)
0 ignored issues
show
get_login_button 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...
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...
49
    {
50
        //back URL
51
        if (!$backURL) {
52
            $backURL = $_SERVER['REQUEST_URI'];
53
        }
54
        $position = strpos($backURL, "?");
55
        if ($position) {
56
            $backURL = substr($backURL, 0, $position);
57
        }
58
        $backURL = str_replace("//", "/", $backURL);
59
        $backURL .= "#".strtolower(self::my_service_name())."_tab";
60
        $backURL = "?BackURL=".urlencode($backURL);
61
        //security
62
        $token = SecurityToken::inst();
63
        if ($member->exists()) {
64
            //AJAX FUNCTIONALITY
65
            //Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% 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...
66
            //Requirements::javascript(THIRDPARTY_DIR . '/jquery-livequery/jquery.livequery.js');
0 ignored issues
show
Unused Code Comprehensibility introduced by
46% 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...
67
            //Requirements::javascript('social_integration/javascript/'.strtolower(self::my_service_name()).".js");
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...
68
            $method = "has".self::my_service_name();
69
            if ($member->$method()) {
70
                $removeURL = Controller::join_links(self::my_class_name(), 'remove', $backURL);
71
                $removeURL = $token->addToUrl($removeURL);
72
                $nameField = self::my_service_name()."Name";
73
                $pictureField = self::my_service_name()."Picture";
74
                return new ArrayData(
75
                    array(
76
                        "IsConnected" => true,
77
                        "IsLoggedIn" => Member::currentUserID() == $member->ID ? true : false,
78
                        "Link" => $removeURL,
79
                        "ConnectedName" => $member->$nameField,
80
                        "ConnectedImageURL" => $member->$pictureField
81
                    )
82
                );
83
            } else {
84
                $connectURL = Controller::join_links(self::my_class_name(), self::my_service_name().'Connect', $backURL);
85
                $connectURL = $token->addToUrl($connectURL);
86
                return new ArrayData(
87
                    array(
88
                        "IsConnected" => false,
89
                        "IsLoggedIn" => Member::currentUserID() == $member->ID ? true : false,
90
                        "Link" => $connectURL,
91
                        "ConnectedName" => "",
92
                        "ConnectedImageURL" => ""
93
                    )
94
                );
95
            }
96
        } else {
97
            $connectURL = Controller::join_links(self::my_class_name(), self::my_service_name().'Connect', $backURL);
98
            $connectURL = $token->addToUrl($connectURL);
99
            return new ArrayData(
100
                array(
101
                    "IsConnected" => false,
102
                    "IsLoggedIn" => false,
103
                    "Link" => $connectURL,
104
                    "ConnectedName" => "",
105
                    "ConnectedImageURL" => ""
106
                )
107
            );
108
        }
109
    }
110
111
112
    /**
113
     * @param String $returnURL
114
     * @return String
115
     */
116
    public static function login_url($returnURL = "")
117
    {
118
        $backURLString = "";
119
        if ($returnURL) {
120
            $backURLString = '?BackURL='.urlencode($returnURL);
121
        }
122
        return 'Security/login/'.$backURLString.'#'.self::my_security_form().'_LoginForm_tab';
123
    }
124
125
    /**
126
     * Link to login form
127
     * @param String $returnURL
128
     * @return String
129
     */
130
    public static function connect_url($returnURL = "", $existingMember = false)
131
    {
132
        $backURLString = "";
133
        if ($returnURL) {
134
            $backURLString = '?BackURL='.urlencode($returnURL);
135
        }
136
        $method = self::my_service_name()."Connect";
137
        $className = self::my_class_name();
138
        return $className."/".$method."/".$backURLString;
139
    }
140
141
142
    /**
143
     * redirects to login prompt, lets the user log in and returns to
144
     * the returnURL specified.
145
     * @param String $returnURL
146
     * @return REDIRECTS!
0 ignored issues
show
The doc-type REDIRECTS! could not be parsed: Unknown type name "REDIRECTS!" 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...
147
     */
148
    public static function redirect_to_login_prompt($returnURL = "")
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...
149
    {
150
        $className = self::my_class_name();
151
        return self::curr()->redirect($className::login_url($returnURL));
152
    }
153
154
    /**
155
     * The class being called
156
     * (e.g. FacebookCallback::my_class_name should return FacebookCallback)
157
     * @return String
158
     */
159
    protected static function my_class_name()
160
    {
161
        return get_called_class();
162
    }
163
164
    /**
165
     * The current ClassName without the "Callback" portion.
166
     * @return String
167
     */
168
    protected static function my_service_name()
169
    {
170
        return str_replace("Callback", "", self::my_class_name());
171
    }
172
173
    /**
174
     * The name of the security form.
175
     * @return String
176
     */
177
    protected function my_security_form()
178
    {
179
        return self::my_class_name()."LoginForm";
180
    }
181
182
    /**
183
     * returns Absolute URL to a link within this controller,
184
     * by default it is the "Connect" link, because this controller
185
     * always needs an action.
186
     * @return String
187
     */
188
    public function Title()
189
    {
190
        return self::my_service_name();
191
    }
192
193
    /**
194
     * returns Absolute URL to a link within this controller,
195
     * by default it is the "Connect" link, because this controller
196
     * always needs an action.
197
     * @return String
198
     */
199
    public function AbsoluteLink($action = "")
200
    {
201
        if (!$action) {
202
            $action = $this->serviceName."Connect";
0 ignored issues
show
The property serviceName does not exist on object<SocialIntegrationControllerBaseClass>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
203
        }
204
        return Director::absoluteURL($this->Link($action));
205
    }
206
207
    /**
208
     * returns relative URL to a link within this controller,
209
     * by default it is the "Connect" link, because this controller
210
     * always needs an action.
211
     * @return String
212
     */
213
    public function Link($action = "")
214
    {
215
        if (!$action) {
216
            $action = $this->serviceName."Connect";
0 ignored issues
show
The property serviceName does not exist on object<SocialIntegrationControllerBaseClass>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
217
        }
218
        $className = self::my_class_name();
219
        return self::join_links($className, $action);
220
    }
221
222
    public static function is_valid_user($screen_name)
223
    {
224
        return true;
225
    }
226
227
228
//========================================== HELPER METHODS =====================================
229
230
    public function __construct()
231
    {
232
        parent::__construct();
233
    }
234
235
    /**
236
     * you need to add an action
237
     */
238
    public function index()
239
    {
240
        if (Director::isDev()) {
241
            return $this->renderWith(array("SocialIntegrationControllerBaseClass"));
242
        } else {
243
            die("For security reasons, this service works in DEV move only.");
0 ignored issues
show
Coding Style Compatibility introduced by
The method index() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
244
        }
245
    }
246
247
    /**
248
     * works out best Return URL
249
     * @param Boolean $hasAbsoluteBaseURL - should it include the Base URL (e.g. http://www.mysite.com)
250
     * @return String
251
     */
252
    protected function returnURL($hasAbsoluteBaseURL = false)
253
    {
254
        $returnURL = "/Security/login/";
255
        if (!empty($this->requestParams["BackURL"])) {
256
            $returnURL = $this->requestParams["BackURL"];
257
        } elseif (Session::get("BackURL")) {
258
            $returnURL = Session::get("BackURL");
259
            Session::set("BackURL", "");
260
            Session::clear("BackURL");
261
        }
262
        $returnURL = urldecode($returnURL);
263
        if ($hasAbsoluteBaseURL) {
264
            $returnURL = Director::absoluteBaseURL().$returnURL;
265
        }
266
        return $returnURL;
267
    }
268
269
    public function Tests()
270
    {
271
        if (Director::isDev()) {
272
            $dos = new DataObjectSet();
273
            $tests = array(
274
                "connect" => "connect to this service",
275
                "login" => "do a traditional log in to this service",
276
                "meonservice" => "what details does this service know about me right now, retrieve from service",
277
                "meondatabase" => "what data is stored with current member",
278
                "updates" => "show my latest updates",
279
                "friends" => "get a list of my friends (or the equivalent (e.g. followers))",
280
                "friendssearch" => "????",
281
                "isvaliduser" => "????",
282
                "sendmessage" => "test sending a message",
283
                "remove" => "remove this service from my account"
284
            );
285
            foreach ($tests as $test => $description) {
286
                $dos->push(
287
                    new ArrayData(
0 ignored issues
show
new \ArrayData(array('Li.... ': ' . $description)) is of type object<ArrayData>, but the function expects a object<DataObject>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
288
                        array(
289
                            "Link" => "/".$this->Link("test/".$test."/"),
290
                            "Name" => "<strong>".$test."</strong>".": ".$description
291
                        )
292
                    )
293
                );
294
            }
295
            return $dos;
296
        }
297
        return null;
298
    }
299
300
301
    public function menondatabase()
302
    {
303
        //to be completed
304
    }
305
306
    public function test($request)
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...
307
    {
308
        $className = self::my_class_name();
309
        $testType = $request->param("ID");
310
        $IDField = self::my_service_name()."ID";
311
        echo "<h2>TEST: $testType</h2><pre>";
312
        switch ($testType) {
313
            case "connect":
314
                return $this->connectUser("/$className/test/meonservice/");
0 ignored issues
show
Documentation Bug introduced by
The method connectUser does not exist on object<SocialIntegrationControllerBaseClass>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
315
                break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
316
            case "login":
317
                print_r($className::redirect_to_login_prompt("/$className/test/meonservice/"));
318
                break;
319
            case "meonservice":
320
                $outcome = $className::get_current_user();
321
                if (!$outcome) {
322
                    echo "NOT CONNECTED";
323
                } else {
324
                    print_r($outcome);
325
                }
326
                break;
327
            case "meondatabase":
328
                $this->meondatabase();
0 ignored issues
show
The method meondatabase() does not exist on SocialIntegrationControllerBaseClass. Did you maybe mean menondatabase()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
329
                break;
330
            case "updates":
331
                print_r($className::get_updates());
332
                break;
333
            case "friends":
334
                print_r($className::get_list_of_friends(-1));
335
                break;
336
            case "friendssearch":
337
                print_r($className::get_list_of_friends(-1, "john"));
338
                break;
339
            case "isvaliduser":
340
                $member = Member::currentUser();
341
                if ($member) {
342
                    if (self::my_service_name() == "Twitter") {
343
                        $IDField = "TwitterID";
344
                    }
345
                    $id = $member->$IDField;
346
                } else {
347
                    $id = "";
348
                }
349
                print_r($className::is_valid_user($id));
350
                break;
351
            case "sendmessage":
352
                $member = Member::currentUser();
353
                $otherVariables = array();
354
                if ($member) {
355
                    if (self::my_service_name() == "Facebook") {
356
                        $otherVariables = array(
357
                            "name" => "test name",
358
                            "caption" =>  "test caption",
359
                            "description" => "test description"
360
                        );
361
                    }
362
                    $fieldName = self::my_service_name()."ID";
363
                    $outcome = $className::send_message(
364
                        $member->$fieldName,
365
                        $message = "message goes here",
366
                        $link = "http://www.google.com",
367
                        $otherVariables
368
                    );
369
                } else {
370
                    $outcome = "You must be logged in to send a message.";
371
                }
372
                echo "
373
					<h1>Sending message to yourself</h1>
374
					<p>OUTCOME: <pre>...$outcome</pre>";
375
                break;
376
            case "remove":
377
                $method = "Remove".self::my_service_name();
378
                echo $this->$method(null);
379
                break;
380
            default:
381
                echo "no test to run";
382
        }
383
        echo "</pre><hr /><a href=\"/$className\">back to test index</a>";
384
    }
385
}
386