Completed
Push — master ( fff73d...f066e6 )
by Thierry
01:44
created

src/Request/Handler.php (2 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
 * Manager.php - Jaxon Request Manager
5
 *
6
 * This class processes the input arguments from the GET or POST data of the request.
7
 * If this is a request for the initial page load, no arguments will be processed.
8
 * During a jaxon request, any arguments found in the GET or POST will be converted to a PHP array.
9
 *
10
 * @package jaxon-core
11
 * @author Jared White
12
 * @author J. Max Wilson
13
 * @author Joseph Woolley
14
 * @author Steffen Konerow
15
 * @author Thierry Feuzeu <[email protected]>
16
 * @copyright Copyright (c) 2005-2007 by Jared White & J. Max Wilson
17
 * @copyright Copyright (c) 2008-2010 by Joseph Woolley, Steffen Konerow, Jared White  & J. Max Wilson
18
 * @copyright 2016 Thierry Feuzeu <[email protected]>
19
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
20
 * @link https://github.com/jaxon-php/jaxon-core
21
 */
22
23
namespace Jaxon\Request;
24
25
use Jaxon\Jaxon;
26
27
use Jaxon\Plugin\Manager as PluginManager;
28
29
class Handler
30
{
31
    use \Jaxon\Utils\Traits\Config;
32
    use \Jaxon\Utils\Traits\Translator;
33
34
    /**
35
     * The plugin manager.
36
     *
37
     * @var PluginManager
38
     */
39
    private $xPluginManager;
40
41
    /**
42
     * An array of arguments received via the GET or POST parameter jxnargs.
43
     *
44
     * @var array
45
     */
46
    private $aArgs;
47
48
    /**
49
     * Stores the method that was used to send the arguments from the client.
50
     * Will be one of: Jaxon::METHOD_UNKNOWN, Jaxon::METHOD_GET, Jaxon::METHOD_POST.
51
     *
52
     * @var integer
53
     */
54
    private $nMethod;
55
56
    /**
57
     * The constructor
58
     *
59
     * Get and decode the arguments of the HTTP request
60
     *
61
     * @param PluginManager         $xPluginManager
62
     */
63
    public function __construct(PluginManager $xPluginManager)
64
    {
65
        $this->xPluginManager = $xPluginManager;
66
67
        $this->aArgs = [];
68
        $this->nMethod = Jaxon::METHOD_UNKNOWN;
69
70
        if(isset($_POST['jxnargs']))
71
        {
72
            $this->nMethod = Jaxon::METHOD_POST;
73
            $this->aArgs = $_POST['jxnargs'];
74
        }
75
        elseif(isset($_GET['jxnargs']))
76
        {
77
            $this->nMethod = Jaxon::METHOD_GET;
78
            $this->aArgs = $_GET['jxnargs'];
79
        }
80
        if(get_magic_quotes_gpc() == 1)
81
        {
82
            array_walk($this->aArgs, array(&$this, '__argumentStripSlashes'));
83
        }
84
        array_walk($this->aArgs, array(&$this, '__argumentDecode'));
85
    }
86
87
    /**
88
     * Converts a string to a boolean var
89
     *
90
     * @param string        $sValue                The string to be converted
91
     *
92
     * @return boolean
93
     */
94
    private function __convertStringToBool($sValue)
95
    {
96
        if(strcasecmp($sValue, 'true') == 0)
97
        {
98
            return true;
99
        }
100
        if(strcasecmp($sValue, 'false') == 0)
101
        {
102
            return false;
103
        }
104
        if(is_numeric($sValue))
105
        {
106
            if($sValue == 0)
107
            {
108
                return false;
109
            }
110
            return true;
111
        }
112
        return false;
113
    }
114
115
    /**
116
     * Strip the slashes from a string
117
     *
118
     * @param string        $sArg                The string to be stripped
119
     *
120
     * @return string
121
     */
122
    private function __argumentStripSlashes(&$sArg)
123
    {
124
        if(!is_string($sArg))
125
        {
126
            return '';
127
        }
128
        $sArg = stripslashes($sArg);
129
    }
130
131
    /**
132
     * Convert an Jaxon request argument to its value
133
     *
134
     * Depending of its first char, the Jaxon request argument is converted to a given type.
135
     *
136
     * @param string        $sValue                The keys of the options in the file
137
     *
138
     * @return mixed
139
     */
140
    private function __convertValue($sValue)
141
    {
142
        $cType = substr($sValue, 0, 1);
143
        $sValue = substr($sValue, 1);
144
        switch ($cType)
145
        {
146
            case 'S':
147
                $value = ($sValue === false ? '' : $sValue);
148
                break;
149
            case 'B':
150
                $value = $this->__convertStringToBool($sValue);
151
                break;
152
            case 'N':
153
                $value = ($sValue == floor($sValue) ? (int)$sValue : (float)$sValue);
154
                break;
155
            case '*':
156
            default:
157
                $value = null;
158
                break;
159
        }
160
        return $value;
161
    }
162
163
    /**
164
     * Decode and convert an Jaxon request argument from JSON
165
     *
166
     * @param string        $sArg                The Jaxon request argument
167
     *
168
     * @return mixed
169
     */
170
    private function __argumentDecode(&$sArg)
171
    {
172
        if($sArg == '')
173
        {
174
            return '';
175
        }
176
177
        // Arguments are url encoded when uploading files
178
        $sType = 'multipart/form-data';
179
        $iLen = strlen($sType);
180
        $sContentType = '';
181
        if(key_exists('CONTENT_TYPE', $_SERVER))
182
        {
183
            $sContentType = substr($_SERVER['CONTENT_TYPE'], 0, $iLen);
184
        }
185
        elseif(key_exists('HTTP_CONTENT_TYPE', $_SERVER))
186
        {
187
            $sContentType = substr($_SERVER['HTTP_CONTENT_TYPE'], 0, $iLen);
188
        }
189
        if($sContentType == $sType)
190
        {
191
            $sArg = urldecode($sArg);
192
        }
193
194
        $data = json_decode($sArg, true);
195
196
        if($data !== null && $sArg != $data)
197
        {
198
            $sArg = $data;
199
        }
200
        else
201
        {
202
            $sArg = $this->__convertValue($sArg);
203
        }
204
    }
205
206
    /**
207
     * Decode an Jaxon request argument and convert to UTF8 with iconv
208
     *
209
     * @param string|array        $mArg                The Jaxon request argument
210
     *
211
     * @return void
212
     */
213
    private function __argumentDecodeUTF8_iconv(&$mArg)
214
    {
215
        if(is_array($mArg))
216
        {
217
            foreach($mArg as $sKey => &$xArg)
218
            {
219
                $sNewKey = $sKey;
220
                $this->__argumentDecodeUTF8_iconv($sNewKey);
221
                if($sNewKey != $sKey)
222
                {
223
                    $mArg[$sNewKey] = $xArg;
224
                    unset($mArg[$sKey]);
225
                    $sKey = $sNewKey;
226
                }
227
                $this->__argumentDecodeUTF8_iconv($xArg);
228
            }
229
        }
230
        elseif(is_string($mArg))
231
        {
232
            $mArg = iconv("UTF-8", $this->getOption('core.encoding') . '//TRANSLIT', $mArg);
233
        }
234
    }
235
236
    /**
237
     * Decode an Jaxon request argument and convert to UTF8 with mb_convert_encoding
238
     *
239
     * @param string|array        $mArg                The Jaxon request argument
240
     *
241
     * @return void
242
     */
243 View Code Duplication
    private function __argumentDecodeUTF8_mb_convert_encoding(&$mArg)
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...
244
    {
245
        if(is_array($mArg))
246
        {
247
            foreach($mArg as $sKey => &$xArg)
248
            {
249
                $sNewKey = $sKey;
250
                $this->__argumentDecodeUTF8_mb_convert_encoding($sNewKey);
251
                if($sNewKey != $sKey)
252
                {
253
                    $mArg[$sNewKey] = $xArg;
254
                    unset($mArg[$sKey]);
255
                    $sKey = $sNewKey;
256
                }
257
                $this->__argumentDecodeUTF8_mb_convert_encoding($xArg);
258
            }
259
        }
260
        elseif(is_string($mArg))
261
        {
262
            $mArg = mb_convert_encoding($mArg, $this->getOption('core.encoding'), "UTF-8");
263
        }
264
    }
265
266
    /**
267
     * Decode an Jaxon request argument from UTF8
268
     *
269
     * @param string|array        $mArg                The Jaxon request argument
270
     *
271
     * @return void
272
     */
273 View Code Duplication
    private function __argumentDecodeUTF8_utf8_decode(&$mArg)
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...
274
    {
275
        if(is_array($mArg))
276
        {
277
            foreach($mArg as $sKey => &$xArg)
278
            {
279
                $sNewKey = $sKey;
280
                $this->__argumentDecodeUTF8_utf8_decode($sNewKey);
281
282
                if($sNewKey != $sKey)
283
                {
284
                    $mArg[$sNewKey] = $xArg;
285
                    unset($mArg[$sKey]);
286
                    $sKey = $sNewKey;
287
                }
288
289
                $this->__argumentDecodeUTF8_utf8_decode($xArg);
290
            }
291
        }
292
        elseif(is_string($mArg))
293
        {
294
            $mArg = utf8_decode($mArg);
295
        }
296
    }
297
298
    /**
299
     * Return the method that was used to send the arguments from the client
300
     *
301
     * The method is one of: Jaxon::METHOD_UNKNOWN, Jaxon::METHOD_GET, Jaxon::METHOD_POST.
302
     *
303
     * @return integer
304
     */
305
    public function getRequestMethod()
306
    {
307
        return $this->nMethod;
308
    }
309
310
    /**
311
     * Return the array of arguments that were extracted and parsed from the GET or POST data
312
     *
313
     * @return array
314
     */
315
    public function processArguments()
316
    {
317
        if(($this->getOption('core.decode_utf8')))
318
        {
319
            $sFunction = '';
320
321
            if(function_exists('iconv'))
322
            {
323
                $sFunction = "iconv";
324
            }
325
            elseif(function_exists('mb_convert_encoding'))
326
            {
327
                $sFunction = "mb_convert_encoding";
328
            }
329
            elseif($this->getOption('core.encoding') == "ISO-8859-1")
330
            {
331
                $sFunction = "utf8_decode";
332
            }
333
            else
334
            {
335
                throw new \Jaxon\Exception\Error($this->trans('errors.request.conversion'));
336
            }
337
338
            $mFunction = array(&$this, '__argumentDecodeUTF8_' . $sFunction);
339
            array_walk($this->aArgs, $mFunction);
340
            $this->setOption('core.decode_utf8', false);
341
        }
342
343
        return $this->aArgs;
344
    }
345
346
    /**
347
     * Check if the current request can be processed
348
     *
349
     * Calls each of the request plugins and determines if the current request can be processed by one of them.
350
     * If no processor identifies the current request, then the request must be for the initial page load.
351
     *
352
     * @return boolean
353
     */
354
    public function canProcessRequest()
355
    {
356
        foreach($this->xPluginManager->getRequestPlugins() as $xPlugin)
357
        {
358
            if($xPlugin->getName() != Jaxon::FILE_UPLOAD && $xPlugin->canProcessRequest())
359
            {
360
                return true;
361
            }
362
        }
363
        return false;
364
    }
365
366
    /**
367
     * Process the current request
368
     *
369
     * Calls each of the request plugins to request that they process the current request.
370
     * If any plugin processes the request, it will return true.
371
     *
372
     * @return boolean
373
     */
374
    public function processRequest()
375
    {
376
        foreach($this->xPluginManager->getRequestPlugins() as $xPlugin)
377
        {
378
            if($xPlugin->getName() != Jaxon::FILE_UPLOAD && $xPlugin->canProcessRequest())
379
            {
380
                $xUploadPlugin = $this->xPluginManager->getRequestPlugin(Jaxon::FILE_UPLOAD);
381
                // Process uploaded files
382
                if($xUploadPlugin != null)
383
                {
384
                    $xUploadPlugin->processRequest();
385
                }
386
                // Process the request
387
                return $xPlugin->processRequest();
388
            }
389
        }
390
        // Todo: throw an exception
391
        return false;
392
    }
393
}
394