Passed
Push — main ( 77b9e9...aee045 )
by Thierry
02:31
created

URI::setScheme()   A

Complexity

Conditions 5
Paths 6

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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