Skip to content

Commit 10bbd5a

Browse files
authored
Merge pull request #6954 from michalsn/fix/getVar-getJsonVar
fix: don't change the variable type and filter all values in JSON request
2 parents ddf1af1 + 99d8bb8 commit 10bbd5a

3 files changed

Lines changed: 134 additions & 30 deletions

File tree

system/HTTP/IncomingRequest.php

Lines changed: 53 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -518,20 +518,6 @@ public function getVar($index = null, $filter = null, $flags = null)
518518
strpos($this->getHeaderLine('Content-Type'), 'application/json') !== false
519519
&& $this->body !== null
520520
) {
521-
if ($index === null) {
522-
return $this->getJSON();
523-
}
524-
525-
if (is_array($index)) {
526-
$output = [];
527-
528-
foreach ($index as $key) {
529-
$output[$key] = $this->getJsonVar($key, false, $filter, $flags);
530-
}
531-
532-
return $output;
533-
}
534-
535521
return $this->getJsonVar($index, false, $filter, $flags);
536522
}
537523

@@ -561,35 +547,76 @@ public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0)
561547
/**
562548
* Get a specific variable from a JSON input stream
563549
*
564-
* @param string $index The variable that you want which can use dot syntax for getting specific values.
565-
* @param bool $assoc If true, return the result as an associative array.
566-
* @param int|null $filter Filter Constant
567-
* @param array|int|null $flags Option
550+
* @param array|string|null $index The variable that you want which can use dot syntax for getting specific values.
551+
* @param bool $assoc If true, return the result as an associative array.
552+
* @param int|null $filter Filter Constant
553+
* @param array|int|null $flags Option
568554
*
569555
* @return array|bool|float|int|stdClass|string|null
570556
*/
571-
public function getJsonVar(string $index, bool $assoc = false, ?int $filter = null, $flags = null)
557+
public function getJsonVar($index = null, bool $assoc = false, ?int $filter = null, $flags = null)
572558
{
573559
helper('array');
574560

575-
$json = $this->getJSON(true);
576-
if (! is_array($json)) {
561+
$data = $this->getJSON(true);
562+
if (! is_array($data)) {
577563
return null;
578564
}
579-
$data = dot_array_search($index, $json);
565+
566+
if (is_string($index)) {
567+
$data = dot_array_search($index, $data);
568+
} elseif (is_array($index)) {
569+
$result = [];
570+
571+
foreach ($index as $key) {
572+
$result[$key] = dot_array_search($key, $data);
573+
}
574+
575+
[$data, $result] = [$result, null];
576+
}
580577

581578
if ($data === null) {
582579
return null;
583580
}
584581

585-
if (! is_array($data)) {
586-
$filter ??= FILTER_DEFAULT;
587-
$flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
582+
$filter ??= FILTER_DEFAULT;
583+
$flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
588584

589-
return filter_var($data, $filter, $flags);
585+
if ($filter !== FILTER_DEFAULT
586+
|| (
587+
(is_numeric($flags) && $flags !== 0)
588+
|| is_array($flags) && $flags !== []
589+
)
590+
) {
591+
if (is_array($data)) {
592+
// Iterate over array and append filter and flags
593+
array_walk_recursive($data, static function (&$val) use ($filter, $flags) {
594+
$valType = gettype($val);
595+
$val = filter_var($val, $filter, $flags);
596+
597+
if (in_array($valType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $val !== false) {
598+
settype($val, $valType);
599+
}
600+
});
601+
} else {
602+
$dataType = gettype($data);
603+
$data = filter_var($data, $filter, $flags);
604+
605+
if (in_array($dataType, ['int', 'integer', 'float', 'double', 'bool', 'boolean'], true) && $data !== false) {
606+
settype($data, $dataType);
607+
}
608+
}
590609
}
591610

592611
if (! $assoc) {
612+
if (is_array($index)) {
613+
foreach ($data as &$val) {
614+
$val = is_array($val) ? json_decode(json_encode($val)) : $val;
615+
}
616+
617+
return $data;
618+
}
619+
593620
return json_decode(json_encode($data));
594621
}
595622

tests/system/HTTP/IncomingRequestTest.php

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,8 +295,13 @@ public function testCanGrabGetRawJSON()
295295
public function testCanGetAVariableFromJson()
296296
{
297297
$jsonObj = [
298-
'foo' => 'bar',
299-
'baz' => ['fizz' => 'buzz'],
298+
'foo' => 'bar',
299+
'baz' => ['fizz' => 'buzz'],
300+
'int' => 123,
301+
'float' => 3.14,
302+
'true' => true,
303+
'false' => false,
304+
'null' => null,
300305
];
301306
$json = json_encode($jsonObj);
302307

@@ -312,14 +317,24 @@ public function testCanGetAVariableFromJson()
312317
$this->assertIsObject($jsonVar);
313318
$this->assertSame('buzz', $jsonVar->fizz);
314319
$this->assertSame('buzz', $request->getJsonVar('baz.fizz'));
320+
$this->assertSame(123, $request->getJsonVar('int'));
321+
$this->assertSame(3.14, $request->getJsonVar('float'));
322+
$this->assertTrue($request->getJsonVar('true'));
323+
$this->assertFalse($request->getJsonVar('false'));
324+
$this->assertNull($request->getJsonVar('null'));
315325
}
316326

317327
public function testGetJsonVarAsArray()
318328
{
319329
$jsonObj = [
320330
'baz' => [
321-
'fizz' => 'buzz',
322-
'foo' => 'bar',
331+
'fizz' => 'buzz',
332+
'foo' => 'bar',
333+
'int' => 123,
334+
'float' => 3.14,
335+
'true' => true,
336+
'false' => false,
337+
'null' => null,
323338
],
324339
];
325340
$json = json_encode($jsonObj);
@@ -333,6 +348,11 @@ public function testGetJsonVarAsArray()
333348
$this->assertIsArray($jsonVar);
334349
$this->assertSame('buzz', $jsonVar['fizz']);
335350
$this->assertSame('bar', $jsonVar['foo']);
351+
$this->assertSame(123, $jsonVar['int']);
352+
$this->assertSame(3.14, $jsonVar['float']);
353+
$this->assertTrue($jsonVar['true']);
354+
$this->assertFalse($jsonVar['false']);
355+
$this->assertNull($jsonVar['null']);
336356
}
337357

338358
public function testGetJsonVarCanFilter()
@@ -347,6 +367,59 @@ public function testGetJsonVarCanFilter()
347367
$this->assertFalse($request->getJsonVar('foo', false, FILTER_VALIDATE_INT));
348368
}
349369

370+
public function testGetJsonVarCanFilterArray()
371+
{
372+
$json = json_encode([
373+
'string' => 'hello123world',
374+
'int' => 123,
375+
'float' => 3.14,
376+
'stringFloat' => 'hello3.14world',
377+
'array' => [
378+
'string' => 'hello123world',
379+
'int' => 123,
380+
],
381+
]);
382+
383+
$config = new App();
384+
$config->baseURL = 'http://example.com/';
385+
386+
$request = new IncomingRequest($config, new URI(), $json, new UserAgent());
387+
$request->setHeader('Content-Type', 'application/json');
388+
389+
$expected = [
390+
'string' => '123',
391+
'int' => 123,
392+
'float' => 3.14,
393+
'stringFloat' => '3.14',
394+
'array' => [
395+
'string' => '123',
396+
'int' => 123,
397+
],
398+
];
399+
400+
$this->assertSame(
401+
$expected,
402+
$request->getJsonVar(null, true, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)
403+
);
404+
405+
$this->assertSame(
406+
$expected['array'],
407+
$request->getJsonVar('array', true, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)
408+
);
409+
410+
$this->assertSame(
411+
['array' => $expected['array'], 'float' => $expected['float']],
412+
$request->getJsonVar(['array', 'float'], true, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION)
413+
);
414+
415+
$result = $request->getJsonVar(['array', 'float'], false, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION);
416+
$this->assertIsObject($result['array']);
417+
$this->assertSame(
418+
['array' => $expected['array'], 'float' => $expected['float']],
419+
['array' => json_decode(json_encode($result['array']), true), 'float' => $result['float']],
420+
);
421+
}
422+
350423
public function testGetVarWorksWithJson()
351424
{
352425
$json = json_encode(['foo' => 'bar', 'fizz' => 'buzz']);

user_guide_src/source/changelogs/v4.3.0.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ Others
185185
- ``Debug\Exceptions::__construct()``
186186
- ``Services::exceptions()``
187187

188+
- **Request:** The ``$index`` parameter of ``IncomingRequest::getJsonVar()`` now accepts an ``array``, ``string`` or ``null`` value.
189+
188190
Enhancements
189191
************
190192

@@ -343,3 +345,5 @@ Bugs Fixed
343345
**********
344346

345347
- Fixed a bug when all types of ``Prepared Queries`` were returning a ``Result`` object instead of a bool value for write-type queries.
348+
- Fixed a bug with variable filtering in JSON requests using with ``IncomingRequest::getVar()`` or ``IncomingRequest::getJsonVar()`` methods.
349+
- Fixed a bug when variable type may be changed when using a specified index with ``IncomingRequest::getVar()`` or ``IncomingRequest::getJsonVar()`` methods.

0 commit comments

Comments
 (0)