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.
![]() |
|||
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) |
|
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) |
|
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': |
||
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': |
||
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.