• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

PHPOffice / Math / 15319655684

29 May 2025 08:25AM UTC coverage: 95.208% (-4.8%) from 100.0%
15319655684

push

github

Progi1984
Merge commit from fork

14 of 29 new or added lines in 2 files covered. (48.28%)

298 of 313 relevant lines covered (95.21%)

3.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

42.31
/src/Math/Reader/Security/XmlScanner.php
1
<?php
2

3
namespace PhpOffice\Math\Reader\Security;
4

5
use PhpOffice\Math\Exception\SecurityException;
6

7
class XmlScanner
8
{
9
    public static function getInstance(): self
10
    {
11
        return new self();
8✔
12
    }
13

14
    /**
15
     * Scan the XML for use of <!ENTITY to prevent XXE/XEE attacks.
16
     */
17
    public function scan(string $xml): string
18
    {
19
        // Don't rely purely on libxml_disable_entity_loader()
20
        $searchDoctype = static::mb_str_split('<!DOCTYPE', 1, 'UTF-8');
8✔
21
        $patternDoctype = '/\0*' . implode('\0*', is_array($searchDoctype) ? $searchDoctype : []) . '\0*/';
8✔
22
        $searchDoctypeMath = static::mb_str_split('<!DOCTYPE math', 1, 'UTF-8');
8✔
23
        $patternDoctypeMath = '/\0*' . implode('\0*', is_array($searchDoctypeMath) ? $searchDoctypeMath : []) . '\0*/';
8✔
24

25
        if (preg_match($patternDoctype, $xml) && !preg_match($patternDoctypeMath, $xml)) {
8✔
26
            throw new SecurityException('Detected use of ENTITY in XML, loading aborted to prevent XXE/XEE attacks');
1✔
27
        }
28

29
        return $xml;
7✔
30
    }
31

32
    /**
33
     * @param string $string
34
     * @param int<1, max> $split_length
35
     * @param string|null $encoding
36
     *
37
     * @return array<string>|bool|null
38
     */
39
    public static function mb_str_split(string $string, int $split_length = 1, ?string $encoding = null)
40
    {
41
        if (extension_loaded('mbstring')) {
8✔
42
            if (function_exists('mb_str_split')) {
8✔
43
                return mb_str_split($string, $split_length, $encoding);
8✔
44
            }
45
        }
NEW
46
        if (null !== $string && !\is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
×
NEW
47
            trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
×
48

NEW
49
            return null;
×
50
        }
51

NEW
52
        if (1 > $split_length = (int) $split_length) {
×
NEW
53
            trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
×
54

NEW
55
            return false;
×
56
        }
57

NEW
58
        if (null === $encoding) {
×
NEW
59
            $encoding = mb_internal_encoding();
×
60
        }
61

NEW
62
        if ('UTF-8' === $encoding || \in_array(strtoupper($encoding), ['UTF-8', 'UTF8'], true)) {
×
NEW
63
            return preg_split("/(.{{$split_length}})/u", $string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
×
64
        }
65

NEW
66
        $result = [];
×
NEW
67
        $length = mb_strlen($string, $encoding);
×
68

NEW
69
        for ($i = 0; $i < $length; $i += $split_length) {
×
NEW
70
            $result[] = mb_substr($string, $i, $split_length, $encoding);
×
71
        }
72

NEW
73
        return $result;
×
74
    }
75
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc