• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

codeigniter4 / CodeIgniter4 / 3719550582

pending completion
3719550582

push

github

GitHub
Merge pull request #6984 from kenjis/fix-large-http-input-crash

17 of 17 new or added lines in 1 file covered. (100.0%)

16177 of 18942 relevant lines covered (85.4%)

174.85 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.68
/system/HTTP/IncomingRequest.php
1
<?php
2

3
/**
4
 * This file is part of CodeIgniter 4 framework.
5
 *
6
 * (c) CodeIgniter Foundation <admin@codeigniter.com>
7
 *
8
 * For the full copyright and license information, please view
9
 * the LICENSE file that was distributed with this source code.
10
 */
11

12
namespace CodeIgniter\HTTP;
13

14
use CodeIgniter\HTTP\Exceptions\HTTPException;
15
use CodeIgniter\HTTP\Files\FileCollection;
16
use CodeIgniter\HTTP\Files\UploadedFile;
17
use Config\App;
18
use Config\Services;
19
use InvalidArgumentException;
20
use Locale;
21
use stdClass;
22

23
/**
24
 * Class IncomingRequest
25
 *
26
 * Represents an incoming, server-side HTTP request.
27
 *
28
 * Per the HTTP specification, this interface includes properties for
29
 * each of the following:
30
 *
31
 * - Protocol version
32
 * - HTTP method
33
 * - URI
34
 * - Headers
35
 * - Message body
36
 *
37
 * Additionally, it encapsulates all data as it has arrived to the
38
 * application from the CGI and/or PHP environment, including:
39
 *
40
 * - The values represented in $_SERVER.
41
 * - Any cookies provided (generally via $_COOKIE)
42
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
43
 * - Upload files, if any (as represented by $_FILES)
44
 * - Deserialized body binds (generally from $_POST)
45
 */
46
class IncomingRequest extends Request
47
{
48
    /**
49
     * Enable CSRF flag
50
     *
51
     * Enables a CSRF cookie token to be set.
52
     * Set automatically based on Config setting.
53
     *
54
     * @var bool
55
     *
56
     * @deprecated Not used
57
     */
58
    protected $enableCSRF = false;
59

60
    /**
61
     * The URI for this request.
62
     *
63
     * Note: This WILL NOT match the actual URL in the browser since for
64
     * everything this cares about (and the router, etc) is the portion
65
     * AFTER the script name. So, if hosted in a sub-folder this will
66
     * appear different than actual URL. If you need that use getPath().
67
     *
68
     * @TODO should be protected. Use getUri() instead.
69
     *
70
     * @var URI
71
     */
72
    public $uri;
73

74
    /**
75
     * The detected path (relative to SCRIPT_NAME).
76
     *
77
     * Note: current_url() uses this to build its URI,
78
     * so this becomes the source for the "current URL"
79
     * when working with the share request instance.
80
     *
81
     * @var string|null
82
     */
83
    protected $path;
84

85
    /**
86
     * File collection
87
     *
88
     * @var FileCollection|null
89
     */
90
    protected $files;
91

92
    /**
93
     * Negotiator
94
     *
95
     * @var Negotiate|null
96
     */
97
    protected $negotiator;
98

99
    /**
100
     * The default Locale this request
101
     * should operate under.
102
     *
103
     * @var string
104
     */
105
    protected $defaultLocale;
106

107
    /**
108
     * The current locale of the application.
109
     * Default value is set in Config\App.php
110
     *
111
     * @var string
112
     */
113
    protected $locale;
114

115
    /**
116
     * Stores the valid locale codes.
117
     *
118
     * @var array
119
     */
120
    protected $validLocales = [];
121

122
    /**
123
     * Configuration settings.
124
     *
125
     * @var App
126
     */
127
    public $config;
128

129
    /**
130
     * Holds the old data from a redirect.
131
     *
132
     * @var array
133
     */
134
    protected $oldInput = [];
135

136
    /**
137
     * The user agent this request is from.
138
     *
139
     * @var UserAgent
140
     */
141
    protected $userAgent;
142

143
    /**
144
     * Constructor
145
     *
146
     * @param App         $config
147
     * @param URI         $uri
148
     * @param string|null $body
149
     * @param UserAgent   $userAgent
150
     */
151
    public function __construct($config, ?URI $uri = null, $body = 'php://input', ?UserAgent $userAgent = null)
152
    {
153
        if (empty($uri) || empty($userAgent)) {
1,278✔
154
            throw new InvalidArgumentException('You must supply the parameters: uri, userAgent.');
×
155
        }
156

157
        $this->populateHeaders();
1,278✔
158

159
        if (
160
            $body === 'php://input'
1,278✔
161
            // php://input is not available with enctype="multipart/form-data".
162
            // See https://www.php.net/manual/en/wrappers.php.php#wrappers.php.input
163
            && strpos($this->getHeaderLine('Content-Type'), 'multipart/form-data') === false
1,278✔
164
            && (int) $this->getHeaderLine('Content-Length') <= $this->getPostMaxSize()
1,278✔
165
        ) {
166
            // Get our body from php://input
167
            $body = file_get_contents('php://input');
1,079✔
168
        }
169

170
        $this->config       = $config;
1,278✔
171
        $this->uri          = $uri;
1,278✔
172
        $this->body         = ! empty($body) ? $body : null;
1,278✔
173
        $this->userAgent    = $userAgent;
1,278✔
174
        $this->validLocales = $config->supportedLocales;
1,278✔
175

176
        parent::__construct($config);
1,278✔
177

178
        $this->detectURI($config->uriProtocol, $config->baseURL);
1,278✔
179
        $this->detectLocale($config);
1,278✔
180
    }
181

182
    private function getPostMaxSize(): int
183
    {
184
        $postMaxSize = ini_get('post_max_size');
1,079✔
185

186
        switch (strtoupper(substr($postMaxSize, -1))) {
1,079✔
187
            case 'G':
1,079✔
188
                $postMaxSize = (int) str_replace('G', '', $postMaxSize) * 1024 ** 3;
×
189
                break;
×
190

191
            case 'M':
1,079✔
192
                $postMaxSize = (int) str_replace('M', '', $postMaxSize) * 1024 ** 2;
1,079✔
193
                break;
1,079✔
194

195
            case 'K':
×
196
                $postMaxSize = (int) str_replace('K', '', $postMaxSize) * 1024;
×
197
                break;
×
198

199
            default:
200
                $postMaxSize = (int) $postMaxSize;
×
201
        }
202

203
        return $postMaxSize;
1,079✔
204
    }
205

206
    /**
207
     * Handles setting up the locale, perhaps auto-detecting through
208
     * content negotiation.
209
     *
210
     * @param App $config
211
     */
212
    public function detectLocale($config)
213
    {
214
        $this->locale = $this->defaultLocale = $config->defaultLocale;
1,278✔
215

216
        if (! $config->negotiateLocale) {
1,278✔
217
            return;
1,278✔
218
        }
219

220
        $this->setLocale($this->negotiate('language', $config->supportedLocales));
2✔
221
    }
222

223
    /**
224
     * Sets up our URI object based on the information we have. This is
225
     * either provided by the user in the baseURL Config setting, or
226
     * determined from the environment as needed.
227
     */
228
    protected function detectURI(string $protocol, string $baseURL)
229
    {
230
        // Passing the config is unnecessary but left for legacy purposes
231
        $config          = clone $this->config;
1,234✔
232
        $config->baseURL = $baseURL;
1,234✔
233

234
        $this->setPath($this->detectPath($protocol), $config);
1,234✔
235
    }
236

237
    /**
238
     * Detects the relative path based on
239
     * the URIProtocol Config setting.
240
     */
241
    public function detectPath(string $protocol = ''): string
242
    {
243
        if (empty($protocol)) {
1,234✔
244
            $protocol = 'REQUEST_URI';
5✔
245
        }
246

247
        switch ($protocol) {
248
            case 'REQUEST_URI':
1,234✔
249
                $this->path = $this->parseRequestURI();
1,234✔
250
                break;
1,234✔
251

252
            case 'QUERY_STRING':
4✔
253
                $this->path = $this->parseQueryString();
2✔
254
                break;
2✔
255

256
            case 'PATH_INFO':
2✔
257
            default:
258
                $this->path = $this->fetchGlobal('server', $protocol) ?? $this->parseRequestURI();
2✔
259
                break;
2✔
260
        }
261

262
        return $this->path;
1,234✔
263
    }
264

265
    /**
266
     * Will parse the REQUEST_URI and automatically detect the URI from it,
267
     * fixing the query string if necessary.
268
     *
269
     * @return string The URI it found.
270
     */
271
    protected function parseRequestURI(): string
272
    {
273
        if (! isset($_SERVER['REQUEST_URI'], $_SERVER['SCRIPT_NAME'])) {
1,234✔
274
            return '';
1,142✔
275
        }
276

277
        // parse_url() returns false if no host is present, but the path or query string
278
        // contains a colon followed by a number. So we attach a dummy host since
279
        // REQUEST_URI does not include the host. This allows us to parse out the query string and path.
280
        $parts = parse_url('http://dummy' . $_SERVER['REQUEST_URI']);
127✔
281
        $query = $parts['query'] ?? '';
127✔
282
        $uri   = $parts['path'] ?? '';
127✔
283

284
        // Strip the SCRIPT_NAME path from the URI
285
        if ($uri !== '' && isset($_SERVER['SCRIPT_NAME'][0]) && pathinfo($_SERVER['SCRIPT_NAME'], PATHINFO_EXTENSION) === 'php') {
127✔
286
            // Compare each segment, dropping them until there is no match
287
            $segments = $keep = explode('/', $uri);
88✔
288

289
            foreach (explode('/', $_SERVER['SCRIPT_NAME']) as $i => $segment) {
88✔
290
                // If these segments are not the same then we're done
291
                if (! isset($segments[$i]) || $segment !== $segments[$i]) {
88✔
292
                    break;
78✔
293
                }
294

295
                array_shift($keep);
88✔
296
            }
297

298
            $uri = implode('/', $keep);
88✔
299
        }
300

301
        // This section ensures that even on servers that require the URI to contain the query string (Nginx) a correct
302
        // URI is found, and also fixes the QUERY_STRING getServer var and $_GET array.
303
        if (trim($uri, '/') === '' && strncmp($query, '/', 1) === 0) {
127✔
304
            $query                   = explode('?', $query, 2);
1✔
305
            $uri                     = $query[0];
1✔
306
            $_SERVER['QUERY_STRING'] = $query[1] ?? '';
1✔
307
        } else {
308
            $_SERVER['QUERY_STRING'] = $query;
126✔
309
        }
310

311
        // Update our globals for values likely to been have changed
312
        parse_str($_SERVER['QUERY_STRING'], $_GET);
127✔
313
        $this->populateGlobals('server');
127✔
314
        $this->populateGlobals('get');
127✔
315

316
        $uri = URI::removeDotSegments($uri);
127✔
317

318
        return ($uri === '/' || $uri === '') ? '/' : ltrim($uri, '/');
127✔
319
    }
320

321
    /**
322
     * Parse QUERY_STRING
323
     *
324
     * Will parse QUERY_STRING and automatically detect the URI from it.
325
     */
326
    protected function parseQueryString(): string
327
    {
328
        $uri = $_SERVER['QUERY_STRING'] ?? @getenv('QUERY_STRING');
2✔
329

330
        if (trim($uri, '/') === '') {
2✔
331
            return '';
1✔
332
        }
333

334
        if (strncmp($uri, '/', 1) === 0) {
1✔
335
            $uri                     = explode('?', $uri, 2);
1✔
336
            $_SERVER['QUERY_STRING'] = $uri[1] ?? '';
1✔
337
            $uri                     = $uri[0];
1✔
338
        }
339

340
        // Update our globals for values likely to been have changed
341
        parse_str($_SERVER['QUERY_STRING'], $_GET);
1✔
342
        $this->populateGlobals('server');
1✔
343
        $this->populateGlobals('get');
1✔
344

345
        $uri = URI::removeDotSegments($uri);
1✔
346

347
        return ($uri === '/' || $uri === '') ? '/' : ltrim($uri, '/');
1✔
348
    }
349

350
    /**
351
     * Provides a convenient way to work with the Negotiate class
352
     * for content negotiation.
353
     */
354
    public function negotiate(string $type, array $supported, bool $strictMatch = false): string
355
    {
356
        if ($this->negotiator === null) {
8✔
357
            $this->negotiator = Services::negotiator($this, true);
8✔
358
        }
359

360
        switch (strtolower($type)) {
8✔
361
            case 'media':
8✔
362
                return $this->negotiator->media($supported, $strictMatch);
2✔
363

364
            case 'charset':
6✔
365
                return $this->negotiator->charset($supported);
1✔
366

367
            case 'encoding':
5✔
368
                return $this->negotiator->encoding($supported);
1✔
369

370
            case 'language':
4✔
371
                return $this->negotiator->language($supported);
3✔
372
        }
373

374
        throw HTTPException::forInvalidNegotiationType($type);
1✔
375
    }
376

377
    /**
378
     * Determines if this request was made from the command line (CLI).
379
     */
380
    public function isCLI(): bool
381
    {
382
        return false;
1✔
383
    }
384

385
    /**
386
     * Test to see if a request contains the HTTP_X_REQUESTED_WITH header.
387
     */
388
    public function isAJAX(): bool
389
    {
390
        return $this->hasHeader('X-Requested-With') && strtolower($this->header('X-Requested-With')->getValue()) === 'xmlhttprequest';
53✔
391
    }
392

393
    /**
394
     * Attempts to detect if the current connection is secure through
395
     * a few different methods.
396
     */
397
    public function isSecure(): bool
398
    {
399
        if (! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') {
3✔
400
            return true;
1✔
401
        }
402

403
        if ($this->hasHeader('X-Forwarded-Proto') && $this->header('X-Forwarded-Proto')->getValue() === 'https') {
2✔
404
            return true;
1✔
405
        }
406

407
        return $this->hasHeader('Front-End-Https') && ! empty($this->header('Front-End-Https')->getValue()) && strtolower($this->header('Front-End-Https')->getValue()) !== 'off';
1✔
408
    }
409

410
    /**
411
     * Sets the relative path and updates the URI object.
412
     * Note: Since current_url() accesses the shared request
413
     * instance, this can be used to change the "current URL"
414
     * for testing.
415
     *
416
     * @param string $path   URI path relative to SCRIPT_NAME
417
     * @param App    $config Optional alternate config to use
418
     *
419
     * @return $this
420
     */
421
    public function setPath(string $path, ?App $config = null)
422
    {
423
        $this->path = $path;
1,236✔
424
        $this->uri->setPath($path);
1,236✔
425

426
        $config ??= $this->config;
1,236✔
427

428
        // It's possible the user forgot a trailing slash on their
429
        // baseURL, so let's help them out.
430
        $baseURL = $config->baseURL === '' ? $config->baseURL : rtrim($config->baseURL, '/ ') . '/';
1,236✔
431

432
        // Based on our baseURL provided by the developer
433
        // set our current domain name, scheme
434
        if ($baseURL !== '') {
1,236✔
435
            $this->uri->setScheme(parse_url($baseURL, PHP_URL_SCHEME));
1,230✔
436
            $this->uri->setHost(parse_url($baseURL, PHP_URL_HOST));
1,230✔
437
            $this->uri->setPort(parse_url($baseURL, PHP_URL_PORT));
1,230✔
438

439
            // Ensure we have any query vars
440
            $this->uri->setQuery($_SERVER['QUERY_STRING'] ?? '');
1,230✔
441

442
            // Check if the baseURL scheme needs to be coerced into its secure version
443
            if ($config->forceGlobalSecureRequests && $this->uri->getScheme() === 'http') {
1,230✔
444
                $this->uri->setScheme('https');
1,230✔
445
            }
446
        } elseif (! is_cli()) {
6✔
447
            // @codeCoverageIgnoreStart
448
            exit('You have an empty or invalid base URL. The baseURL value must be set in Config\App.php, or through the .env file.');
449
            // @codeCoverageIgnoreEnd
450
        }
451

452
        return $this;
1,236✔
453
    }
454

455
    /**
456
     * Returns the path relative to SCRIPT_NAME,
457
     * running detection as necessary.
458
     */
459
    public function getPath(): string
460
    {
461
        if ($this->path === null) {
159✔
462
            $this->detectPath($this->config->uriProtocol);
×
463
        }
464

465
        return $this->path;
159✔
466
    }
467

468
    /**
469
     * Sets the locale string for this request.
470
     *
471
     * @return IncomingRequest
472
     */
473
    public function setLocale(string $locale)
474
    {
475
        // If it's not a valid locale, set it
476
        // to the default locale for the site.
477
        if (! in_array($locale, $this->validLocales, true)) {
4✔
478
            $locale = $this->defaultLocale;
1✔
479
        }
480

481
        $this->locale = $locale;
4✔
482
        Locale::setDefault($locale);
4✔
483

484
        return $this;
4✔
485
    }
486

487
    /**
488
     * Gets the current locale, with a fallback to the default
489
     * locale if none is set.
490
     */
491
    public function getLocale(): string
492
    {
493
        return $this->locale ?? $this->defaultLocale;
315✔
494
    }
495

496
    /**
497
     * Returns the default locale as set in Config\App.php
498
     */
499
    public function getDefaultLocale(): string
500
    {
501
        return $this->defaultLocale;
3✔
502
    }
503

504
    /**
505
     * Fetch an item from JSON input stream with fallback to $_REQUEST object. This is the simplest way
506
     * to grab data from the request object and can be used in lieu of the
507
     * other get* methods in most cases.
508
     *
509
     * @param array|string|null $index
510
     * @param int|null          $filter Filter constant
511
     * @param mixed             $flags
512
     *
513
     * @return array|bool|float|int|stdClass|string|null
514
     */
515
    public function getVar($index = null, $filter = null, $flags = null)
516
    {
517
        if (strpos($this->getHeaderLine('Content-Type'), 'application/json') !== false && $this->body !== null) {
18✔
518
            if ($index === null) {
1✔
519
                return $this->getJSON();
1✔
520
            }
521

522
            if (is_array($index)) {
1✔
523
                $output = [];
1✔
524

525
                foreach ($index as $key) {
1✔
526
                    $output[$key] = $this->getJsonVar($key, false, $filter, $flags);
1✔
527
                }
528

529
                return $output;
1✔
530
            }
531

532
            return $this->getJsonVar($index, false, $filter, $flags);
1✔
533
        }
534

535
        return $this->fetchGlobal('request', $index, $filter, $flags);
17✔
536
    }
537

538
    /**
539
     * A convenience method that grabs the raw input stream and decodes
540
     * the JSON into an array.
541
     *
542
     * If $assoc == true, then all objects in the response will be converted
543
     * to associative arrays.
544
     *
545
     * @param bool $assoc   Whether to return objects as associative arrays
546
     * @param int  $depth   How many levels deep to decode
547
     * @param int  $options Bitmask of options
548
     *
549
     * @see http://php.net/manual/en/function.json-decode.php
550
     *
551
     * @return array|bool|float|int|stdClass|null
552
     */
553
    public function getJSON(bool $assoc = false, int $depth = 512, int $options = 0)
554
    {
555
        return json_decode($this->body ?? '', $assoc, $depth, $options);
13✔
556
    }
557

558
    /**
559
     * Get a specific variable from a JSON input stream
560
     *
561
     * @param string         $index  The variable that you want which can use dot syntax for getting specific values.
562
     * @param bool           $assoc  If true, return the result as an associative array.
563
     * @param int|null       $filter Filter Constant
564
     * @param array|int|null $flags  Option
565
     *
566
     * @return array|bool|float|int|stdClass|string|null
567
     */
568
    public function getJsonVar(string $index, bool $assoc = false, ?int $filter = null, $flags = null)
569
    {
570
        helper('array');
5✔
571

572
        $json = $this->getJSON(true);
5✔
573
        if (! is_array($json)) {
5✔
574
            return null;
1✔
575
        }
576
        $data = dot_array_search($index, $json);
4✔
577

578
        if ($data === null) {
4✔
579
            return null;
2✔
580
        }
581

582
        if (! is_array($data)) {
4✔
583
            $filter ??= FILTER_DEFAULT;
3✔
584
            $flags = is_array($flags) ? $flags : (is_numeric($flags) ? (int) $flags : 0);
3✔
585

586
            return filter_var($data, $filter, $flags);
3✔
587
        }
588

589
        if (! $assoc) {
2✔
590
            return json_decode(json_encode($data));
1✔
591
        }
592

593
        return $data;
1✔
594
    }
595

596
    /**
597
     * A convenience method that grabs the raw input stream(send method in PUT, PATCH, DELETE) and decodes
598
     * the String into an array.
599
     *
600
     * @return array
601
     */
602
    public function getRawInput()
603
    {
604
        parse_str($this->body ?? '', $output);
7✔
605

606
        return $output;
7✔
607
    }
608

609
    /**
610
     * Fetch an item from GET data.
611
     *
612
     * @param array|string|null $index  Index for item to fetch from $_GET.
613
     * @param int|null          $filter A filter name to apply.
614
     * @param mixed|null        $flags
615
     *
616
     * @return mixed
617
     */
618
    public function getGet($index = null, $filter = null, $flags = null)
619
    {
620
        return $this->fetchGlobal('get', $index, $filter, $flags);
13✔
621
    }
622

623
    /**
624
     * Fetch an item from POST.
625
     *
626
     * @param array|string|null $index  Index for item to fetch from $_POST.
627
     * @param int|null          $filter A filter name to apply
628
     * @param mixed             $flags
629
     *
630
     * @return mixed
631
     */
632
    public function getPost($index = null, $filter = null, $flags = null)
633
    {
634
        return $this->fetchGlobal('post', $index, $filter, $flags);
69✔
635
    }
636

637
    /**
638
     * Fetch an item from POST data with fallback to GET.
639
     *
640
     * @param array|string|null $index  Index for item to fetch from $_POST or $_GET
641
     * @param int|null          $filter A filter name to apply
642
     * @param mixed             $flags
643
     *
644
     * @return mixed
645
     */
646
    public function getPostGet($index = null, $filter = null, $flags = null)
647
    {
648
        if ($index === null) {
5✔
649
            return array_merge($this->getGet($index, $filter, $flags), $this->getPost($index, $filter, $flags));
3✔
650
        }
651
        // Use $_POST directly here, since filter_has_var only
652
        // checks the initial POST data, not anything that might
653
        // have been added since.
654
        return isset($_POST[$index]) ? $this->getPost($index, $filter, $flags) : (isset($_GET[$index]) ? $this->getGet($index, $filter, $flags) : $this->getPost($index, $filter, $flags));
2✔
655
    }
656

657
    /**
658
     * Fetch an item from GET data with fallback to POST.
659
     *
660
     * @param array|string|null $index  Index for item to be fetched from $_GET or $_POST
661
     * @param int|null          $filter A filter name to apply
662
     * @param mixed             $flags
663
     *
664
     * @return mixed
665
     */
666
    public function getGetPost($index = null, $filter = null, $flags = null)
667
    {
668
        if ($index === null) {
5✔
669
            return array_merge($this->getPost($index, $filter, $flags), $this->getGet($index, $filter, $flags));
3✔
670
        }
671
        // Use $_GET directly here, since filter_has_var only
672
        // checks the initial GET data, not anything that might
673
        // have been added since.
674
        return isset($_GET[$index]) ? $this->getGet($index, $filter, $flags) : (isset($_POST[$index]) ? $this->getPost($index, $filter, $flags) : $this->getGet($index, $filter, $flags));
2✔
675
    }
676

677
    /**
678
     * Fetch an item from the COOKIE array.
679
     *
680
     * @param array|string|null $index  Index for item to be fetched from $_COOKIE
681
     * @param int|null          $filter A filter name to be applied
682
     * @param mixed             $flags
683
     *
684
     * @return mixed
685
     */
686
    public function getCookie($index = null, $filter = null, $flags = null)
687
    {
688
        return $this->fetchGlobal('cookie', $index, $filter, $flags);
96✔
689
    }
690

691
    /**
692
     * Fetch the user agent string
693
     *
694
     * @return UserAgent
695
     */
696
    public function getUserAgent()
697
    {
698
        return $this->userAgent;
1✔
699
    }
700

701
    /**
702
     * Attempts to get old Input data that has been flashed to the session
703
     * with redirect_with_input(). It first checks for the data in the old
704
     * POST data, then the old GET data and finally check for dot arrays
705
     *
706
     * @return array|string|null
707
     */
708
    public function getOldInput(string $key)
709
    {
710
        // If the session hasn't been started, or no
711
        // data was previously saved, we're done.
712
        if (empty($_SESSION['_ci_old_input'])) {
19✔
713
            return null;
6✔
714
        }
715

716
        // Check for the value in the POST array first.
717
        if (isset($_SESSION['_ci_old_input']['post'][$key])) {
15✔
718
            return $_SESSION['_ci_old_input']['post'][$key];
13✔
719
        }
720

721
        // Next check in the GET array.
722
        if (isset($_SESSION['_ci_old_input']['get'][$key])) {
7✔
723
            return $_SESSION['_ci_old_input']['get'][$key];
3✔
724
        }
725

726
        helper('array');
5✔
727

728
        // Check for an array value in POST.
729
        if (isset($_SESSION['_ci_old_input']['post'])) {
5✔
730
            $value = dot_array_search($key, $_SESSION['_ci_old_input']['post']);
5✔
731
            if ($value !== null) {
5✔
732
                return $value;
1✔
733
            }
734
        }
735

736
        // Check for an array value in GET.
737
        if (isset($_SESSION['_ci_old_input']['get'])) {
5✔
738
            $value = dot_array_search($key, $_SESSION['_ci_old_input']['get']);
3✔
739
            if ($value !== null) {
3✔
740
                return $value;
1✔
741
            }
742
        }
743

744
        // requested session key not found
745
        return null;
4✔
746
    }
747

748
    /**
749
     * Returns an array of all files that have been uploaded with this
750
     * request. Each file is represented by an UploadedFile instance.
751
     */
752
    public function getFiles(): array
753
    {
754
        if ($this->files === null) {
1✔
755
            $this->files = new FileCollection();
1✔
756
        }
757

758
        return $this->files->all(); // return all files
1✔
759
    }
760

761
    /**
762
     * Verify if a file exist, by the name of the input field used to upload it, in the collection
763
     * of uploaded files and if is have been uploaded with multiple option.
764
     *
765
     * @return array|null
766
     */
767
    public function getFileMultiple(string $fileID)
768
    {
769
        if ($this->files === null) {
45✔
770
            $this->files = new FileCollection();
45✔
771
        }
772

773
        return $this->files->getFileMultiple($fileID);
45✔
774
    }
775

776
    /**
777
     * Retrieves a single file by the name of the input field used
778
     * to upload it.
779
     *
780
     * @return UploadedFile|null
781
     */
782
    public function getFile(string $fileID)
783
    {
784
        if ($this->files === null) {
41✔
785
            $this->files = new FileCollection();
1✔
786
        }
787

788
        return $this->files->getFile($fileID);
41✔
789
    }
790

791
    /**
792
     * Remove relative directory (../) and multi slashes (///)
793
     *
794
     * Do some final cleaning of the URI and return it, currently only used in static::_parse_request_uri()
795
     *
796
     * @deprecated Use URI::removeDotSegments() directly
797
     */
798
    protected function removeRelativeDirectory(string $uri): string
799
    {
800
        $uri = URI::removeDotSegments($uri);
801

802
        return $uri === '/' ? $uri : ltrim($uri, '/');
803
    }
804
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc