Issues (847)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

inc/Utf8/PhpString.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

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 dokuwiki\Utf8;
4
5
/**
6
 * UTF-8 aware equivalents to PHP's string functions
7
 */
8
class PhpString
9
{
10
11
    /**
12
     * A locale independent basename() implementation
13
     *
14
     * works around a bug in PHP's basename() implementation
15
     *
16
     * @param string $path A path
17
     * @param string $suffix If the name component ends in suffix this will also be cut off
18
     * @return string
19
     * @link   https://bugs.php.net/bug.php?id=37738
20
     *
21
     * @see basename()
22
     */
23
    public static function basename($path, $suffix = '')
24
    {
25
        $path = trim($path, '\\/');
26
        $rpos = max(strrpos($path, '/'), strrpos($path, '\\'));
27
        if ($rpos) {
28
            $path = substr($path, $rpos + 1);
29
        }
30
31
        $suflen = strlen($suffix);
32
        if ($suflen && (substr($path, -$suflen) === $suffix)) {
33
            $path = substr($path, 0, -$suflen);
34
        }
35
36
        return $path;
37
    }
38
39
    /**
40
     * Unicode aware replacement for strlen()
41
     *
42
     * utf8_decode() converts characters that are not in ISO-8859-1
43
     * to '?', which, for the purpose of counting, is alright - It's
44
     * even faster than mb_strlen.
45
     *
46
     * @param string $string
47
     * @return int
48
     * @see    utf8_decode()
49
     *
50
     * @author <chernyshevsky at hotmail dot com>
51
     * @see    strlen()
52
     */
53
    public static function strlen($string)
54
    {
55
        if (function_exists('utf8_decode')) {
56
            return strlen(utf8_decode($string));
57
        }
58
59
        if (UTF8_MBSTRING) {
60
            return mb_strlen($string, 'UTF-8');
61
        }
62
63
        if (function_exists('iconv_strlen')) {
64
            return iconv_strlen($string, 'UTF-8');
65
        }
66
67
        return strlen($string);
68
    }
69
70
    /**
71
     * UTF-8 aware alternative to substr
72
     *
73
     * Return part of a string given character offset (and optionally length)
74
     *
75
     * @param string $str
76
     * @param int $offset number of UTF-8 characters offset (from left)
77
     * @param int $length (optional) length in UTF-8 characters from offset
78
     * @return string
79
     * @author Harry Fuecks <[email protected]>
80
     * @author Chris Smith <[email protected]>
81
     *
82
     */
83
    public static function substr($str, $offset, $length = null)
84
    {
85
        if (UTF8_MBSTRING) {
86
            if ($length === null) {
87
                return mb_substr($str, $offset);
88
            }
89
90
            return mb_substr($str, $offset, $length);
91
        }
92
93
        /*
94
         * Notes:
95
         *
96
         * no mb string support, so we'll use pcre regex's with 'u' flag
97
         * pcre only supports repetitions of less than 65536, in order to accept up to MAXINT values for
98
         * offset and length, we'll repeat a group of 65535 characters when needed (ok, up to MAXINT-65536)
99
         *
100
         * substr documentation states false can be returned in some cases (e.g. offset > string length)
101
         * mb_substr never returns false, it will return an empty string instead.
102
         *
103
         * calculating the number of characters in the string is a relatively expensive operation, so
104
         * we only carry it out when necessary. It isn't necessary for +ve offsets and no specified length
105
         */
106
107
        // cast parameters to appropriate types to avoid multiple notices/warnings
108
        $str = (string)$str;                          // generates E_NOTICE for PHP4 objects, but not PHP5 objects
109
        $offset = (int)$offset;
110
        if ($length !== null) $length = (int)$length;
111
112
        // handle trivial cases
113
        if ($length === 0) return '';
114
        if ($offset < 0 && $length < 0 && $length < $offset) return '';
115
116
        $offset_pattern = '';
117
        $length_pattern = '';
118
119
        // normalise -ve offsets (we could use a tail anchored pattern, but they are horribly slow!)
120
        if ($offset < 0) {
121
            $strlen = self::strlen($str);        // see notes
122
            $offset = $strlen + $offset;
123
            if ($offset < 0) $offset = 0;
124
        }
125
126
        // establish a pattern for offset, a non-captured group equal in length to offset
127
        if ($offset > 0) {
128
            $Ox = (int)($offset / 65535);
129
            $Oy = $offset % 65535;
130
131
            if ($Ox) $offset_pattern = '(?:.{65535}){' . $Ox . '}';
132
            $offset_pattern = '^(?:' . $offset_pattern . '.{' . $Oy . '})';
133
        } else {
134
            $offset_pattern = '^';                      // offset == 0; just anchor the pattern
135
        }
136
137
        // establish a pattern for length
138
        if ($length === null) {
139
            $length_pattern = '(.*)$';                  // the rest of the string
140
        } else {
141
142
            if (!isset($strlen)) $strlen = self::strlen($str);    // see notes
143
            if ($offset > $strlen) return '';           // another trivial case
144
145
            if ($length > 0) {
146
147
                // reduce any length that would go past the end of the string
148
                $length = min($strlen - $offset, $length);
149
150
                $Lx = (int)($length / 65535);
151
                $Ly = $length % 65535;
152
153
                // +ve length requires ... a captured group of length characters
154
                if ($Lx) $length_pattern = '(?:.{65535}){' . $Lx . '}';
155
                $length_pattern = '(' . $length_pattern . '.{' . $Ly . '})';
156
157
            } else if ($length < 0) {
158
159
                if ($length < ($offset - $strlen)) return '';
160
161
                $Lx = (int)((-$length) / 65535);
162
                $Ly = (-$length) % 65535;
163
164
                // -ve length requires ... capture everything except a group of -length characters
165
                //                         anchored at the tail-end of the string
166
                if ($Lx) $length_pattern = '(?:.{65535}){' . $Lx . '}';
167
                $length_pattern = '(.*)(?:' . $length_pattern . '.{' . $Ly . '})$';
168
            }
169
        }
170
171
        if (!preg_match('#' . $offset_pattern . $length_pattern . '#us', $str, $match)) return '';
172
        return $match[1];
173
    }
174
175
    // phpcs:disable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
176
    /**
177
     * Unicode aware replacement for substr_replace()
178
     *
179
     * @param string $string input string
180
     * @param string $replacement the replacement
181
     * @param int $start the replacing will begin at the start'th offset into string.
182
     * @param int $length If given and is positive, it represents the length of the portion of string which is
183
     *                            to be replaced. If length is zero then this function will have the effect of inserting
184
     *                            replacement into string at the given start offset.
185
     * @return string
186
     * @see    substr_replace()
187
     *
188
     * @author Andreas Gohr <[email protected]>
189
     */
190
    public static function substr_replace($string, $replacement, $start, $length = 0)
191
    {
192
        $ret = '';
193
        if ($start > 0) $ret .= self::substr($string, 0, $start);
194
        $ret .= $replacement;
195
        $ret .= self::substr($string, $start + $length);
196
        return $ret;
197
    }
198
    // phpcs:enable PSR1.Methods.CamelCapsMethodName.NotCamelCaps
199
200
    /**
201
     * Unicode aware replacement for ltrim()
202
     *
203
     * @param string $str
204
     * @param string $charlist
205
     * @return string
206
     * @see    ltrim()
207
     *
208
     * @author Andreas Gohr <[email protected]>
209
     */
210
    public static function ltrim($str, $charlist = '')
211
    {
212
        if ($charlist === '') return ltrim($str);
213
214
        //quote charlist for use in a characterclass
215
        $charlist = preg_replace('!([\\\\\\-\\]\\[/])!', '\\\${1}', $charlist);
216
217
        return preg_replace('/^[' . $charlist . ']+/u', '', $str);
218
    }
219
220
    /**
221
     * Unicode aware replacement for rtrim()
222
     *
223
     * @param string $str
224
     * @param string $charlist
225
     * @return string
226
     * @see    rtrim()
227
     *
228
     * @author Andreas Gohr <[email protected]>
229
     */
230
    public static function rtrim($str, $charlist = '')
231
    {
232
        if ($charlist === '') return rtrim($str);
233
234
        //quote charlist for use in a characterclass
235
        $charlist = preg_replace('!([\\\\\\-\\]\\[/])!', '\\\${1}', $charlist);
236
237
        return preg_replace('/[' . $charlist . ']+$/u', '', $str);
238
    }
239
240
    /**
241
     * Unicode aware replacement for trim()
242
     *
243
     * @param string $str
244
     * @param string $charlist
245
     * @return string
246
     * @see    trim()
247
     *
248
     * @author Andreas Gohr <[email protected]>
249
     */
250
    public static function trim($str, $charlist = '')
251
    {
252
        if ($charlist === '') return trim($str);
253
254
        return self::ltrim(self::rtrim($str, $charlist), $charlist);
255
    }
256
257
    /**
258
     * This is a unicode aware replacement for strtolower()
259
     *
260
     * Uses mb_string extension if available
261
     *
262
     * @param string $string
263
     * @return string
264
     * @see    \dokuwiki\Utf8\PhpString::strtoupper()
265
     *
266
     * @author Leo Feyer <[email protected]>
267
     * @see    strtolower()
268
     */
269
    public static function strtolower($string)
270
    {
271
        if (UTF8_MBSTRING) {
272
            if (class_exists('Normalizer', $autoload = false)) {
273
                return \Normalizer::normalize(mb_strtolower($string, 'utf-8'));
274
            }
275
            return (mb_strtolower($string, 'utf-8'));
276
        }
277
        return strtr($string, Table::upperCaseToLowerCase());
278
    }
279
280
    /**
281
     * This is a unicode aware replacement for strtoupper()
282
     *
283
     * Uses mb_string extension if available
284
     *
285
     * @param string $string
286
     * @return string
287
     * @see    \dokuwiki\Utf8\PhpString::strtoupper()
288
     *
289
     * @author Leo Feyer <[email protected]>
290
     * @see    strtoupper()
291
     */
292
    public static function strtoupper($string)
293
    {
294
        if (UTF8_MBSTRING) return mb_strtoupper($string, 'utf-8');
295
296
        return strtr($string, Table::lowerCaseToUpperCase());
0 ignored issues
show
It seems like \dokuwiki\Utf8\Table::lowerCaseToUpperCase() targeting dokuwiki\Utf8\Table::lowerCaseToUpperCase() can also be of type null; however, strtr() does only seem to accept array, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
297
    }
298
299
300
    /**
301
     * UTF-8 aware alternative to ucfirst
302
     * Make a string's first character uppercase
303
     *
304
     * @param string $str
305
     * @return string with first character as upper case (if applicable)
306
     * @author Harry Fuecks
307
     *
308
     */
309
    public static function ucfirst($str)
310
    {
311
        switch (self::strlen($str)) {
312
            case 0:
313
                return '';
314
            case 1:
315
                return self::strtoupper($str);
316
            default:
317
                preg_match('/^(.{1})(.*)$/us', $str, $matches);
318
                return self::strtoupper($matches[1]) . $matches[2];
319
        }
320
    }
321
322
    /**
323
     * UTF-8 aware alternative to ucwords
324
     * Uppercase the first character of each word in a string
325
     *
326
     * @param string $str
327
     * @return string with first char of each word uppercase
328
     * @author Harry Fuecks
329
     * @see http://php.net/ucwords
330
     *
331
     */
332
    public static function ucwords($str)
333
    {
334
        // Note: [\x0c\x09\x0b\x0a\x0d\x20] matches;
335
        // form feeds, horizontal tabs, vertical tabs, linefeeds and carriage returns
336
        // This corresponds to the definition of a "word" defined at http://php.net/ucwords
337
        $pattern = '/(^|([\x0c\x09\x0b\x0a\x0d\x20]+))([^\x0c\x09\x0b\x0a\x0d\x20]{1})[^\x0c\x09\x0b\x0a\x0d\x20]*/u';
338
339
        return preg_replace_callback(
340
            $pattern,
341
            function ($matches) {
342
                $leadingws = $matches[2];
343
                $ucfirst = self::strtoupper($matches[3]);
344
                $ucword = self::substr_replace(ltrim($matches[0]), $ucfirst, 0, 1);
345
                return $leadingws . $ucword;
346
            },
347
            $str
348
        );
349
    }
350
351
    /**
352
     * This is an Unicode aware replacement for strpos
353
     *
354
     * @param string $haystack
355
     * @param string $needle
356
     * @param integer $offset
357
     * @return integer
358
     * @author Leo Feyer <[email protected]>
359
     * @see    strpos()
360
     *
361
     */
362
    public static function strpos($haystack, $needle, $offset = 0)
363
    {
364
        $comp = 0;
365
        $length = null;
366
367
        while ($length === null || $length < $offset) {
368
            $pos = strpos($haystack, $needle, $offset + $comp);
369
370
            if ($pos === false)
371
                return false;
372
373
            $length = self::strlen(substr($haystack, 0, $pos));
374
375
            if ($length < $offset)
376
                $comp = $pos - $length;
377
        }
378
379
        return $length;
380
    }
381
382
383
}
384