Completed
Push — master ( 9b4408...bfd5a5 )
by Thierry
01:45
created

Argument::__argumentStripSlashes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
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\Handler;
24
25
class Argument
26
{
27
    use \Jaxon\Features\Config;
28
    use \Jaxon\Features\Translator;
29
30
    /*
31
     * Request methods
32
     */
33
    const METHOD_UNKNOWN = 0;
34
    const METHOD_GET = 1;
35
    const METHOD_POST = 2;
36
37
    /**
38
     * An array of arguments received via the GET or POST parameter jxnargs.
39
     *
40
     * @var array
41
     */
42
    private $aArgs;
43
44
    /**
45
     * Stores the method that was used to send the arguments from the client.
46
     * Will be one of: self::METHOD_UNKNOWN, self::METHOD_GET, self::METHOD_POST.
47
     *
48
     * @var integer
49
     */
50
    private $nMethod;
51
52
    /**
53
     * The function which decodes utf8 string.
54
     *
55
     * @var Callable
56
     */
57
    private $cUtf8Decoder;
58
59
    /**
60
     * The constructor
61
     *
62
     * Get and decode the arguments of the HTTP request
63
     */
64
    public function __construct()
65
    {
66
        $this->aArgs = [];
67
        $this->nMethod = self::METHOD_UNKNOWN;
68
69
        if(isset($_POST['jxnargs']))
70
        {
71
            $this->nMethod = self::METHOD_POST;
72
            $this->aArgs = $_POST['jxnargs'];
73
        }
74
        elseif(isset($_GET['jxnargs']))
75
        {
76
            $this->nMethod = self::METHOD_GET;
77
            $this->aArgs = $_GET['jxnargs'];
78
        }
79
        if(get_magic_quotes_gpc() == 1)
80
        {
81
            array_walk($this->aArgs, [&$this, '__argumentStripSlashes']);
82
        }
83
        array_walk($this->aArgs, [&$this, '__argumentDecode']);
84
85
        // By default, no decoding
86
        $this->cUtf8Decoder = function($sStr) {
87
            return $sStr;
88
        };
89
    }
90
91
    /**
92
     * Return the method that was used to send the arguments from the client
93
     *
94
     * The method is one of: self::METHOD_UNKNOWN, self::METHOD_GET, self::METHOD_POST.
95
     *
96
     * @return integer
97
     */
98
    public function getRequestMethod()
99
    {
100
        return $this->nMethod;
101
    }
102
103
    /**
104
     * Converts a string to a boolean var
105
     *
106
     * @param string        $sValue                The string to be converted
107
     *
108
     * @return boolean
109
     */
110
    private function __convertStringToBool($sValue)
111
    {
112
        if(strcasecmp($sValue, 'true') == 0)
113
        {
114
            return true;
115
        }
116
        if(strcasecmp($sValue, 'false') == 0)
117
        {
118
            return false;
119
        }
120
        if(is_numeric($sValue))
121
        {
122
            if($sValue == 0)
123
            {
124
                return false;
125
            }
126
            return true;
127
        }
128
        return false;
129
    }
130
131
    /**
132
     * Strip the slashes from a string
133
     *
134
     * @param string        $sArg                The string to be stripped
135
     *
136
     * @return string
137
     */
138
    private function __argumentStripSlashes(&$sArg)
139
    {
140
        if(!is_string($sArg))
141
        {
142
            return '';
143
        }
144
        $sArg = stripslashes($sArg);
145
    }
146
147
    /**
148
     * Convert an Jaxon request argument to its value
149
     *
150
     * Depending of its first char, the Jaxon request argument is converted to a given type.
151
     *
152
     * @param string        $sValue                The keys of the options in the file
153
     *
154
     * @return mixed
155
     */
156
    private function __convertValue($sValue)
157
    {
158
        $cType = substr($sValue, 0, 1);
159
        $sValue = substr($sValue, 1);
160
        switch($cType)
161
        {
162
        case 'S':
163
            $value = ($sValue === false ? '' : $sValue);
164
            break;
165
        case 'B':
166
            $value = $this->__convertStringToBool($sValue);
167
            break;
168
        case 'N':
169
            $value = ($sValue == floor($sValue) ? (int)$sValue : (float)$sValue);
170
            break;
171
        case '*':
172
        default:
173
            $value = null;
174
            break;
175
        }
176
        return $value;
177
    }
178
179
    /**
180
     * Decode and convert an Jaxon request argument from JSON
181
     *
182
     * @param string        $sArg                The Jaxon request argument
183
     *
184
     * @return string|null
185
     */
186
    private function __argumentDecode(&$sArg)
187
    {
188
        if($sArg == '')
189
        {
190
            return '';
191
        }
192
193
        // Arguments are url encoded when uploading files
194
        $sType = 'multipart/form-data';
195
        $iLen = strlen($sType);
196
        $sContentType = '';
197
        if(key_exists('CONTENT_TYPE', $_SERVER))
198
        {
199
            $sContentType = substr($_SERVER['CONTENT_TYPE'], 0, $iLen);
200
        }
201
        elseif(key_exists('HTTP_CONTENT_TYPE', $_SERVER))
202
        {
203
            $sContentType = substr($_SERVER['HTTP_CONTENT_TYPE'], 0, $iLen);
204
        }
205
        if($sContentType == $sType)
206
        {
207
            $sArg = urldecode($sArg);
208
        }
209
210
        $data = json_decode($sArg, true);
211
212
        if($data !== null && $sArg != $data)
213
        {
214
            $sArg = $data;
215
        }
216
        else
217
        {
218
            $sArg = $this->__convertValue($sArg);
219
        }
220
    }
221
222
    /**
223
     * Decode an Jaxon request argument from UTF8
224
     *
225
     * @param array             &$aDst          An array to store the decoded arguments
226
     * @param string            $sKey           The key of the argument being decoded
227
     * @param string|array      $mValue         The value of the argument being decoded
228
     *
229
     * @return void
230
     */
231
    private function _decode_utf8_argument(array &$aDst, $sKey, $mValue)
232
    {
233
        $sDestKey = $sKey;
234
        // Decode the key
235
        if(is_string($sDestKey))
236
        {
237
            $sDestKey = call_user_func($this->cUtf8Decoder, $sDestKey);
238
        }
239
240
        if(is_array($mValue))
241
        {
242
            $aDst[$sDestKey] = [];
243
            foreach($mValue as $_sKey => &$_mValue)
244
            {
245
                $this->_decode_utf8_argument($aDst[$sDestKey], $_sKey, $_mValue);
246
            }
247
        }
248
        elseif(is_string($mValue))
249
        {
250
            $aDst[$sDestKey] = call_user_func($this->cUtf8Decoder, $mValue);
251
        }
252
        elseif(is_numeric($mValue))
253
        {
254
            $aDst[$sDestKey] = $mValue;
255
        }
256
    }
257
258
    /**
259
     * Return the array of arguments that were extracted and parsed from the GET or POST data
260
     *
261
     * @return array
262
     */
263
    public function process()
264
    {
265
        if(($this->getOption('core.decode_utf8')))
266
        {
267
            if(function_exists('iconv'))
268
            {
269
                $this->cUtf8Decoder = function($sStr) {
270
                    return iconv("UTF-8", $this->getOption('core.encoding') . '//TRANSLIT', $sStr);
271
                };
272
            }
273
            elseif(function_exists('mb_convert_encoding'))
274
            {
275
                $this->cUtf8Decoder = function($sStr) {
276
                    return mb_convert_encoding($sStr, $this->getOption('core.encoding'), "UTF-8");
277
                };
278
            }
279
            elseif($this->getOption('core.encoding') == "ISO-8859-1")
280
            {
281
                $this->cUtf8Decoder = function($sStr) {
282
                    return utf8_decode($sStr);
283
                };
284
            }
285
            else
286
            {
287
                throw new \Jaxon\Exception\Error($this->trans('errors.request.conversion'));
288
            }
289
290
            $aDst = [];
291
            foreach($this->aArgs as $sKey => &$mValue)
292
            {
293
                $this->_decode_utf8_argument($aDst, $sKey, $mValue);
294
            };
295
            $this->aArgs = $aDst;
296
297
            $this->setOption('core.decode_utf8', false);
298
        }
299
300
        return $this->aArgs;
301
    }
302
}
303