PluginProbe ʕ •ᴥ•ʔ
Advanced Ads – Ad Manager & AdSense / 1.29.0
Advanced Ads – Ad Manager & AdSense v1.29.0
2.0.26 2.0.25 2.0.24 2.0.23 2.0.22 2.0.21 1.38.0 1.39.0 1.39.1 1.39.2 1.39.3 1.39.4 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.42.1 1.42.2 1.43.0 1.44.0 1.44.1 1.45.0 1.45.1 1.46.0 1.47.0 1.47.1 1.47.2 1.47.3 1.47.4 1.47.5 1.48.0 1.48.1 1.49.0 1.5.0 1.5.0.1 1.5.1 1.5.2 1.5.2.1 1.5.4 1.5.4.1 1.5.5 1.50.0 1.51.0 1.51.1 1.51.2 1.51.3 1.52.0 1.52.1 1.52.2 1.52.3 1.52.4 1.53.0 1.53.1 1.53.2 1.54.0 1.54.1 1.55.0 1.56.0 1.56.1 1.56.2 1.56.3 1.56.4 1.6 1.6.1 1.6.10 1.6.10.1 1.6.10.2 1.6.11 1.6.11.1 1.6.12 1.6.13 1.6.14 1.6.15 1.6.16 1.6.17 1.6.17.1 1.6.17.2 1.6.2 1.6.2.1 1.6.3 1.6.4 1.6.4.1 1.6.5 1.6.6 1.6.6.1 1.6.7 1.6.7.1 1.6.8 1.6.8.1 1.6.8.2 1.6.8.3 1.6.9 1.6.9.1 1.6.9.2 1.6.9.3 1.6.9.4 1.7 1.7.0.1 1.7.0.2 1.7.0.3 1.7.1 1.7.1.1 1.7.1.2 1.7.1.3 1.7.1.4 1.7.1.5 1.7.10 trunk 1.7.11 1.0.1 1.7.12 1.0.2 1.7.13 1.0.3 1.7.14 1.1.0 1.7.15 1.1.1 1.7.16 1.1.2 1.7.17 1.1.3 1.7.18 1.10 1.7.19 1.10.1 1.7.2 1.10.10 1.7.2.1 1.10.11 1.7.20 1.10.12 1.7.21 1.10.2 1.7.22 1.10.3 1.7.23 1.10.4 1.7.24 1.10.5 1.7.25 1.10.6 1.7.3 1.10.7 1.7.4 1.10.8 1.7.4.1 1.10.9 1.7.4.2 1.11 1.7.4.3 1.11.1 1.7.4.4 1.11.2 1.7.4.5 1.12 1.7.5 1.13 1.7.5.1 1.13.1 1.7.6 1.13.2 1.7.7 1.13.3 1.7.8 1.13.4 1.7.9 1.13.5 1.7.9.1 1.13.6 1.7.9.2 1.13.7 1.7.9.3 1.13.8 1.8 1.14 1.8.1 1.14.1 1.8.10 1.14.10 1.8.11 1.14.11 1.8.12 1.14.2 1.8.13 1.14.3 1.8.14 1.14.4 1.8.15 1.14.5 1.8.16 1.14.6 1.8.17 1.14.7 1.8.18 1.14.8 1.8.19 1.14.9 1.8.2 1.15 1.8.20 1.16 1.8.21 1.16.1 1.8.22 1.17 1.8.23 1.17.1 1.8.24 1.17.10 1.8.25 1.17.10-rc.1 1.8.26 1.17.11 1.8.27 1.17.12 1.8.28 1.17.12-rc.1 1.8.29 1.17.2 1.8.3 1.17.3 1.8.30 1.17.4 1.8.4 1.17.5 1.8.5 1.17.6 1.8.6 1.17.7 1.8.7 1.17.8 1.8.8 1.17.9 1.8.9 1.17.9-beta.1 1.9 1.18.0 2.0.0 1.19.0 2.0.1 1.19.1 2.0.10 1.2 2.0.11 1.2.1 2.0.12 1.2.2 2.0.13 1.2.3 2.0.14 1.2.4 2.0.15 1.2.5 2.0.16 1.2.6 2.0.17 1.2.7 2.0.18 1.20.0 2.0.19 1.20.0-rc.1 2.0.2 1.20.0-rc.2 2.0.20 1.20.1 2.0.3 1.20.2 2.0.4 1.20.3 2.0.5 1.21.0 2.0.6 1.21.1 2.0.7 1.22.0 2.0.8 1.22.1 2.0.9 1.22.2 1.23.0 1.23.1 1.23.2 1.24.0 1.24.1 1.24.2 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.29.0 1.29.1 1.3 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.30.0 1.30.1 1.30.2 1.30.2-rc.1 1.30.3 1.30.4 1.30.4-rc.1 1.30.5 1.31.0 1.31.1 1.32.0 1.32.0-rc.1 1.33.0 1.33.1 1.33.2 1.34.0 1.35.0 1.35.1 1.36.0 1.36.1 1.36.2 1.36.3 1.37.0 1.37.1 1.37.2
advanced-ads / modules / import-export / classes / XmlEncoder.php
advanced-ads / modules / import-export / classes Last commit date
XmlEncoder.php 5 years ago export.php 5 years ago import.php 5 years ago
XmlEncoder.php
345 lines
1 <?php
2 /**
3 * Encodes XML data.
4 *
5 * Based on code from the Symfony package
6 *
7 * Copyright (c) 2004-2016 Fabien Potencier <fabien@symfony.com>
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is furnished
14 * to do so, subject to the following conditions:
15
16 * The above copyright notice and this permission notice shall be included in all
17 * copies or substantial portions of the Software.
18
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * THE SOFTWARE.
26 *
27 * @author Jordi Boggiano <j.boggiano@seld.be>
28 * @author John Wards <jwards@whiteoctober.co.uk>
29 * @author Fabian Vogler <fabian@equivalence.ch>
30 * @author Kévin Dunglas <dunglas@gmail.com>
31 */
32 class Advanced_Ads_XmlEncoder
33 {
34 /**
35 * @var DOMDocument
36 */
37 private $dom;
38
39 /**
40 * @var Advanced_Ads_XmlEncoder
41 */
42 private static $instance;
43
44 private function __construct() {}
45
46 /**
47 * @return Advanced_Ads_XmlEncoder
48 */
49 public static function get_instance()
50 {
51 if ( ! isset(self::$instance) ) {
52 self::$instance = new self;
53 }
54
55 return self::$instance;
56 }
57
58
59 public function encode( $data, $options = array()) {
60 if ( ! extension_loaded( 'simplexml' ) ) {
61 throw new Exception( sprintf( __( 'The %s extension(s) is not loaded', 'advanced-ads' ), 'simplexml' ) );
62 }
63 if ( ! extension_loaded( 'dom' ) ) {
64 throw new Exception( sprintf( __( 'The %s extension(s) is not loaded', 'advanced-ads' ), 'dom' ) );
65 }
66
67 $this->dom = new DOMDocument();
68 $this->dom->preserveWhiteSpace = false;
69 $this->dom->formatOutput = true;
70 if (isset($options['encoding'])) {
71 $this->dom->encoding = $options['encoding'];
72 }
73
74 if ( ! is_array($data) ) {
75 throw new UnexpectedValueException( _x( 'The data must be an array', 'import_export', 'advanced-ads' ) );
76 }
77
78 if (isset($options['skip_root'])) {
79 $this->buildXml($this->dom, $data );
80 } else {
81 // create root <advads-export> tag
82 $root = $this->dom->createElement('advads-export');
83 $this->dom->appendChild($root);
84 $this->buildXml($root, $data );
85 }
86
87
88 return $this->dom->saveXML();
89 }
90
91 /**
92 * Parse the data and convert it to DOMElements.
93 */
94 private function buildXml(DOMNode $parentNode, $data ) {
95 $append = true;
96
97 foreach ($data as $key => $data) {
98 if (is_numeric($key) ) {
99 $append = $this->appendNode($parentNode, $data, 'item', $key);
100 } elseif ( $this->isElementNameValid($key) ) {
101 $append = $this->appendNode($parentNode, $data, $key);
102 }
103 }
104
105 return $append;
106 }
107
108
109 /**
110 * Selects the type of node to create and appends it to the parent.
111 *
112 * @param DOMNode $parentNode
113 * @param array|object $data
114 * @param string $nodeName
115 * @param string $key
116 *
117 * @return bool
118 */
119 private function appendNode(DOMNode $parentNode, $data, $nodeName, $key = null) {
120 $node = $this->dom->createElement($nodeName);
121
122 if (null !== $key) {
123 $node->setAttribute('key', $key);
124 }
125
126 $appendNode = false;
127 if (is_array($data)) {
128 $node->setAttribute('type', 'array' );
129 $appendNode = $this->buildXml($node, $data);
130 } elseif (is_numeric($data)) {
131 $node->setAttribute('type', is_string( $data) ? 'string' : 'numeric' );
132 $appendNode = $this->appendText($node, (string) $data);
133 } elseif (is_string($data)) {
134 $node->setAttribute('type', 'string');
135 $appendNode = $this->needsCdataWrapping($data) ? $this->appendCData($node, $data) : $this->appendText($node, $data);
136 } elseif (is_bool($data)) {
137 $node->setAttribute('type', 'boolean');
138 $appendNode = $this->appendText($node, (int) $data);
139 } elseif (is_null($data)) {
140 $node->setAttribute('type', 'null');
141 $appendNode = $this->appendText($node, '');
142 }
143
144 if ($appendNode) {
145 $parentNode->appendChild($node);
146 } else {
147 throw new UnexpectedValueException( sprintf( _x( 'An unexpected value could not be serialized: %s', 'import_export', 'advanced-ads' ), var_export($data, true) ) );
148 }
149
150 return $appendNode;
151 }
152
153 final protected function appendText(DOMNode $node, $val) {
154 $nodeText = $this->dom->createTextNode($val);
155 $node->appendChild($nodeText);
156
157 return true;
158 }
159
160 final protected function appendCData(DOMNode $node, $val) {
161 $nodeText = $this->dom->createCDATASection($val);
162 $node->appendChild($nodeText);
163
164 return true;
165 }
166
167 /**
168 * Checks if a value contains any characters which would require CDATA wrapping.
169 *
170 * @param string $val
171 *
172 * @return bool
173 */
174 private function needsCdataWrapping($val) {
175 return preg_match('/[<>&]/', $val);
176 }
177
178 /**
179 * Checks the name is a valid xml element name.
180 *
181 * @param string $name
182 *
183 * @return bool
184 */
185 final protected function isElementNameValid($name) {
186 return $name && false === strpos($name, ' ') && preg_match('#^[\pL_][\pL0-9._:-]*$#ui', $name);
187 }
188
189 /**
190 * Decode XML data.
191 *
192 * @throws Exception If an extension is lt loaded.
193 * @throws UnexpectedValueException If XML data is invalid.
194 *
195 * @param string $data XML data.
196 * @return array Decoded XML data.
197 */
198 public function decode( $data ) {
199 if ( ! extension_loaded( 'simplexml' ) ) {
200 /* translators: %s: A name of not loaded extension. */
201 throw new Exception( sprintf( __( 'The %s extension(s) is not loaded', 'advanced-ads' ), 'simplexml' ) );
202 }
203 if ( ! extension_loaded( 'dom' ) ) {
204 /* translators: %s: A name of not loaded extension. */
205 throw new Exception( sprintf( __( 'The %s extension(s) is not loaded', 'advanced-ads' ), 'dom' ) );
206 }
207
208
209 if ('' === trim($data)) {
210 throw new UnexpectedValueException( _x( 'Invalid XML data, it can not be empty', 'import_export', 'advanced-ads' ) );
211 }
212
213 $internal_errors = libxml_use_internal_errors( true );
214
215 if ( PHP_VERSION_ID < 80000 ) {
216 // This function has been deprecated in PHP 8.0 because in libxml 2.9.0, external entity loading
217 // is disabled by default, so this function is no longer needed to protect against XXE attacks.
218 // phpcs:ignore PHPCompatibility.FunctionUse.RemovedFunctions.libxml_disable_entity_loaderDeprecated
219 $disable_entities = libxml_disable_entity_loader( true );
220 }
221
222 libxml_clear_errors();
223
224 $dom = new DOMDocument();
225
226 if ( strpos( $data, '<advads-export>' ) === false ) {
227 $data = preg_replace('/^<\?xml.*?\?>/', '', $data );
228 $data = '<advads-export>' . $data . '</advads-export>';
229 }
230
231 $dom->loadXML($data, LIBXML_NONET | LIBXML_NOBLANKS);
232
233 libxml_use_internal_errors( $internal_errors );
234
235 if ( PHP_VERSION_ID < 80000 && isset( $disable_entities ) ) {
236 libxml_disable_entity_loader( $disable_entities );
237 }
238
239 if ($error = libxml_get_last_error()) {
240 libxml_clear_errors();
241
242 throw new UnexpectedValueException( sprintf( _x( 'XML error: %s', 'import_export', 'advanced-ads' ), $error->message ) );
243
244 }
245
246 // <advads-export>
247 $rootNode = $dom->firstChild;
248
249 if ($rootNode->hasChildNodes()) {
250 return $this->parseXml($rootNode);
251 }
252 }
253
254 /**
255 * Parse the input DOMNode into an array or a string.
256 *
257 * @param DOMNode $node xml to parse
258 *
259 * @return array|string
260 */
261 private function parseXml(DOMNode $node) {
262 // Parse the input DOMNode value (content and children) into an array or a string
263 $data = array();
264 if ( $node->hasAttributes() ) {
265 foreach ($node->attributes as $attr) {
266 if (ctype_digit($attr->nodeValue)) {
267 $data['@'.$attr->nodeName] = (int) $attr->nodeValue;
268 } else {
269 $data['@'.$attr->nodeName] = $attr->nodeValue;
270 }
271 }
272 }
273
274 $text_type = isset($data['@type']) ? $data['@type'] : null;
275 unset( $data['@type'] );
276
277 // Parse the input DOMNode value (content and children) into an array or a string.
278 if (!$node->hasChildNodes()) {
279 $value = $node->nodeValue;
280 } elseif (1 === $node->childNodes->length && in_array($node->firstChild->nodeType, array(XML_TEXT_NODE, XML_CDATA_SECTION_NODE))) {
281 $value = $node->firstChild->nodeValue;
282 } else {
283
284
285 $value = array();
286
287 foreach ($node->childNodes as $subnode) {
288 $val = $this->parseXml($subnode);
289
290 if ('item' === $subnode->nodeName && is_array($val) && isset($val['@key'])) {
291 $a = $val['@key'];
292 if (isset($val['#'])) {
293 $value[$a] = $val['#'] !== 'null' ? $val['#'] : null;
294 } else {
295 $value[$a] = $val !== 'null' ? $val : null;
296 }
297
298 } else {
299 $value[$subnode->nodeName][] = $val === 'null' ? null : $val;
300 }
301 }
302 foreach ($value as $key => $val) {
303 if (is_array($val) && 1 === count($val)) {
304 $value[$key] = current($val);
305 } else if ( is_array( $value[$key] ) && isset( $value[$key]['@key'] ) ) {
306 unset( $value[$key]['@key'] );
307 }
308 }
309 }
310
311 if (!count($data)) {
312 $value = $this->changeType( $value, $text_type );
313 return $value;
314 }
315
316 if (!is_array($value)) {
317 $value = $this->changeType( $value, $text_type );
318 $data['#'] = $value;
319 return $data;
320 }
321
322 if (1 === count($value) && key($value)) {
323 $data[key($value)] = current($value);
324
325 return $data;
326 }
327
328 foreach ($value as $key => $val) {
329 $data[$key] = $val;
330 }
331
332 return $data;
333 }
334
335 private function changeType( $text, $type ) {
336 if ( $type === 'string' ) return (string) $text;
337 if ( $type === 'numeric' ) return 0 + $text;
338 if ( $type === 'boolean' ) return (boolean) $text;
339 if ( $type === 'array' && $text=== '' ) return array();
340 if ( $type === 'null' ) return 'null';
341 return $text;
342 }
343
344 }
345