Issues (1)

Security Analysis    no request data  

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

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

src/Eventbrite.php (1 issue)

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
 * @file
4
 * A lightweight wrapper for the Eventbrite API using Guzzle 6. Inspired by
5
 * drewm/mailchimp-api.
6
 */
7
namespace jamiehollern\eventbrite;
8
9
use GuzzleHttp\Client;
10
use GuzzleHttp\Psr7\Request;
11
use GuzzleHttp\Exception\BadResponseException;
12
use Psr\Http\Message\ResponseInterface;
13
use Exception;
14
15
/**
16
 * Class Eventbrite
17
 *
18
 * @package jamiehollern\eventbrite
19
 * @todo    Add a batch method.
20
 * @todo    Allow the token to be passed as a query string.
21
 * @todo    Properly deal with errors/non-200 responses correctly?
22
 */
23
class Eventbrite
24
{
25
    /**
26
     * The current version of this library.
27
     */
28
    const VERSION = '1.0.1';
29
30
    /**
31
     * An array of valid HTTP verbs.
32
     */
33
    private static $valid_verbs = ['get', 'post', 'put', 'patch', 'delete'];
34
35
    /**
36
     * The API endpoint to get the current user's details.
37
     */
38
    const CURRENT_USER_ENDPOINT = 'users/me/';
39
40
    /**
41
     * @var string The Eventbrite OAuth token.
42
     */
43
    private $token;
44
45
    /**
46
     * @var \GuzzleHttp\Client
47
     */
48
    private $client;
49
50
    /**
51
     * @var \GuzzleHttp\Psr7\Request
52
     */
53
    private $last_request = null;
54
55
    /**
56
     * @var \Psr\Http\Message\ResponseInterface
57
     */
58
    private $last_response = null;
59
60
    /**
61
     * @param string $token
62
     *   The OAuth token to authenticate the request
63
     * @param array  $config
64
     *   An array of Guzzle config options so that everything is configurable.
65
     *
66
     * @throws \Exception
67
     */
68
    public function __construct($token, $config = [])
69
    {
70
        $default_config = [
71
            'base_uri' => 'https://www.eventbriteapi.com/v3/',
72
            // Turn exceptions off so we can handle the responses ourselves.
73
            'exceptions' => false,
74
            'timeout' => 30,
75
        ];
76
        $config = array_merge($default_config, $config);
77
        // Add this last so it's always there and isn't overwritten.
78
        $config['headers']['User-Agent'] = 'jamiehollern\eventbrite v' . self::VERSION . ' ' . \GuzzleHttp\default_user_agent();
79
        if (!empty($token)) {
80
            $this->token = $token;
81
            // Set the authorisation header.
82
            $config['headers']['Authorization'] = 'Bearer ' . $this->token;
83
            $this->client = new Client($config);
84
        } else {
85
            throw new \Exception('An OAuth token is required to connect to the Eventbrite API.');
86
        }
87
    }
88
89
    /**
90
     * Make the call to Eventbrite, only synchronous calls at present.
91
     *
92
     * @param string $verb
93
     * @param string $endpoint
94
     * @param array  $options
95
     *
96
     * @return array|mixed|\Psr\Http\Message\ResponseInterface
97
     * @throws \Exception
98
     */
99
    public function call($verb, $endpoint, $options = [])
100
    {
101
        if ($this->validMethod($verb)) {
102
            // Get the headers and body from the options.
103
            $headers = isset($options['headers']) ? $options['headers'] : [];
104
            $body = isset($options['body']) ? $options['body'] : null;
105
            $pv = isset($options['protocol_version']) ? $options['protocol_version'] : '1.1';
106
            // Make the request.
107
            $request = new Request($verb, $endpoint, $headers, $body, $pv);
108
            // Save the request as the last request.
109
            $this->last_request = $request;
110
            // Send it.
111
            $response = $this->client->send($request, $options);
112
            if ($response instanceof ResponseInterface) {
113
                // Set the last response.
114
                $this->last_response = $response;
115
                // If the caller wants the raw response, give it to them.
116
                if (isset($options['parse_response']) && $options['parse_response'] === false) {
117
                    return $response;
118
                }
119
                $parsed_response = $this->parseResponse($response);
120
                return $parsed_response;
121
            } else {
122
                // This only really happens when the network is interrupted.
123
                throw new BadResponseException('A bad response was received.',
124
                    $request);
125
            }
126
        } else {
127
            throw new \Exception('Unrecognised HTTP verb.');
128
        }
129
    }
130
131
    /**
132
     * A slightly abstracted wrapper around call().
133
     *
134
     * This essentially splits the call options array into different parameters
135
     * to make it more obvious to less advanced users what parameters can be
136
     * passed to the client.
137
     *
138
     * @param string $verb
139
     * @param string $endpoint
140
     * @param null   $params
141
     * @param null   $body
142
     * @param null   $headers
143
     * @param array  $options
144
     *
145
     * @return array|mixed|\Psr\Http\Message\ResponseInterface
146
     * @throws \Exception
147
     */
148
    public function makeRequest($verb, $endpoint, $params = null, $body = null, $headers = null, $options = [])
149
    {
150
        // We can only have one body, so overwrite it if it exists.
151
        if ($body !== null) {
152
            $options['body'] = $body;
153
        }
154
        // Merge the mergeable arrays if necessary.
155
        $mergeable = [
156
            'query' => $params,
157
            'headers' => $headers,
158
        ];
159
        foreach ($mergeable as $key => $value) {
160
            if ($value !== null) {
161
                if (!isset($options[$key])) {
162
                    $options[$key] = [];
163
                }
164
                $options[$key] = array_merge($options[$key], $value);
165
            }
166
        }
167
        // Make the call.
168
        return $this->call($verb, $endpoint, $options);
169
    }
170
171
    /**
172
     * Checks if the HTTP method being used is correct.
173
     *
174
     * @param string $http_method
175
     *
176
     * @return bool
177
     */
178
    public function validMethod($http_method)
179
    {
180
        if (in_array(strtolower($http_method), self::$valid_verbs)) {
181
            return true;
182
        }
183
        return false;
184
    }
185
186
    /**
187
     * Parses the response from
188
     *
189
     * @param \Psr\Http\Message\ResponseInterface $response
190
     *
191
     * @return array
192
     */
193
    public function parseResponse(ResponseInterface $response)
194
    {
195
        $body = $response->getBody()->getContents();
196
        return [
197
            'code' => $response->getStatusCode(),
198
            'headers' => $response->getHeaders(),
199
            'body' => ($this->isValidJson($body)) ? json_decode($body,
200
                true) : $body,
201
        ];
202
    }
203
204
    /**
205
     * Checks a string to see if it's JSON. True if it is, false if it's not.
206
     *
207
     * @param string $string
208
     *
209
     * @return bool
210
     */
211
    public function isValidJson($string)
212
    {
213
        if (is_string($string)) {
214
            json_decode($string);
215
            return (json_last_error() === JSON_ERROR_NONE);
216
        }
217
        return false;
218
    }
219
220
    /**
221
     * Checks if the class can connect to the Eventbrite API.
222
     *
223
     * Checks if we can connect to the API by calling the user endpoint and
224
     * checking the response code. If the response code is 2xx it returns true,
225
     * otherwise false.
226
     *
227
     * @return bool
228
     */
229
    public function canConnect()
230
    {
231
        $data = $this->get(self::CURRENT_USER_ENDPOINT);
0 ignored issues
show
Documentation Bug introduced by
The method get does not exist on object<jamiehollern\eventbrite\Eventbrite>? 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...
232
        if (strpos($data['code'], '2') === 0) {
233
            return true;
234
        }
235
        return false;
236
    }
237
238
    /**
239
     * Provides shortcut methods named by HTTP verbs.
240
     *
241
     * Provides shortcut methods for GET, POST, PUT, PATCH and DELETE.
242
     *
243
     * @param string $method
244
     * @param array  $args
245
     *
246
     * @return array|mixed|\Psr\Http\Message\ResponseInterface
247
     * @throws \Exception
248
     */
249
    public function __call($method, $args) {
250
        if ($this->validMethod($method)) {
251
            array_unshift($args, $method);
252
            return call_user_func_array(array($this, 'makeRequest'), $args);
253
        } else {
254
            throw new \BadMethodCallException('Method not found in class.');
255
        }
256
    }
257
258
    /**
259
     * Returns the last request object for inspection.
260
     *
261
     * @return \GuzzleHttp\Psr7\Request
262
     */
263
    public function getLastRequest()
264
    {
265
        return $this->last_request;
266
    }
267
268
    /**
269
     * Returns the last response object for inspection.
270
     *
271
     * @return \Psr\Http\Message\ResponseInterface
272
     */
273
    public function getLastResponse()
274
    {
275
        return $this->last_response;
276
    }
277
278
}
279