run:R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
DIR
2026-03-11 16:18:52
R W Run
1.86 KB
2026-03-11 16:18:52
R W Run
3.17 KB
2026-03-11 16:18:52
R W Run
3.03 KB
2026-03-11 16:18:52
R W Run
2.41 KB
2026-03-11 16:18:52
R W Run
1.67 KB
2026-03-11 16:18:52
R W Run
2.09 KB
2026-03-11 16:18:52
R W Run
31.39 KB
2026-03-11 16:18:52
R W Run
355 By
2026-03-11 16:18:52
R W Run
18.94 KB
2026-03-11 16:18:52
R W Run
8.31 KB
2026-03-11 16:18:52
R W Run
33.99 KB
2026-03-11 16:18:52
R W Run
128.54 KB
2026-03-11 16:18:52
R W Run
16.31 KB
2026-03-11 16:18:52
R W Run
68.16 KB
2026-03-11 16:18:52
R W Run
34.05 KB
2026-03-11 16:18:52
R W Run
1.75 KB
2026-03-11 16:18:52
R W Run
7.71 KB
2026-03-11 16:18:52
R W Run
447 By
2026-03-11 16:18:52
R W Run
2.31 KB
2026-03-11 16:18:52
R W Run
29.64 KB
2026-03-11 16:18:52
R W Run
125.05 KB
2026-03-11 16:18:52
R W Run
23.18 KB
2026-03-11 16:18:52
R W Run
error_log
📄Parser.php
1<?php
2
3// SPDX-FileCopyrightText: 2004-2023 Ryan Parman, Sam Sneddon, Ryan McCue
4// SPDX-License-Identifier: BSD-3-Clause
5
6declare(strict_types=1);
7
8namespace SimplePie;
9
10use SimplePie\XML\Declaration\Parser as DeclarationParser;
11use XMLParser;
12
13/**
14 * Parses XML into something sane
15 *
16 *
17 * This class can be overloaded with {@see \SimplePie\SimplePie::set_parser_class()}
18 */
19class Parser implements RegistryAware
20{
21 /** @var int */
22 public $error_code;
23 /** @var string */
24 public $error_string;
25 /** @var int */
26 public $current_line;
27 /** @var int */
28 public $current_column;
29 /** @var int */
30 public $current_byte;
31 /** @var string */
32 public $separator = ' ';
33 /** @var string[] */
34 public $namespace = [''];
35 /** @var string[] */
36 public $element = [''];
37 /** @var string[] */
38 public $xml_base = [''];
39 /** @var bool[] */
40 public $xml_base_explicit = [false];
41 /** @var string[] */
42 public $xml_lang = [''];
43 /** @var array<string, mixed> */
44 public $data = [];
45 /** @var array<array<string, mixed>> */
46 public $datas = [[]];
47 /** @var int */
48 public $current_xhtml_construct = -1;
49 /** @var string */
50 public $encoding;
51 /** @var Registry */
52 protected $registry;
53
54 /**
55 * @return void
56 */
57 public function set_registry(\SimplePie\Registry $registry)
58 {
59 $this->registry = $registry;
60 }
61
62 /**
63 * @return bool
64 */
65 public function parse(string &$data, string $encoding, string $url = '')
66 {
67 if (class_exists('DOMXpath') && function_exists('Mf2\parse')) {
68 $doc = new \DOMDocument();
69 @$doc->loadHTML($data);
70 $xpath = new \DOMXpath($doc);
71 // Check for both h-feed and h-entry, as both a feed with no entries
72 // and a list of entries without an h-feed wrapper are both valid.
73 $query = '//*[contains(concat(" ", @class, " "), " h-feed ") or '.
74 'contains(concat(" ", @class, " "), " h-entry ")]';
75 /** @var \DOMNodeList<\DOMElement> $result */
76 $result = $xpath->query($query);
77 if ($result->length !== 0) {
78 return $this->parse_microformats($data, $url);
79 }
80 }
81
82 // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
83 if (strtoupper($encoding) === 'US-ASCII') {
84 $this->encoding = 'UTF-8';
85 } else {
86 $this->encoding = $encoding;
87 }
88
89 // Strip BOM:
90 // UTF-32 Big Endian BOM
91 if (substr($data, 0, 4) === "\x00\x00\xFE\xFF") {
92 $data = substr($data, 4);
93 }
94 // UTF-32 Little Endian BOM
95 elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00") {
96 $data = substr($data, 4);
97 }
98 // UTF-16 Big Endian BOM
99 elseif (substr($data, 0, 2) === "\xFE\xFF") {
100 $data = substr($data, 2);
101 }
102 // UTF-16 Little Endian BOM
103 elseif (substr($data, 0, 2) === "\xFF\xFE") {
104 $data = substr($data, 2);
105 }
106 // UTF-8 BOM
107 elseif (substr($data, 0, 3) === "\xEF\xBB\xBF") {
108 $data = substr($data, 3);
109 }
110
111 if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false) {
112 $declaration = $this->registry->create(DeclarationParser::class, [substr($data, 5, $pos - 5)]);
113 if ($declaration->parse()) {
114 $data = substr($data, $pos + 2);
115 $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . "\n" .
116 self::set_doctype($data);
117 } else {
118 $this->error_string = 'SimplePie bug! Please report this!';
119 return false;
120 }
121 } else {
122 $data = self::set_doctype($data);
123 }
124
125 $return = true;
126
127 static $xml_is_sane = null;
128 if ($xml_is_sane === null) {
129 $parser_check = xml_parser_create();
130 xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
131 if (\PHP_VERSION_ID < 80000) {
132 xml_parser_free($parser_check);
133 }
134 $xml_is_sane = isset($values[0]['value']);
135 }
136
137 // Create the parser
138 if ($xml_is_sane) {
139 $xml = xml_parser_create_ns($this->encoding, $this->separator);
140 xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
141 xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
142 xml_set_character_data_handler($xml, [$this, 'cdata']);
143 xml_set_element_handler($xml, [$this, 'tag_open'], [$this, 'tag_close']);
144
145 // Parse!
146 $wrapper = @is_writable(sys_get_temp_dir()) ? 'php://temp' : 'php://memory';
147 if (($stream = fopen($wrapper, 'r+')) &&
148 fwrite($stream, $data) &&
149 rewind($stream)) {
150 //Parse by chunks not to use too much memory
151 do {
152 $stream_data = (string) fread($stream, 1048576);
153
154 if (!xml_parse($xml, $stream_data, feof($stream))) {
155 $this->error_code = xml_get_error_code($xml);
156 $this->error_string = xml_error_string($this->error_code) ?: "Unknown";
157 $return = false;
158 break;
159 }
160 } while (!feof($stream));
161 fclose($stream);
162 } else {
163 $return = false;
164 }
165
166 $this->current_line = xml_get_current_line_number($xml);
167 $this->current_column = xml_get_current_column_number($xml);
168 $this->current_byte = xml_get_current_byte_index($xml);
169 if (\PHP_VERSION_ID < 80000) {
170 xml_parser_free($xml);
171 }
172 return $return;
173 }
174
175 libxml_clear_errors();
176 $xml = new \XMLReader();
177 $xml->xml($data);
178 while (@$xml->read()) {
179 switch ($xml->nodeType) {
180 case \XMLReader::END_ELEMENT:
181 if ($xml->namespaceURI !== '') {
182 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
183 } else {
184 $tagName = $xml->localName;
185 }
186 $this->tag_close(null, $tagName);
187 break;
188 case \XMLReader::ELEMENT:
189 $empty = $xml->isEmptyElement;
190 if ($xml->namespaceURI !== '') {
191 $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
192 } else {
193 $tagName = $xml->localName;
194 }
195 $attributes = [];
196 while ($xml->moveToNextAttribute()) {
197 if ($xml->namespaceURI !== '') {
198 $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
199 } else {
200 $attrName = $xml->localName;
201 }
202 $attributes[$attrName] = $xml->value;
203 }
204 $this->tag_open(null, $tagName, $attributes);
205 if ($empty) {
206 $this->tag_close(null, $tagName);
207 }
208 break;
209 case \XMLReader::TEXT:
210
211 case \XMLReader::CDATA:
212 $this->cdata(null, $xml->value);
213 break;
214 }
215 }
216 if ($error = libxml_get_last_error()) {
217 $this->error_code = $error->code;
218 $this->error_string = $error->message;
219 $this->current_line = $error->line;
220 $this->current_column = $error->column;
221 return false;
222 }
223
224 return true;
225 }
226
227 /**
228 * @return int
229 */
230 public function get_error_code()
231 {
232 return $this->error_code;
233 }
234
235 /**
236 * @return string
237 */
238 public function get_error_string()
239 {
240 return $this->error_string;
241 }
242
243 /**
244 * @return int
245 */
246 public function get_current_line()
247 {
248 return $this->current_line;
249 }
250
251 /**
252 * @return int
253 */
254 public function get_current_column()
255 {
256 return $this->current_column;
257 }
258
259 /**
260 * @return int
261 */
262 public function get_current_byte()
263 {
264 return $this->current_byte;
265 }
266
267 /**
268 * @return array<string, mixed>
269 */
270 public function get_data()
271 {
272 return $this->data;
273 }
274
275 /**
276 * @param XMLParser|resource|null $parser
277 * @param array<string, string> $attributes
278 * @return void
279 */
280 public function tag_open($parser, string $tag, array $attributes)
281 {
282 [$this->namespace[], $this->element[]] = $this->split_ns($tag);
283
284 $attribs = [];
285 foreach ($attributes as $name => $value) {
286 [$attrib_namespace, $attribute] = $this->split_ns($name);
287 $attribs[$attrib_namespace][$attribute] = $value;
288 }
289
290 if (isset($attribs[\SimplePie\SimplePie::NAMESPACE_XML]['base'])) {
291 $base = $this->registry->call(Misc::class, 'absolutize_url', [$attribs[\SimplePie\SimplePie::NAMESPACE_XML]['base'], end($this->xml_base)]);
292 if ($base !== false) {
293 $this->xml_base[] = $base;
294 $this->xml_base_explicit[] = true;
295 }
296 } else {
297 $this->xml_base[] = end($this->xml_base) ?: '';
298 $this->xml_base_explicit[] = end($this->xml_base_explicit);
299 }
300
301 if (isset($attribs[\SimplePie\SimplePie::NAMESPACE_XML]['lang'])) {
302 $this->xml_lang[] = $attribs[\SimplePie\SimplePie::NAMESPACE_XML]['lang'];
303 } else {
304 $this->xml_lang[] = end($this->xml_lang) ?: '';
305 }
306
307 if ($this->current_xhtml_construct >= 0) {
308 $this->current_xhtml_construct++;
309 if (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_XHTML) {
310 $this->data['data'] .= '<' . end($this->element);
311 if (isset($attribs[''])) {
312 foreach ($attribs[''] as $name => $value) {
313 $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
314 }
315 }
316 $this->data['data'] .= '>';
317 }
318 } else {
319 $this->datas[] = &$this->data;
320 $this->data = &$this->data['child'][end($this->namespace)][end($this->element)][];
321 $this->data = ['data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang)];
322 if ((end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_ATOM_03 && in_array(end($this->element), ['title', 'tagline', 'copyright', 'info', 'summary', 'content']) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
323 || (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_ATOM_10 && in_array(end($this->element), ['rights', 'subtitle', 'summary', 'info', 'title', 'content']) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml')
324 || (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_RSS_20 && in_array(end($this->element), ['title']))
325 || (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_RSS_090 && in_array(end($this->element), ['title']))
326 || (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_RSS_10 && in_array(end($this->element), ['title']))) {
327 $this->current_xhtml_construct = 0;
328 }
329 }
330 }
331
332 /**
333 * @param XMLParser|resource|null $parser
334 * @return void
335 */
336 public function cdata($parser, string $cdata)
337 {
338 if ($this->current_xhtml_construct >= 0) {
339 $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
340 } else {
341 $this->data['data'] .= $cdata;
342 }
343 }
344
345 /**
346 * @param XMLParser|resource|null $parser
347 * @return void
348 */
349 public function tag_close($parser, string $tag)
350 {
351 if ($this->current_xhtml_construct >= 0) {
352 $this->current_xhtml_construct--;
353 if (end($this->namespace) === \SimplePie\SimplePie::NAMESPACE_XHTML && !in_array(end($this->element), ['area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param'])) {
354 $this->data['data'] .= '</' . end($this->element) . '>';
355 }
356 }
357 if ($this->current_xhtml_construct === -1) {
358 $this->data = &$this->datas[count($this->datas) - 1];
359 array_pop($this->datas);
360 }
361
362 array_pop($this->element);
363 array_pop($this->namespace);
364 array_pop($this->xml_base);
365 array_pop($this->xml_base_explicit);
366 array_pop($this->xml_lang);
367 }
368
369 /**
370 * @return array{string, string}
371 */
372 public function split_ns(string $string)
373 {
374 static $cache = [];
375 if (!isset($cache[$string])) {
376 if ($pos = strpos($string, $this->separator)) {
377 static $separator_length;
378 if (!$separator_length) {
379 $separator_length = strlen($this->separator);
380 }
381 $namespace = substr($string, 0, $pos);
382 $local_name = substr($string, $pos + $separator_length);
383 if (strtolower($namespace) === \SimplePie\SimplePie::NAMESPACE_ITUNES) {
384 $namespace = \SimplePie\SimplePie::NAMESPACE_ITUNES;
385 }
386
387 // Normalize the Media RSS namespaces
388 if ($namespace === \SimplePie\SimplePie::NAMESPACE_MEDIARSS_WRONG ||
389 $namespace === \SimplePie\SimplePie::NAMESPACE_MEDIARSS_WRONG2 ||
390 $namespace === \SimplePie\SimplePie::NAMESPACE_MEDIARSS_WRONG3 ||
391 $namespace === \SimplePie\SimplePie::NAMESPACE_MEDIARSS_WRONG4 ||
392 $namespace === \SimplePie\SimplePie::NAMESPACE_MEDIARSS_WRONG5) {
393 $namespace = \SimplePie\SimplePie::NAMESPACE_MEDIARSS;
394 }
395 $cache[$string] = [$namespace, $local_name];
396 } else {
397 $cache[$string] = ['', $string];
398 }
399 }
400 return $cache[$string];
401 }
402
403 /**
404 * @param array<string, mixed> $data
405 */
406 private function parse_hcard(array $data, bool $category = false): string
407 {
408 $name = '';
409 $link = '';
410 // Check if h-card is set and pass that information on in the link.
411 if (isset($data['type']) && in_array('h-card', $data['type'])) {
412 if (isset($data['properties']['name'][0])) {
413 $name = $data['properties']['name'][0];
414 }
415 if (isset($data['properties']['url'][0])) {
416 $link = $data['properties']['url'][0];
417 if ($name === '') {
418 $name = $link;
419 } else {
420 // can't have commas in categories.
421 $name = str_replace(',', '', $name);
422 }
423 $person_tag = $category ? '<span class="person-tag"></span>' : '';
424 return '<a class="h-card" href="'.$link.'">'.$person_tag.$name.'</a>';
425 }
426 }
427 return $data['value'] ?? '';
428 }
429
430 /**
431 * @return true
432 */
433 private function parse_microformats(string &$data, string $url): bool
434 {
435 // For PHPStan, we already check that in call site.
436 \assert(function_exists('Mf2\parse'));
437 \assert(function_exists('Mf2\fetch'));
438 $feed_title = '';
439 $feed_author = null;
440 $author_cache = [];
441 $items = [];
442 $entries = [];
443 $mf = \Mf2\parse($data, $url);
444 // First look for an h-feed.
445 $h_feed = [];
446 foreach ($mf['items'] as $mf_item) {
447 if (in_array('h-feed', $mf_item['type'])) {
448 $h_feed = $mf_item;
449 break;
450 }
451 // Also look for h-feed or h-entry in the children of each top level item.
452 if (!isset($mf_item['children'][0]['type'])) {
453 continue;
454 }
455 if (in_array('h-feed', $mf_item['children'][0]['type'])) {
456 $h_feed = $mf_item['children'][0];
457 // In this case the parent of the h-feed may be an h-card, so use it as
458 // the feed_author.
459 if (in_array('h-card', $mf_item['type'])) {
460 $feed_author = $mf_item;
461 }
462 break;
463 } elseif (in_array('h-entry', $mf_item['children'][0]['type'])) {
464 $entries = $mf_item['children'];
465 // In this case the parent of the h-entry list may be an h-card, so use
466 // it as the feed_author.
467 if (in_array('h-card', $mf_item['type'])) {
468 $feed_author = $mf_item;
469 }
470 break;
471 }
472 }
473 if (isset($h_feed['children'])) {
474 $entries = $h_feed['children'];
475 // Also set the feed title and store author from the h-feed if available.
476 if (isset($mf['items'][0]['properties']['name'][0])) {
477 $feed_title = $mf['items'][0]['properties']['name'][0];
478 }
479 if (isset($mf['items'][0]['properties']['author'][0])) {
480 $feed_author = $mf['items'][0]['properties']['author'][0];
481 }
482 } elseif (count($entries) === 0) {
483 $entries = $mf['items'];
484 }
485 for ($i = 0; $i < count($entries); $i++) {
486 $entry = $entries[$i];
487 if (in_array('h-entry', $entry['type'])) {
488 $item = [];
489 $title = '';
490 $description = '';
491 if (isset($entry['properties']['url'][0])) {
492 $link = $entry['properties']['url'][0];
493 if (isset($link['value'])) {
494 $link = $link['value'];
495 }
496 $item['link'] = [['data' => $link]];
497 }
498 if (isset($entry['properties']['uid'][0])) {
499 $guid = $entry['properties']['uid'][0];
500 if (isset($guid['value'])) {
501 $guid = $guid['value'];
502 }
503 $item['guid'] = [['data' => $guid]];
504 }
505 if (isset($entry['properties']['name'][0])) {
506 $title = $entry['properties']['name'][0];
507 if (isset($title['value'])) {
508 $title = $title['value'];
509 }
510 $item['title'] = [['data' => $title]];
511 }
512 if (isset($entry['properties']['author'][0]) || isset($feed_author)) {
513 // author is a special case, it can be plain text or an h-card array.
514 // If it's plain text it can also be a url that should be followed to
515 // get the actual h-card.
516 $author = $entry['properties']['author'][0] ?? $feed_author;
517 if (!is_string($author)) {
518 $author = $this->parse_hcard($author);
519 } elseif (strpos($author, 'http') === 0) {
520 if (isset($author_cache[$author])) {
521 $author = $author_cache[$author];
522 } else {
523 if ($mf = \Mf2\fetch($author)) {
524 foreach ($mf['items'] as $hcard) {
525 // Only interested in an h-card by itself in this case.
526 if (!in_array('h-card', $hcard['type'])) {
527 continue;
528 }
529 // It must have a url property matching what we fetched.
530 if (!isset($hcard['properties']['url']) ||
531 !(in_array($author, $hcard['properties']['url']))) {
532 continue;
533 }
534 // Save parse_hcard the trouble of finding the correct url.
535 $hcard['properties']['url'][0] = $author;
536 // Cache this h-card for the next h-entry to check.
537 $author_cache[$author] = $this->parse_hcard($hcard);
538 $author = $author_cache[$author];
539 break;
540 }
541 }
542 }
543 }
544 $item['author'] = [['data' => $author]];
545 }
546 if (isset($entry['properties']['photo'][0])) {
547 // If a photo is also in content, don't need to add it again here.
548 $content = '';
549 if (isset($entry['properties']['content'][0]['html'])) {
550 $content = $entry['properties']['content'][0]['html'];
551 }
552 $photo_list = [];
553 for ($j = 0; $j < count($entry['properties']['photo']); $j++) {
554 $photo = $entry['properties']['photo'][$j];
555 if (!empty($photo) && strpos($content, $photo) === false) {
556 $photo_list[] = $photo;
557 }
558 }
559 // When there's more than one photo show the first and use a lightbox.
560 // Need a permanent, unique name for the image set, but don't have
561 // anything unique except for the content itself, so use that.
562 $count = count($photo_list);
563 if ($count > 1) {
564 $image_set_id = preg_replace('/[[:^alnum:]]/', '', $photo_list[0]);
565 $description = '<p>';
566 for ($j = 0; $j < $count; $j++) {
567 $hidden = $j === 0 ? '' : 'class="hidden" ';
568 $description .= '<a href="'.$photo_list[$j].'" '.$hidden.
569 'data-lightbox="image-set-'.$image_set_id.'">'.
570 '<img src="'.$photo_list[$j].'"></a>';
571 }
572 $description .= '<br><b>'.$count.' photos</b></p>';
573 } elseif ($count == 1) {
574 $description = '<p><img src="'.$photo_list[0].'"></p>';
575 }
576 }
577 if (isset($entry['properties']['content'][0]['html'])) {
578 // e-content['value'] is the same as p-name when they are on the same
579 // element. Use this to replace title with a strip_tags version so
580 // that alt text from images is not included in the title.
581 if ($entry['properties']['content'][0]['value'] === $title) {
582 $title = strip_tags($entry['properties']['content'][0]['html']);
583 $item['title'] = [['data' => $title]];
584 }
585 $description .= $entry['properties']['content'][0]['html'];
586 if (isset($entry['properties']['in-reply-to'][0])) {
587 $in_reply_to = '';
588 if (is_string($entry['properties']['in-reply-to'][0])) {
589 $in_reply_to = $entry['properties']['in-reply-to'][0];
590 } elseif (isset($entry['properties']['in-reply-to'][0]['value'])) {
591 $in_reply_to = $entry['properties']['in-reply-to'][0]['value'];
592 }
593 if ($in_reply_to !== '') {
594 $description .= '<p><span class="in-reply-to"></span> '.
595 '<a href="'.$in_reply_to.'">'.$in_reply_to.'</a><p>';
596 }
597 }
598 $item['description'] = [['data' => $description]];
599 }
600 if (isset($entry['properties']['category'])) {
601 $category_csv = '';
602 // Categories can also contain h-cards.
603 foreach ($entry['properties']['category'] as $category) {
604 if ($category_csv !== '') {
605 $category_csv .= ', ';
606 }
607 if (is_string($category)) {
608 // Can't have commas in categories.
609 $category_csv .= str_replace(',', '', $category);
610 } else {
611 $category_csv .= $this->parse_hcard($category, true);
612 }
613 }
614 $item['category'] = [['data' => $category_csv]];
615 }
616 if (isset($entry['properties']['published'][0])) {
617 $timestamp = strtotime($entry['properties']['published'][0]);
618 $pub_date = date('F j Y g:ia', $timestamp).' GMT';
619 $item['pubDate'] = [['data' => $pub_date]];
620 }
621 // The title and description are set to the empty string to represent
622 // a deleted item (which also makes it an invalid rss item).
623 if (isset($entry['properties']['deleted'][0])) {
624 $item['title'] = [['data' => '']];
625 $item['description'] = [['data' => '']];
626 }
627 $items[] = ['child' => ['' => $item]];
628 }
629 }
630 // Mimic RSS data format when storing microformats.
631 $link = [['data' => $url]];
632 $image = '';
633 if (!is_string($feed_author) &&
634 isset($feed_author['properties']['photo'][0])) {
635 $image = [['child' => ['' => ['url' =>
636 [['data' => $feed_author['properties']['photo'][0]]]]]]];
637 }
638 // Use the name given for the h-feed, or get the title from the html.
639 if ($feed_title !== '') {
640 $feed_title = [['data' => htmlspecialchars($feed_title)]];
641 } elseif ($position = strpos($data, '<title>')) {
642 $start = $position < 200 ? 0 : $position - 200;
643 $check = substr($data, $start, 400);
644 $matches = [];
645 if (preg_match('/<title>(.+)<\/title>/', $check, $matches)) {
646 $feed_title = [['data' => htmlspecialchars($matches[1])]];
647 }
648 }
649 $channel = ['channel' => [['child' => ['' =>
650 ['link' => $link, 'image' => $image, 'title' => $feed_title,
651 'item' => $items]]]]];
652 $rss = [['attribs' => ['' => ['version' => '2.0']],
653 'child' => ['' => $channel]]];
654 $this->data = ['child' => ['' => ['rss' => $rss]]];
655 return true;
656 }
657
658 private static function set_doctype(string $data): string
659 {
660 // Strip DOCTYPE except if containing an [internal subset]
661 $data = preg_replace('/^\\s*<!DOCTYPE\\s[^>\\[\\]]*>\s*/', '', $data) ?? $data;
662 // Declare HTML entities only if no remaining DOCTYPE
663 $doctype = preg_match('/^\\s*<!DOCTYPE\\s/', $data) ? '' : self::declare_html_entities();
664 return $doctype . $data;
665 }
666
667 private static function declare_html_entities(): string
668 {
669 // This is required because the RSS specification says that entity-encoded
670 // html is allowed, but the xml specification says they must be declared.
671 return '<!DOCTYPE rss [ <!ENTITY nbsp "&#x00A0;"> <!ENTITY iexcl "&#x00A1;"> <!ENTITY cent "&#x00A2;"> <!ENTITY pound "&#x00A3;"> <!ENTITY curren "&#x00A4;"> <!ENTITY yen "&#x00A5;"> <!ENTITY brvbar "&#x00A6;"> <!ENTITY sect "&#x00A7;"> <!ENTITY uml "&#x00A8;"> <!ENTITY copy "&#x00A9;"> <!ENTITY ordf "&#x00AA;"> <!ENTITY laquo "&#x00AB;"> <!ENTITY not "&#x00AC;"> <!ENTITY shy "&#x00AD;"> <!ENTITY reg "&#x00AE;"> <!ENTITY macr "&#x00AF;"> <!ENTITY deg "&#x00B0;"> <!ENTITY plusmn "&#x00B1;"> <!ENTITY sup2 "&#x00B2;"> <!ENTITY sup3 "&#x00B3;"> <!ENTITY acute "&#x00B4;"> <!ENTITY micro "&#x00B5;"> <!ENTITY para "&#x00B6;"> <!ENTITY middot "&#x00B7;"> <!ENTITY cedil "&#x00B8;"> <!ENTITY sup1 "&#x00B9;"> <!ENTITY ordm "&#x00BA;"> <!ENTITY raquo "&#x00BB;"> <!ENTITY frac14 "&#x00BC;"> <!ENTITY frac12 "&#x00BD;"> <!ENTITY frac34 "&#x00BE;"> <!ENTITY iquest "&#x00BF;"> <!ENTITY Agrave "&#x00C0;"> <!ENTITY Aacute "&#x00C1;"> <!ENTITY Acirc "&#x00C2;"> <!ENTITY Atilde "&#x00C3;"> <!ENTITY Auml "&#x00C4;"> <!ENTITY Aring "&#x00C5;"> <!ENTITY AElig "&#x00C6;"> <!ENTITY Ccedil "&#x00C7;"> <!ENTITY Egrave "&#x00C8;"> <!ENTITY Eacute "&#x00C9;"> <!ENTITY Ecirc "&#x00CA;"> <!ENTITY Euml "&#x00CB;"> <!ENTITY Igrave "&#x00CC;"> <!ENTITY Iacute "&#x00CD;"> <!ENTITY Icirc "&#x00CE;"> <!ENTITY Iuml "&#x00CF;"> <!ENTITY ETH "&#x00D0;"> <!ENTITY Ntilde "&#x00D1;"> <!ENTITY Ograve "&#x00D2;"> <!ENTITY Oacute "&#x00D3;"> <!ENTITY Ocirc "&#x00D4;"> <!ENTITY Otilde "&#x00D5;"> <!ENTITY Ouml "&#x00D6;"> <!ENTITY times "&#x00D7;"> <!ENTITY Oslash "&#x00D8;"> <!ENTITY Ugrave "&#x00D9;"> <!ENTITY Uacute "&#x00DA;"> <!ENTITY Ucirc "&#x00DB;"> <!ENTITY Uuml "&#x00DC;"> <!ENTITY Yacute "&#x00DD;"> <!ENTITY THORN "&#x00DE;"> <!ENTITY szlig "&#x00DF;"> <!ENTITY agrave "&#x00E0;"> <!ENTITY aacute "&#x00E1;"> <!ENTITY acirc "&#x00E2;"> <!ENTITY atilde "&#x00E3;"> <!ENTITY auml "&#x00E4;"> <!ENTITY aring "&#x00E5;"> <!ENTITY aelig "&#x00E6;"> <!ENTITY ccedil "&#x00E7;"> <!ENTITY egrave "&#x00E8;"> <!ENTITY eacute "&#x00E9;"> <!ENTITY ecirc "&#x00EA;"> <!ENTITY euml "&#x00EB;"> <!ENTITY igrave "&#x00EC;"> <!ENTITY iacute "&#x00ED;"> <!ENTITY icirc "&#x00EE;"> <!ENTITY iuml "&#x00EF;"> <!ENTITY eth "&#x00F0;"> <!ENTITY ntilde "&#x00F1;"> <!ENTITY ograve "&#x00F2;"> <!ENTITY oacute "&#x00F3;"> <!ENTITY ocirc "&#x00F4;"> <!ENTITY otilde "&#x00F5;"> <!ENTITY ouml "&#x00F6;"> <!ENTITY divide "&#x00F7;"> <!ENTITY oslash "&#x00F8;"> <!ENTITY ugrave "&#x00F9;"> <!ENTITY uacute "&#x00FA;"> <!ENTITY ucirc "&#x00FB;"> <!ENTITY uuml "&#x00FC;"> <!ENTITY yacute "&#x00FD;"> <!ENTITY thorn "&#x00FE;"> <!ENTITY yuml "&#x00FF;"> <!ENTITY OElig "&#x0152;"> <!ENTITY oelig "&#x0153;"> <!ENTITY Scaron "&#x0160;"> <!ENTITY scaron "&#x0161;"> <!ENTITY Yuml "&#x0178;"> <!ENTITY fnof "&#x0192;"> <!ENTITY circ "&#x02C6;"> <!ENTITY tilde "&#x02DC;"> <!ENTITY Alpha "&#x0391;"> <!ENTITY Beta "&#x0392;"> <!ENTITY Gamma "&#x0393;"> <!ENTITY Epsilon "&#x0395;"> <!ENTITY Zeta "&#x0396;"> <!ENTITY Eta "&#x0397;"> <!ENTITY Theta "&#x0398;"> <!ENTITY Iota "&#x0399;"> <!ENTITY Kappa "&#x039A;"> <!ENTITY Lambda "&#x039B;"> <!ENTITY Mu "&#x039C;"> <!ENTITY Nu "&#x039D;"> <!ENTITY Xi "&#x039E;"> <!ENTITY Omicron "&#x039F;"> <!ENTITY Pi "&#x03A0;"> <!ENTITY Rho "&#x03A1;"> <!ENTITY Sigma "&#x03A3;"> <!ENTITY Tau "&#x03A4;"> <!ENTITY Upsilon "&#x03A5;"> <!ENTITY Phi "&#x03A6;"> <!ENTITY Chi "&#x03A7;"> <!ENTITY Psi "&#x03A8;"> <!ENTITY Omega "&#x03A9;"> <!ENTITY alpha "&#x03B1;"> <!ENTITY beta "&#x03B2;"> <!ENTITY gamma "&#x03B3;"> <!ENTITY delta "&#x03B4;"> <!ENTITY epsilon "&#x03B5;"> <!ENTITY zeta "&#x03B6;"> <!ENTITY eta "&#x03B7;"> <!ENTITY theta "&#x03B8;"> <!ENTITY iota "&#x03B9;"> <!ENTITY kappa "&#x03BA;"> <!ENTITY lambda "&#x03BB;"> <!ENTITY mu "&#x03BC;"> <!ENTITY nu "&#x03BD;"> <!ENTITY xi "&#x03BE;"> <!ENTITY omicron "&#x03BF;"> <!ENTITY pi "&#x03C0;"> <!ENTITY rho "&#x03C1;"> <!ENTITY sigmaf "&#x03C2;"> <!ENTITY sigma "&#x03C3;"> <!ENTITY tau "&#x03C4;"> <!ENTITY upsilon "&#x03C5;"> <!ENTITY phi "&#x03C6;"> <!ENTITY chi "&#x03C7;"> <!ENTITY psi "&#x03C8;"> <!ENTITY omega "&#x03C9;"> <!ENTITY thetasym "&#x03D1;"> <!ENTITY upsih "&#x03D2;"> <!ENTITY piv "&#x03D6;"> <!ENTITY ensp "&#x2002;"> <!ENTITY emsp "&#x2003;"> <!ENTITY thinsp "&#x2009;"> <!ENTITY zwnj "&#x200C;"> <!ENTITY zwj "&#x200D;"> <!ENTITY lrm "&#x200E;"> <!ENTITY rlm "&#x200F;"> <!ENTITY ndash "&#x2013;"> <!ENTITY mdash "&#x2014;"> <!ENTITY lsquo "&#x2018;"> <!ENTITY rsquo "&#x2019;"> <!ENTITY sbquo "&#x201A;"> <!ENTITY ldquo "&#x201C;"> <!ENTITY rdquo "&#x201D;"> <!ENTITY bdquo "&#x201E;"> <!ENTITY dagger "&#x2020;"> <!ENTITY Dagger "&#x2021;"> <!ENTITY bull "&#x2022;"> <!ENTITY hellip "&#x2026;"> <!ENTITY permil "&#x2030;"> <!ENTITY prime "&#x2032;"> <!ENTITY Prime "&#x2033;"> <!ENTITY lsaquo "&#x2039;"> <!ENTITY rsaquo "&#x203A;"> <!ENTITY oline "&#x203E;"> <!ENTITY frasl "&#x2044;"> <!ENTITY euro "&#x20AC;"> <!ENTITY image "&#x2111;"> <!ENTITY weierp "&#x2118;"> <!ENTITY real "&#x211C;"> <!ENTITY trade "&#x2122;"> <!ENTITY alefsym "&#x2135;"> <!ENTITY larr "&#x2190;"> <!ENTITY uarr "&#x2191;"> <!ENTITY rarr "&#x2192;"> <!ENTITY darr "&#x2193;"> <!ENTITY harr "&#x2194;"> <!ENTITY crarr "&#x21B5;"> <!ENTITY lArr "&#x21D0;"> <!ENTITY uArr "&#x21D1;"> <!ENTITY rArr "&#x21D2;"> <!ENTITY dArr "&#x21D3;"> <!ENTITY hArr "&#x21D4;"> <!ENTITY forall "&#x2200;"> <!ENTITY part "&#x2202;"> <!ENTITY exist "&#x2203;"> <!ENTITY empty "&#x2205;"> <!ENTITY nabla "&#x2207;"> <!ENTITY isin "&#x2208;"> <!ENTITY notin "&#x2209;"> <!ENTITY ni "&#x220B;"> <!ENTITY prod "&#x220F;"> <!ENTITY sum "&#x2211;"> <!ENTITY minus "&#x2212;"> <!ENTITY lowast "&#x2217;"> <!ENTITY radic "&#x221A;"> <!ENTITY prop "&#x221D;"> <!ENTITY infin "&#x221E;"> <!ENTITY ang "&#x2220;"> <!ENTITY and "&#x2227;"> <!ENTITY or "&#x2228;"> <!ENTITY cap "&#x2229;"> <!ENTITY cup "&#x222A;"> <!ENTITY int "&#x222B;"> <!ENTITY there4 "&#x2234;"> <!ENTITY sim "&#x223C;"> <!ENTITY cong "&#x2245;"> <!ENTITY asymp "&#x2248;"> <!ENTITY ne "&#x2260;"> <!ENTITY equiv "&#x2261;"> <!ENTITY le "&#x2264;"> <!ENTITY ge "&#x2265;"> <!ENTITY sub "&#x2282;"> <!ENTITY sup "&#x2283;"> <!ENTITY nsub "&#x2284;"> <!ENTITY sube "&#x2286;"> <!ENTITY supe "&#x2287;"> <!ENTITY oplus "&#x2295;"> <!ENTITY otimes "&#x2297;"> <!ENTITY perp "&#x22A5;"> <!ENTITY sdot "&#x22C5;"> <!ENTITY lceil "&#x2308;"> <!ENTITY rceil "&#x2309;"> <!ENTITY lfloor "&#x230A;"> <!ENTITY rfloor "&#x230B;"> <!ENTITY lang "&#x2329;"> <!ENTITY rang "&#x232A;"> <!ENTITY loz "&#x25CA;"> <!ENTITY spades "&#x2660;"> <!ENTITY clubs "&#x2663;"> <!ENTITY hearts "&#x2665;"> <!ENTITY diams "&#x2666;"> ]>';
672 }
673}
674
675class_alias('SimplePie\Parser', 'SimplePie_Parser');
676
Ui Ux Design – Teachers Night Out https://cardgames4educators.com Wed, 16 Oct 2024 22:24:18 +0000 en-US hourly 1 https://wordpress.org/?v=6.9.4 https://cardgames4educators.com/wp-content/uploads/2024/06/cropped-Card-4-Educators-logo-32x32.png Ui Ux Design – Teachers Night Out https://cardgames4educators.com 32 32 Masters In English How English Speaker https://cardgames4educators.com/masters-in-english-how-english-speaker/ https://cardgames4educators.com/masters-in-english-how-english-speaker/#comments Mon, 27 May 2024 08:54:45 +0000 https://themexriver.com/wp/kadu/?p=1

Erat himenaeos neque id sagittis massa. Hac suscipit pulvinar dignissim platea magnis eu. Don tellus a pharetra inceptos efficitur dui pulvinar. Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent pulvinar odio volutpat parturient. Quisque risus finibus suspendisse mus purus magnis facilisi condimentum consectetur dui. Curae elit suspendisse cursus vehicula.

Turpis taciti class non vel pretium quis pulvinar tempor lobortis nunc. Libero phasellus parturient sapien volutpat malesuada ornare. Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae. Porta est tempor ex eget feugiat vulputate ipsum. Justo nec iaculis habitant diam arcu fermentum.

We offer comprehen sive emplo ment services such as assistance wit employer compliance.Our company is your strategic HR partner as instead of HR. john smithson

Cubilia dignissim sollicitudin rhoncus lacinia maximus. Cras lorem fermentum bibendum pellentesque nisl etiam ligula enim cubilia. Vulputate pede sapien torquent montes tempus malesuada in mattis dis turpis vitae.

Exploring Learning Landscapes in Academic

Feugiat facilisis penatibus pulvinar nunc dictumst donec odio platea habitasse. Lacus porta dolor purus elit ante bibendum tortor netus taciti nullam cubilia. Erat per suspendisse placerat morbi egestas pulvinar bibendum sollicitudin nec. Euismod cubilia eleifend velit himenaeos sodales lectus. Leo maximus cras ac porttitor aliquam torquent.

]]>
https://cardgames4educators.com/masters-in-english-how-english-speaker/feed/ 1