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 | * @package Fuel\Common |
||
4 | * @version 2.0 |
||
5 | * @author Fuel Development Team |
||
6 | * @license MIT License |
||
7 | * @copyright 2010 - 2015 Fuel Development Team |
||
8 | * @link http://fuelphp.com |
||
9 | */ |
||
10 | |||
11 | namespace Fuel\Common; |
||
12 | |||
13 | /** |
||
14 | * String handling with encoding support |
||
15 | * |
||
16 | * PHP needs to be compiled with --enable-mbstring |
||
17 | * or a fallback without encoding support is used |
||
18 | */ |
||
19 | class Str |
||
20 | { |
||
21 | protected $encoding = 'UTF-8'; |
||
22 | |||
23 | /** |
||
24 | * Truncates a string to the given length. It will optionally preserve |
||
25 | * HTML tags if $is_html is set to true. |
||
26 | * |
||
27 | * @param string $string the string to truncate |
||
28 | * @param int $limit the number of characters to truncate too |
||
29 | * @param string $continuation the string to use to denote it was truncated |
||
30 | * @param bool $is_html whether the string has HTML |
||
31 | * @return string the truncated string |
||
32 | */ |
||
33 | public function truncate($string, $limit, $continuation = '...', $is_html = false) |
||
34 | { |
||
35 | $offset = 0; |
||
36 | $tags = array(); |
||
37 | if ($is_html) |
||
38 | { |
||
39 | // Handle special characters. |
||
40 | preg_match_all('/&[a-z]+;/i', strip_tags($string), $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); |
||
41 | foreach ($matches as $match) |
||
0 ignored issues
–
show
|
|||
42 | { |
||
43 | if ($match[0][1] >= $limit) |
||
44 | { |
||
45 | break; |
||
46 | } |
||
47 | $limit += ($this->length($match[0][0]) - 1); |
||
48 | } |
||
49 | |||
50 | // Handle all the html tags. |
||
51 | preg_match_all('/<[^>]+>([^<]*)/', $string, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); |
||
52 | foreach ($matches as $match) |
||
0 ignored issues
–
show
The expression
$matches of type null|array<integer,array<integer,string>> is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
Loading history...
|
|||
53 | { |
||
54 | if($match[0][1] - $offset >= $limit) |
||
55 | { |
||
56 | break; |
||
57 | } |
||
58 | $tag = $this->sub(strtok($match[0][0], " \t\n\r\0\x0B>"), 1); |
||
59 | if($tag[0] != '/') |
||
60 | { |
||
61 | $tags[] = $tag; |
||
62 | } |
||
63 | elseif (end($tags) == $this->sub($tag, 1)) |
||
64 | { |
||
65 | array_pop($tags); |
||
66 | } |
||
67 | $offset += $match[1][1] - $match[0][1]; |
||
68 | } |
||
69 | } |
||
70 | $new_string = $this->sub($string, 0, $limit = min($this->length($string), $limit + $offset)); |
||
71 | $new_string .= ($this->length($string) > $limit ? $continuation : ''); |
||
72 | $new_string .= (count($tags = array_reverse($tags)) ? '</'.implode('></',$tags).'>' : ''); |
||
73 | return $new_string; |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * Add's _1 to a string or increment the ending number to allow _2, _3, etc |
||
78 | * |
||
79 | * @param string $str required |
||
80 | * @return string |
||
81 | */ |
||
82 | public function increment($str, $first = 1, $separator = '_') |
||
83 | { |
||
84 | preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match); |
||
85 | |||
86 | return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first; |
||
87 | } |
||
88 | |||
89 | /** |
||
90 | * Checks wether a string has a precific beginning. |
||
91 | * |
||
92 | * @param string $str string to check |
||
93 | * @param string $start beginning to check for |
||
94 | * @param boolean $ignore_case wether to ignore the case |
||
95 | * @return boolean wether a string starts with a specified beginning |
||
96 | */ |
||
97 | public function startsWith($str, $start, $ignore_case = false) |
||
98 | { |
||
99 | return (bool) preg_match('/^'.preg_quote($start, '/').'/m'.($ignore_case ? 'i' : ''), $str); |
||
100 | } |
||
101 | |||
102 | /** |
||
103 | * Checks wether a string has a precific ending. |
||
104 | * |
||
105 | * @param string $str string to check |
||
106 | * @param string $end ending to check for |
||
107 | * @param boolean $ignore_case wether to ignore the case |
||
108 | * @return boolean wether a string ends with a specified ending |
||
109 | */ |
||
110 | public function endsWith($str, $end, $ignore_case = false) |
||
111 | { |
||
112 | return (bool) preg_match('/'.preg_quote($end, '/').'$/m'.($ignore_case ? 'i' : ''), $str); |
||
113 | } |
||
114 | |||
115 | /** |
||
116 | * substr |
||
117 | * |
||
118 | * @param string $str required |
||
119 | * @param int $start required |
||
120 | * @param int|null $length |
||
121 | * @param string $encoding default UTF-8 |
||
122 | * @return string |
||
123 | */ |
||
124 | public function sub($str, $start, $length = null, $encoding = null) |
||
125 | { |
||
126 | $encoding or $encoding = $this->encoding; |
||
127 | |||
128 | // substr functions don't parse null correctly |
||
129 | $length = is_null($length) ? (function_exists('mb_substr') ? mb_strlen($str, $encoding) : strlen($str)) - $start : $length; |
||
130 | |||
131 | return function_exists('mb_substr') |
||
132 | ? mb_substr($str, $start, $length, $encoding) |
||
133 | : substr($str, $start, $length); |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * strlen |
||
138 | * |
||
139 | * @param string $str required |
||
140 | * @param string $encoding default UTF-8 |
||
141 | * @return int |
||
142 | */ |
||
143 | public function length($str, $encoding = null) |
||
144 | { |
||
145 | $encoding or $encoding = $this->encoding; |
||
146 | |||
147 | return function_exists('mb_strlen') |
||
148 | ? mb_strlen($str, $encoding) |
||
149 | : strlen($str); |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * lower |
||
154 | * |
||
155 | * @param string $str required |
||
156 | * @param string $encoding default UTF-8 |
||
157 | * @return string |
||
158 | */ |
||
159 | public function lower($str, $encoding = null) |
||
160 | { |
||
161 | $encoding or $encoding = $this->encoding; |
||
162 | |||
163 | return function_exists('mb_strtolower') |
||
164 | ? mb_strtolower($str, $encoding) |
||
165 | : strtolower($str); |
||
166 | } |
||
167 | |||
168 | /** |
||
169 | * upper |
||
170 | * |
||
171 | * @param string $str required |
||
172 | * @param string $encoding default UTF-8 |
||
173 | * @return string |
||
174 | */ |
||
175 | public function upper($str, $encoding = null) |
||
176 | { |
||
177 | $encoding or $encoding = $this->encoding; |
||
178 | |||
179 | return function_exists('mb_strtoupper') |
||
180 | ? mb_strtoupper($str, $encoding) |
||
181 | : strtoupper($str); |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * lcfirst |
||
186 | * |
||
187 | * Does not strtoupper first |
||
188 | * |
||
189 | * @param string $str required |
||
190 | * @param string $encoding default UTF-8 |
||
191 | * @return string |
||
192 | */ |
||
193 | View Code Duplication | public function lcfirst($str, $encoding = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
194 | { |
||
195 | $encoding or $encoding = $this->encoding; |
||
196 | |||
197 | return function_exists('mb_strtolower') |
||
198 | ? mb_strtolower(mb_substr($str, 0, 1, $encoding), $encoding). |
||
199 | mb_substr($str, 1, mb_strlen($str, $encoding), $encoding) |
||
200 | : lcfirst($str); |
||
201 | } |
||
202 | |||
203 | /** |
||
204 | * ucfirst |
||
205 | * |
||
206 | * Does not strtolower first |
||
207 | * |
||
208 | * @param string $str required |
||
209 | * @param string $encoding default UTF-8 |
||
210 | * @return string |
||
211 | */ |
||
212 | View Code Duplication | public function ucfirst($str, $encoding = null) |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository.
Loading history...
|
|||
213 | { |
||
214 | $encoding or $encoding = $this->encoding; |
||
215 | |||
216 | return function_exists('mb_strtoupper') |
||
217 | ? mb_strtoupper(mb_substr($str, 0, 1, $encoding), $encoding). |
||
218 | mb_substr($str, 1, mb_strlen($str, $encoding), $encoding) |
||
219 | : ucfirst($str); |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * ucwords |
||
224 | * |
||
225 | * First strtolower then ucwords |
||
226 | * |
||
227 | * ucwords normally doesn't strtolower first |
||
228 | * but MB_CASE_TITLE does, so ucwords now too |
||
229 | * |
||
230 | * @param string $str required |
||
231 | * @param string $encoding default UTF-8 |
||
232 | * @return string |
||
233 | */ |
||
234 | public function ucwords($str, $encoding = null) |
||
235 | { |
||
236 | $encoding or $encoding = $this->encoding; |
||
237 | |||
238 | return function_exists('mb_convert_case') |
||
239 | ? mb_convert_case($str, MB_CASE_TITLE, $encoding) |
||
240 | : ucwords(strtolower($str)); |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Creates a random string of characters |
||
245 | * |
||
246 | * @param string the type of string |
||
247 | * @param int the number of characters |
||
248 | * @return string the random string |
||
249 | */ |
||
250 | public function random($type = 'alnum', $length = 16) |
||
251 | { |
||
252 | switch($type) |
||
253 | { |
||
254 | case 'basic': |
||
255 | $result = mt_rand(); |
||
256 | break; |
||
257 | |||
258 | case 'unique': |
||
259 | $result = md5(uniqid(mt_rand())); |
||
260 | break; |
||
261 | |||
262 | case 'sha1' : |
||
263 | $result = sha1(uniqid(mt_rand(), true)); |
||
264 | break; |
||
265 | |||
266 | default: |
||
267 | case 'alnum': |
||
0 ignored issues
–
show
case 'alnum': does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last
Loading history...
|
|||
268 | case 'numeric': |
||
269 | case 'nozero': |
||
270 | case 'alpha': |
||
271 | case 'distinct': |
||
272 | case 'hexdec': |
||
273 | switch ($type) |
||
274 | { |
||
275 | case 'alpha': |
||
276 | $pool = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
||
277 | break; |
||
278 | |||
279 | case 'numeric': |
||
280 | $pool = '0123456789'; |
||
281 | break; |
||
282 | |||
283 | case 'nozero': |
||
284 | $pool = '123456789'; |
||
285 | break; |
||
286 | |||
287 | case 'distinct': |
||
288 | $pool = '2345679ACDEFHJKLMNPRSTUVWXYZ'; |
||
289 | break; |
||
290 | |||
291 | case 'hexdec': |
||
292 | $pool = '0123456789abcdef'; |
||
293 | break; |
||
294 | |||
295 | default: |
||
296 | case 'alnum': |
||
0 ignored issues
–
show
case 'alnum': $pool ...FGHIJKLMNOPQRSTUVWXYZ'; does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last
Loading history...
|
|||
297 | $pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; |
||
298 | } |
||
299 | |||
300 | $result = ''; |
||
301 | for ($i=0; $i < $length; $i++) |
||
302 | { |
||
303 | $result .= substr($pool, mt_rand(0, strlen($pool) -1), 1); |
||
304 | } |
||
305 | } |
||
306 | |||
307 | return $result; |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Returns a closure that will alternate between the args which to return. |
||
312 | * If you call the closure with false as the arg it will return the value without |
||
313 | * alternating the next time. |
||
314 | * |
||
315 | * @return \Closure |
||
316 | */ |
||
317 | public function alternator() |
||
318 | { |
||
319 | // the args are the values to alternate |
||
320 | $args = func_get_args(); |
||
321 | |||
322 | return function ($next = true) use ($args) |
||
323 | { |
||
324 | static $i = 0; |
||
325 | return $args[($next ? $i++ : $i) % count($args)]; |
||
326 | }; |
||
327 | } |
||
328 | |||
329 | /** |
||
330 | * Parse the params from a string using strtr() |
||
331 | * |
||
332 | * @param string string to parse |
||
333 | * @param array params to str_replace |
||
334 | * @return string |
||
335 | */ |
||
336 | public function tr($string, $array = array()) |
||
337 | { |
||
338 | if (is_string($string)) |
||
339 | { |
||
340 | $tr_arr = array(); |
||
341 | |||
342 | foreach ($array as $from => $to) |
||
343 | { |
||
344 | substr($from, 0, 1) !== ':' and $from = ':'.$from; |
||
345 | $tr_arr[$from] = $to; |
||
346 | } |
||
347 | unset($array); |
||
348 | |||
349 | return strtr($string, $tr_arr); |
||
350 | } |
||
351 | else |
||
352 | { |
||
353 | return $string; |
||
354 | } |
||
355 | } |
||
356 | |||
357 | /** |
||
358 | * Check if a string is json encoded |
||
359 | * |
||
360 | * @param string $string string to check |
||
361 | * @return bool |
||
362 | */ |
||
363 | public function is_json($string) |
||
364 | { |
||
365 | json_decode($string); |
||
366 | return json_last_error() === JSON_ERROR_NONE; |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Check if a string is a valid XML |
||
371 | * |
||
372 | * @param string $string string to check |
||
373 | * @return bool |
||
374 | */ |
||
375 | public function is_xml($string) |
||
376 | { |
||
377 | $internal_errors = libxml_use_internal_errors(); |
||
378 | libxml_use_internal_errors(true); |
||
379 | $result = simplexml_load_string($string) !== false; |
||
380 | libxml_use_internal_errors($internal_errors); |
||
381 | |||
382 | return $result; |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * Check if a string is serialized |
||
387 | * |
||
388 | * @param string $string string to check |
||
389 | * @return bool |
||
390 | */ |
||
391 | public function is_serialized($string) |
||
392 | { |
||
393 | $array = @unserialize($string); |
||
394 | return ! ($array === false and $string !== 'b:0;'); |
||
395 | } |
||
396 | |||
397 | /** |
||
398 | * Check if a string is html |
||
399 | * |
||
400 | * @param string $string string to check |
||
401 | * @return bool |
||
402 | */ |
||
403 | public function is_html($string) |
||
404 | { |
||
405 | return strlen(strip_tags($string)) < strlen($string); |
||
406 | } |
||
407 | } |
||
408 |
There are different options of fixing this problem.
If you want to be on the safe side, you can add an additional type-check:
If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:
Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.