[SECURITY] XML entity expansion
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Localization / Parser / AbstractXmlParser.php
1 <?php
2 namespace TYPO3\CMS\Core\Localization\Parser;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Core\Charset\CharsetConverter;
18 use TYPO3\CMS\Core\Localization\Exception\FileNotFoundException;
19 use TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException;
20 use TYPO3\CMS\Core\Utility\GeneralUtility;
21
22 /**
23 * Abstract class for XML based parser.
24 */
25 abstract class AbstractXmlParser implements \TYPO3\CMS\Core\Localization\Parser\LocalizationParserInterface
26 {
27 /**
28 * @var string
29 */
30 protected $sourcePath;
31
32 /**
33 * @var string
34 */
35 protected $languageKey;
36
37 /**
38 * @var string
39 */
40 protected $charset;
41
42 /**
43 * Returns parsed representation of XML file.
44 *
45 * @param string $sourcePath Source file path
46 * @param string $languageKey Language key
47 * @param string $charset File charset
48 * @return array
49 * @throws \TYPO3\CMS\Core\Localization\Exception\FileNotFoundException
50 */
51 public function getParsedData($sourcePath, $languageKey, $charset = '')
52 {
53 $this->sourcePath = $sourcePath;
54 $this->languageKey = $languageKey;
55 $this->charset = $this->getCharset($languageKey, $charset);
56 if ($this->languageKey !== 'default') {
57 $this->sourcePath = GeneralUtility::getFileAbsFileName(GeneralUtility::llXmlAutoFileName($this->sourcePath, $this->languageKey));
58 if (!@is_file($this->sourcePath)) {
59 // Global localization is not available, try split localization file
60 $this->sourcePath = GeneralUtility::getFileAbsFileName(GeneralUtility::llXmlAutoFileName($sourcePath, $languageKey, true));
61 }
62 if (!@is_file($this->sourcePath)) {
63 throw new FileNotFoundException('Localization file does not exist', 1306332397);
64 }
65 }
66 $LOCAL_LANG = array();
67 $LOCAL_LANG[$languageKey] = $this->parseXmlFile();
68 return $LOCAL_LANG;
69 }
70
71 /**
72 * Gets the character set to use.
73 *
74 * @param string $languageKey
75 * @param string $charset
76 * @return string
77 */
78 protected function getCharset($languageKey, $charset = '')
79 {
80 /** @var $charsetConverter CharsetConverter */
81 if (is_object($GLOBALS['LANG'])) {
82 $charsetConverter = $GLOBALS['LANG']->csConvObj;
83 } elseif (is_object($GLOBALS['TSFE'])) {
84 $charsetConverter = $GLOBALS['TSFE']->csConvObj;
85 } else {
86 $charsetConverter = GeneralUtility::makeInstance(CharsetConverter::class);
87 }
88 if ($charset !== '') {
89 $targetCharset = $charsetConverter->parse_charset($charset);
90 } else {
91 $targetCharset = 'utf-8';
92 }
93 return $targetCharset;
94 }
95
96 /**
97 * Loads the current XML file before processing.
98 *
99 * @return array An array representing parsed XML file (structure depends on concrete parser)
100 * @throws \TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException
101 */
102 protected function parseXmlFile()
103 {
104 $xmlContent = file_get_contents($this->sourcePath);
105 // Disables the functionality to allow external entities to be loaded when parsing the XML, must be kept
106 $previousValueOfEntityLoader = libxml_disable_entity_loader(true);
107 $rootXmlNode = simplexml_load_string($xmlContent, 'SimpleXMLElement', LIBXML_NOWARNING);
108 libxml_disable_entity_loader($previousValueOfEntityLoader);
109 if (!isset($rootXmlNode) || $rootXmlNode === false) {
110 throw new InvalidXmlFileException('The path provided does not point to existing and accessible well-formed XML file.', 1278155988);
111 }
112 return $this->doParsingFromRoot($rootXmlNode);
113 }
114
115 /**
116 * Returns array representation of XML data, starting from a root node.
117 *
118 * @param \SimpleXMLElement $root A root node
119 * @return array An array representing the parsed XML file
120 */
121 abstract protected function doParsingFromRoot(\SimpleXMLElement $root);
122 }