Passed
Push — main ( 2519a4...62a0e8 )
by Thierry
03:58
created

UriDetector::setQuery()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
1
<?php
2
3
/**
4
 * UriDetector.php - Jaxon request UriDetector detector
5
 *
6
 * Detect and parse the URI of the Jaxon request being processed.
7
 *
8
 * @package jaxon-core
9
 * @author Thierry Feuzeu <[email protected]>
10
 * @copyright 2022 Thierry Feuzeu <[email protected]>
11
 * @license https://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License
12
 * @link https://github.com/jaxon-php/jaxon-core
13
 */
14
15
namespace Jaxon\Utils\Http;
16
17
use function strpos;
18
use function explode;
19
use function implode;
20
use function strtolower;
21
use function strlen;
22
use function basename;
23
use function parse_url;
24
use function str_replace;
25
26
class UriDetector
27
{
28
    /**
29
     * The URL components
30
     * 
31
     * @var array
32
     */
33
    protected $aUrl;
34
35
    /**
36
     * @param array $server The HTTP request server data
37
     *
38
     * @return void
39
     */
40
    private function setScheme(array $server)
41
    {
42
        if(isset($this->aUrl['scheme']))
43
        {
44
            return;
45
        }
46
        if(isset($server['HTTP_SCHEME']))
47
        {
48
            $this->aUrl['scheme'] = $server['HTTP_SCHEME'];
49
            return;
50
        }
51
        $this->aUrl['scheme'] = (isset($server['HTTPS']) && strtolower($server['HTTPS']) != 'off') ? 'https' : 'http';
52
    }
53
54
    /**
55
     * Get the URL from the $server var
56
     *
57
     * @param array $server The HTTP request server data
58
     * @param string $sKey The key in the $server array
59
     *
60
     * @return void
61
     */
62
    private function setHostFromServer(array $server, string $sKey)
63
    {
64
        if(isset($this->aUrl['host']) && isset($server[$sKey]))
65
        {
66
            return;
67
        }
68
        if(strpos($server[$sKey], ':') === false)
69
        {
70
            $this->aUrl['host'] = $server[$sKey];
71
            return;
72
        }
73
        list($this->aUrl['host'], $this->aUrl['port']) = explode(':', $server[$sKey]);
74
    }
75
76
    /**
77
     * @param array $server The HTTP request server data
78
     *
79
     * @return void
80
     * @throws UriException
81
     */
82
    private function setHost(array $server)
83
    {
84
        $this->setHostFromServer($server, 'HTTP_X_FORWARDED_HOST');
85
        $this->setHostFromServer($server, 'HTTP_HOST');
86
        $this->setHostFromServer($server, 'SERVER_NAME');
87
        if(empty($this->aUrl['host']))
88
        {
89
            throw new UriException();
90
        }
91
        if(empty($this->aUrl['port']) && isset($server['SERVER_PORT']))
92
        {
93
            $this->aUrl['port'] = $server['SERVER_PORT'];
94
        }
95
    }
96
97
    /**
98
     * @param array $server The HTTP request server data
99
     *
100
     * @return void
101
     */
102
    private function setPath(array $server)
103
    {
104
        if(isset($this->aUrl['path']) && strlen(basename($this->aUrl['path'])) === 0)
105
        {
106
            unset($this->aUrl['path']);
107
        }
108
        if(isset($this->aUrl['path']))
109
        {
110
            return;
111
        }
112
        $aPath = parse_url($server['PATH_INFO'] ?? $server['PHP_SELF']);
113
        if(isset($aPath['path']))
114
        {
115
            $this->aUrl['path'] = str_replace(['"', "'", '<', '>'], ['%22', '%27', '%3C', '%3E'], $aPath['path']);
116
        }
117
    }
118
119
    /**
120
     * @return string
121
     */
122
    private function getUser(): string
123
    {
124
        if(empty($this->aUrl['user']))
125
        {
126
            return '';
127
        }
128
        $sUrl = $this->aUrl['user'];
129
        if(isset($this->aUrl['pass']))
130
        {
131
            $sUrl .= ':' . $this->aUrl['pass'];
132
        }
133
        return $sUrl . '@';
134
    }
135
136
    /**
137
     * @return string
138
     */
139
    private function getPort(): string
140
    {
141
        if(isset($this->aUrl['port']) &&
142
            (($this->aUrl['scheme'] === 'http' && $this->aUrl['port'] != 80) ||
143
                ($this->aUrl['scheme'] === 'https' && $this->aUrl['port'] != 443)))
144
        {
145
            return ':' . $this->aUrl['port'];
146
        }
147
        return '';
148
    }
149
150
    /**
151
     * @param array $server The HTTP request server data
152
     *
153
     * @return void
154
     */
155
    private function setQuery(array $server)
156
    {
157
        if(empty($this->aUrl['query']))
158
        {
159
            $this->aUrl['query'] = empty($server['QUERY_STRING']) ? '' : $server['QUERY_STRING'];
160
        }
161
    }
162
163
    /**
164
     * @return string
165
     */
166
    private function getQuery(): string
167
    {
168
        if(empty($this->aUrl['query']))
169
        {
170
            return '';
171
        }
172
        $aQueries = explode("&", $this->aUrl['query']);
173
        foreach($aQueries as $sKey => $sQuery)
174
        {
175
            if(substr($sQuery, 0, 11) === 'jxnGenerate')
176
            {
177
                unset($aQueries[$sKey]);
178
            }
179
        }
180
        return '?' . implode("&", $aQueries);
181
    }
182
183
    /**
184
     * Detect the UriDetector of the current request
185
     * 
186
     * @param array $server The server data in the HTTP request
187
     *
188
     * @return string
189
     * @throws UriException
190
     */
191
    public function detect(array $server): string
192
    {
193
        $this->aUrl = [];
194
        // Try to get the request URL
195
        if(isset($server['REQUEST_URI']))
196
        {
197
            $sUri = str_replace(['"', "'", '<', '>'], ['%22', '%27', '%3C', '%3E'], $server['REQUEST_URI']);
198
            $this->aUrl = parse_url($sUri);
199
        }
200
201
        // Fill in the empty values
202
        $this->setScheme($server);
203
        $this->setHost($server);
204
        $this->setPath($server);
205
        $this->setQuery($server);
206
207
        // Build the URL: Start with scheme, user and pass
208
        return $this->aUrl['scheme'] . '://' . $this->getUser() . $this->aUrl['host'] .
209
            $this->getPort() . $this->aUrl['path'] . $this->getQuery();
210
    }
211
}
212