This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Thinktomorrow\Locale\Values; |
||
4 | |||
5 | use Thinktomorrow\Locale\Exceptions\InvalidUrl; |
||
6 | |||
7 | class Url |
||
0 ignored issues
–
show
Coding Style
introduced
by
![]() |
|||
8 | { |
||
9 | private $parsed; |
||
10 | private $root; |
||
11 | |||
12 | private $secure; |
||
13 | private $schemeless = false; |
||
14 | private $absolute = false; |
||
15 | |||
16 | 86 | private function __construct(string $url) |
|
17 | { |
||
18 | 86 | $this->parse($url); |
|
19 | 85 | } |
|
20 | |||
21 | 86 | public static function fromString(string $url) |
|
22 | { |
||
23 | 86 | return new self($url); |
|
24 | } |
||
25 | |||
26 | 10 | public function setCustomRoot(Root $root) |
|
27 | { |
||
28 | 10 | $this->root = $root; |
|
29 | |||
30 | 10 | return $this; |
|
31 | } |
||
32 | |||
33 | 34 | public function secure($secure = true) |
|
34 | { |
||
35 | 34 | $this->secure = (bool) $secure; |
|
36 | |||
37 | 34 | return $this; |
|
38 | } |
||
39 | |||
40 | 51 | public function get() |
|
41 | { |
||
42 | 51 | if ($this->root) { |
|
43 | 10 | if ($this->secure) { |
|
44 | 1 | $this->root->secure($this->secure); |
|
0 ignored issues
–
show
The call to
Root::secure() has too many arguments starting with $this->secure .
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. In this case you can add the ![]() |
|||
45 | } |
||
46 | |||
47 | // Path is reconstructed. Taken care of possible double slashes |
||
48 | 10 | $path = str_replace('//', '/', '/'.trim($this->reassembleWithoutRoot(), '/')); |
|
49 | 10 | if ($path == '/') { |
|
50 | $path = ''; |
||
51 | } |
||
52 | |||
53 | 10 | return $this->root->get().$path; |
|
54 | } |
||
55 | |||
56 | 44 | return $this->reassemble(); |
|
57 | } |
||
58 | |||
59 | 1 | public function isAbsolute(): bool |
|
60 | { |
||
61 | 1 | return $this->absolute; |
|
62 | } |
||
63 | |||
64 | 49 | public function localize(string $localeSegment = null, array $available_locales = []) |
|
65 | { |
||
66 | 49 | $this->parsed['path'] = str_replace( |
|
67 | 49 | '//', |
|
68 | 49 | '/', |
|
69 | 49 | rtrim( |
|
70 | 49 | '/'.trim($localeSegment.$this->delocalizePath($available_locales), '/'), |
|
71 | 49 | '/' |
|
72 | ) |
||
73 | ); |
||
74 | |||
75 | 49 | return $this; |
|
76 | } |
||
77 | |||
78 | 49 | private function delocalizePath(array $available_locales) |
|
79 | { |
||
80 | 49 | if (!isset($this->parsed['path'])) { |
|
81 | 5 | return; |
|
82 | } |
||
83 | |||
84 | 49 | $path_segments = explode('/', trim($this->parsed['path'], '/')); |
|
85 | |||
86 | // Remove the locale segment if present |
||
87 | 49 | if (in_array($path_segments[0], array_keys($available_locales))) { |
|
88 | 5 | unset($path_segments[0]); |
|
89 | } |
||
90 | |||
91 | 49 | return '/'.implode('/', $path_segments); |
|
92 | } |
||
93 | |||
94 | 86 | private function parse(string $url) |
|
95 | { |
||
96 | // Sanitize url input a bit to remove double slashes, but do not remove first slashes |
||
97 | 86 | if ($url == '//') { |
|
98 | 2 | $url = '/'; |
|
99 | } |
||
100 | |||
101 | 86 | $this->parsed = parse_url($url); |
|
102 | |||
103 | 86 | if (false === $this->parsed) { |
|
104 | 2 | throw new InvalidUrl('Failed to parse url. Invalid url ['.$url.'] passed as parameter.'); |
|
105 | } |
||
106 | |||
107 | // If a schemeless url is passed, parse_url will ignore this and strip the first tags |
||
108 | // so we keep a reminder to explicitly reassemble the 'anonymous scheme' manually |
||
109 | 85 | $this->schemeless = (0 === strpos($url, '//') && isset($this->parsed['host'])); |
|
110 | |||
111 | 85 | $this->absolute = (!preg_match('~^(#|//|https?://|mailto:|tel:)~', $url)) |
|
112 | 21 | ? filter_var($url, FILTER_VALIDATE_URL) !== false |
|
113 | 82 | : true; |
|
114 | 85 | } |
|
115 | |||
116 | 1 | public function __toString(): string |
|
117 | { |
||
118 | 1 | return $this->get(); |
|
119 | } |
||
120 | |||
121 | 44 | private function reassemble(): string |
|
122 | { |
||
123 | 44 | $scheme = (isset($this->parsed['scheme'])) |
|
124 | 33 | ? $this->parsed['scheme'].'://' |
|
125 | 44 | : ($this->schemeless ? '//' : ''); |
|
126 | |||
127 | // Convert to secure scheme if needed or vice versa |
||
128 | 44 | if ($scheme == 'http://' && $this->secure) { |
|
129 | 6 | $scheme = 'https://'; |
|
130 | 40 | } elseif ($scheme == 'https://' && false === $this->secure) { |
|
131 | 1 | $scheme = 'http://'; |
|
132 | } |
||
133 | |||
134 | return |
||
135 | $scheme |
||
136 | 44 | .((isset($this->parsed['user'])) ? $this->parsed['user'].((isset($this->parsed['pass'])) ? ':'.$this->parsed['pass'] : '').'@' : '') |
|
137 | 44 | .((isset($this->parsed['host'])) ? $this->parsed['host'] : '') |
|
138 | 44 | .((isset($this->parsed['port'])) ? ':'.$this->parsed['port'] : '') |
|
139 | 44 | .((isset($this->parsed['path'])) ? $this->parsed['path'] : '') |
|
140 | 44 | .((isset($this->parsed['query'])) ? '?'.$this->parsed['query'] : '') |
|
141 | 44 | .((isset($this->parsed['fragment'])) ? '#'.$this->parsed['fragment'] : ''); |
|
142 | } |
||
143 | |||
144 | /** |
||
145 | * Construct a full url with the parsed url elements |
||
146 | * resulted from a parse_url() function call. |
||
147 | * |
||
148 | * @return string |
||
149 | */ |
||
150 | 10 | private function reassembleWithoutRoot() |
|
151 | { |
||
152 | 10 | if (!$this->root) { |
|
153 | return $this->reassemble(); |
||
154 | } |
||
155 | |||
156 | /** |
||
157 | * In some rare conditions the path in interpreted as the host when there is no domain.tld format given. |
||
158 | * This is still considered a valid url, be it with only a tld as indication. |
||
159 | */ |
||
160 | 10 | $path = (isset($this->parsed['path']) && $this->parsed['path'] != $this->root->host()) |
|
161 | 10 | ? $this->parsed['path'] |
|
162 | 10 | : ''; |
|
163 | |||
164 | return $path |
||
165 | 10 | .((isset($this->parsed['query'])) ? '?'.$this->parsed['query'] : '') |
|
166 | 10 | .((isset($this->parsed['fragment'])) ? '#'.$this->parsed['fragment'] : ''); |
|
167 | } |
||
168 | } |
||
169 |