Issues (1131)

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.

src/response/Response.class.php (7 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
namespace Agavi\Response;
4
5
// +---------------------------------------------------------------------------+
6
// | This file is part of the Agavi package.                                   |
7
// | Copyright (c) 2005-2011 the Agavi Project.                                |
8
// |                                                                           |
9
// | For the full copyright and license information, please view the LICENSE   |
10
// | file that was distributed with this source code. You can also view the    |
11
// | LICENSE file online at http://www.agavi.org/LICENSE.txt                   |
12
// |   vi: set noexpandtab:                                                    |
13
// |   Local Variables:                                                        |
14
// |   indent-tabs-mode: t                                                     |
15
// |   End:                                                                    |
16
// +---------------------------------------------------------------------------+
17
use Agavi\Core\Context;
18
use Agavi\Dispatcher\OutputType;
19
use Agavi\Util\AttributeHolder;
20
21
/**
22
 * AgaviResponse handles the output and other stuff sent back to the client.
23
 *
24
 * @package    agavi
25
 * @subpackage response
26
 *
27
 * @author     David Zülke <[email protected]>
28
 * @copyright  Authors
29
 * @copyright  The Agavi Project
30
 *
31
 * @since      0.11.0
32
 *
33
 * @version    $Id$
34
 */
35
abstract class Response extends AttributeHolder
36
{
37
    /**
38
     * @var        Context An Context instance.
39
     */
40
    protected $context = null;
41
    
42
    /**
43
     * @var        mixed The content to send back to the client.
44
     */
45
    protected $content = null;
46
    
47
    /**
48
     * @var        OutputType The output type of this response.
49
     */
50
    protected $outputType = null;
51
    
52
    /**
53
     * Pre-serialization callback.
54
     *
55
     * Will set the name of the context and exclude the instance from serializing.
56
     *
57
     * @author     David Zülke <[email protected]>
58
     * @since      0.11.0
59
     */
60
    public function __sleep()
61
    {
62
        $vars = get_object_vars($this);
63
        $also = array();
64
        
65
        $this->contextName = $this->context->getName();
0 ignored issues
show
The property contextName does not seem to exist. Did you mean context?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
66
        unset($vars['context']);
67
        $also[] = 'contextName';
68
        
69
        if ($this->outputType) {
70
            $this->outputTypeName = $this->outputType->getName();
0 ignored issues
show
The property outputTypeName does not seem to exist. Did you mean outputType?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
71
            unset($vars['outputType']);
72
            $also[] = 'outputTypeName';
73
        }
74
        
75
        if (is_resource($this->content)) {
76
            $this->contentStreamMeta = stream_get_meta_data($this->content);
0 ignored issues
show
The property contentStreamMeta does not seem to exist. Did you mean content?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
77
            unset($vars['content']);
78
            $also[] = 'contentStreamMeta';
79
        }
80
        
81
        return array_merge(array_keys($vars), $also);
82
    }
83
    
84
    /**
85
     * Post-unserialization callback.
86
     *
87
     * Will restore the context based on the names set by __sleep.
88
     *
89
     * @author     David Zülke <[email protected]>
90
     * @since      0.11.0
91
     */
92
    public function __wakeup()
93
    {
94
        $this->context = Context::getInstance($this->contextName);
0 ignored issues
show
The property contextName does not seem to exist. Did you mean context?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
95
        unset($this->contextName);
96
        
97
        if (isset($this->outputTypeName)) {
98
            $this->outputType = $this->context->getDispatcher()->getOutputType($this->outputTypeName);
0 ignored issues
show
The property outputTypeName does not seem to exist. Did you mean outputType?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
99
            unset($this->outputTypeName);
100
        }
101
        
102
        if (isset($this->contentStreamMeta)) {
103
            // contrary to what the documentation says, stream_get_meta_data() will not return a list of filters attached to the stream, so we cannot restore these, unfortunately.
104
            $this->content = fopen($this->contentStreamMeta['uri'], $this->contentStreamMeta['mode']);
0 ignored issues
show
The property contentStreamMeta does not seem to exist. Did you mean content?

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
105
            unset($this->contentStreamMeta);
106
        }
107
    }
108
    
109
    /**
110
     * Retrieve the Context instance this Response object belongs to.
111
     *
112
     * @return     Context An Context instance.
113
     *
114
     * @author     David Zülke <[email protected]>
115
     * @since      0.11.0
116
     */
117
    final public function getContext()
118
    {
119
        return $this->context;
120
    }
121
    
122
    /**
123
     * Initialize this Response.
124
     *
125
     * @param      Context $context    An Context instance.
126
     * @param      array   $parameters An array of initialization parameters.
127
     *
128
     * @author     David Zülke <[email protected]>
129
     * @since      0.11.0
130
     */
131
    public function initialize(Context $context, array $parameters = array())
132
    {
133
        $this->context = $context;
134
        $this->setParameters($parameters);
135
    }
136
    
137
    /**
138
     * Get the Output Type to use with this response.
139
     *
140
     * @return     OutputType The Output Type instance associated with.
141
     *
142
     * @author     David Zülke <[email protected]>
143
     * @since      0.11.1
144
     */
145
    public function getOutputType()
146
    {
147
        return $this->outputType;
148
    }
149
    
150
    /**
151
     * Set the Output Type to use with this response.
152
     *
153
     * @param      OutputType $outputType The Output Type instance to associate with.
154
     *
155
     * @author     David Zülke <[email protected]>
156
     * @since      0.11.1
157
     */
158
    public function setOutputType(OutputType $outputType)
159
    {
160
        $this->outputType = $outputType;
161
    }
162
    
163
    /**
164
     * Clear the Output Type to use with this response.
165
     *
166
     * @author     David Zülke <[email protected]>
167
     * @since      0.11.1
168
     */
169
    public function clearOutputType()
170
    {
171
        $this->outputType = null;
172
    }
173
    
174
    /**
175
     * Retrieve the content set for this Response.
176
     *
177
     * @return     mixed The content set in this Response.
178
     *
179
     * @author     David Zülke <[email protected]>
180
     * @since      0.11.0
181
     */
182
    public function getContent()
183
    {
184
        return $this->content;
185
    }
186
    
187
    /**
188
     * Check whether or not some content is set.
189
     *
190
     * @return     bool If any content is set, false otherwise.
191
     *
192
     * @author     David Zülke <[email protected]>
193
     * @since      0.11.6
194
     */
195
    public function hasContent()
196
    {
197
        return $this->content !== null;
198
    }
199
    
200
    /**
201
     * Retrieve the size (in bytes) of the content set for this Response.
202
     *
203
     * @return     int The content size in bytes.
204
     *
205
     * @author     David Zülke <[email protected]>
206
     * @since      0.11.0
207
     */
208
    public function getContentSize()
209
    {
210
        if (is_resource($this->content)) {
211
            if (($stat = fstat($this->content)) !== false) {
212
                return $stat['size'];
213
            } else {
214
                return false;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return false; (false) is incompatible with the return type documented by Agavi\Response\Response::getContentSize of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
215
            }
216
        } else {
217
            return strlen($this->content);
218
        }
219
    }
220
    
221
    /**
222
     * Set the content for this Response.
223
     *
224
     * @param      mixed $content The content to be sent in this Response.
225
     *
226
     * @author     David Zülke <[email protected]>
227
     * @since      0.11.0
228
     */
229
    public function setContent($content)
230
    {
231
        $this->content = $content;
232
    }
233
    
234
    /**
235
     * Prepend content to the existing content for this Response.
236
     *
237
     * @param      mixed $content The content to be prepended to this Response.
238
     *
239
     * @author     David Zülke <[email protected]>
240
     * @since      0.11.0
241
     */
242
    public function prependContent($content)
243
    {
244
        $this->setContent($content . $this->getContent());
245
    }
246
    
247
    /**
248
     * Append content to the existing content for this Response.
249
     *
250
     * @param      mixed $content The content to be appended to this Response.
251
     *
252
     * @author     David Zülke <[email protected]>
253
     * @since      0.11.0
254
     */
255
    public function appendContent($content)
256
    {
257
        $this->setContent($this->getContent() . $content);
258
    }
259
    
260
    /**
261
     * Clear the content for this Response
262
     *
263
     * @author     David Zülke <[email protected]>
264
     * @since      0.11.0
265
     */
266
    public function clearContent()
267
    {
268
        $this->content = null;
269
    }
270
    
271
    /**
272
     * Redirect externally.
273
     *
274
     * @param      mixed $to Where to redirect.
275
     *
276
     * @author     David Zülke <[email protected]>
277
     * @since      0.11.0
278
     */
279
    abstract public function setRedirect($to);
280
281
    /**
282
     * Get info about the set redirect.
283
     *
284
     * @return     array An assoc array of redirect info, or null if none set.
285
     *
286
     * @author     David Zülke <[email protected]>
287
     * @since      0.11.0
288
     */
289
    abstract public function getRedirect();
290
291
    /**
292
     * Check if a redirect is set.
293
     *
294
     * @return     bool true, if a redirect is set, otherwise false
295
     *
296
     * @author     David Zülke <[email protected]>
297
     * @since      0.11.0
298
     */
299
    abstract public function hasRedirect();
300
301
    /**
302
     * Clear any set redirect information.
303
     *
304
     * @author     David Zülke <[email protected]>
305
     * @since      0.11.0
306
     */
307
    abstract public function clearRedirect();
308
309
    /**
310
     * Import response metadata from another response.
311
     *
312
     * @param      Response $otherResponse The other response to import information from.
313
     *
314
     * @author     David Zülke <[email protected]>
315
     * @since      0.11.0
316
     */
317
    public function merge(Response $otherResponse)
318
    {
319
        foreach ($otherResponse->getAttributeNamespaces() as $namespace) {
320
            foreach ($otherResponse->getAttributes($namespace) as $name => $value) {
321
                if (!$this->hasAttribute($name, $namespace)) {
322
                    $this->setAttribute($name, $value, $namespace);
323
                } elseif (is_array($value)) {
324
                    $thisAttribute =& $this->getAttribute($name, $namespace);
325
                    if (is_array($thisAttribute)) {
326
                        $thisAttribute = array_merge($value, $thisAttribute);
327
                    }
328
                }
329
            }
330
        }
331
    }
332
    
333
    /**
334
     * Clear all data for this Response.
335
     *
336
     * @author     David Zülke <[email protected]>
337
     * @since      0.11.0
338
     */
339
    abstract public function clear();
340
    
341
    /**
342
     * Send all response data to the client.
343
     *
344
     * @param      OutputType $outputType An optional Output Type object with information
345
     *                                    the response can use to send additional data.
346
     *
347
     * @author     David Zülke <[email protected]>
348
     * @since      0.11.0
349
     */
350
    abstract public function send(OutputType $outputType = null);
351
    
352
    /**
353
     * Determine whether the content in the response may be modified by appending
354
     * or prepending data using string operations. Typically false for streams,
355
     * and for responses like XMLRPC where the content is an array.
356
     *
357
     * @return     bool If the content can be treated as / changed like a string.
358
     *
359
     * @author     David Zülke <[email protected]>
360
     * @since      0.11.0
361
     */
362
    public function isContentMutable()
363
    {
364
        return !$this->hasRedirect() && !is_resource($this->content);
365
    }
366
    
367
    /**
368
     * Send the content for this response
369
     *
370
     * @author     David Zülke <[email protected]>
371
     * @since      0.11.0
372
     */
373
    protected function sendContent()
374
    {
375
        if (is_resource($this->content)) {
376
            fpassthru($this->content);
377
            fclose($this->content);
378
        } else {
379
            echo $this->content;
380
        }
381
    }
382
}
383