PageRenderTime 123ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 2ms

/third-party/simplepie.php

https://github.com/UCF/TechTransfer-Theme
PHP | 15123 lines | 12746 code | 713 blank | 1664 comment | 1019 complexity | 5498f0e31ca5c00c663d1a60f15474a6 MD5 | raw file
  1. <?php
  2. /**
  3. * SimplePie
  4. *
  5. * A PHP-Based RSS and Atom Feed Framework.
  6. * Takes the hard work out of managing a complete RSS/Atom solution.
  7. *
  8. * Copyright (c) 2004-2010, Ryan Parman, Geoffrey Sneddon, Ryan McCue, and contributors
  9. * All rights reserved.
  10. *
  11. * Redistribution and use in source and binary forms, with or without modification, are
  12. * permitted provided that the following conditions are met:
  13. *
  14. * * Redistributions of source code must retain the above copyright notice, this list of
  15. * conditions and the following disclaimer.
  16. *
  17. * * Redistributions in binary form must reproduce the above copyright notice, this list
  18. * of conditions and the following disclaimer in the documentation and/or other materials
  19. * provided with the distribution.
  20. *
  21. * * Neither the name of the SimplePie Team nor the names of its contributors may be used
  22. * to endorse or promote products derived from this software without specific prior
  23. * written permission.
  24. *
  25. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  26. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  27. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  28. * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  29. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  30. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  31. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  32. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  33. * POSSIBILITY OF SUCH DAMAGE.
  34. *
  35. * @package SimplePie
  36. * @version 1.3-dev
  37. * @copyright 2004-2010 Ryan Parman, Geoffrey Sneddon, Ryan McCue
  38. * @author Ryan Parman
  39. * @author Geoffrey Sneddon
  40. * @author Ryan McCue
  41. * @link http://simplepie.org/ SimplePie
  42. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  43. * @todo phpDoc comments
  44. */
  45. /**
  46. * SimplePie class.
  47. *
  48. * Class for backward compatibility.
  49. *
  50. * @package SimplePie
  51. */
  52. class SimplePie extends SimplePie_Core
  53. {
  54. }
  55. class SimplePie_Author
  56. {
  57. var $name;
  58. var $link;
  59. var $email;
  60. // Constructor, used to input the data
  61. public function __construct($name = null, $link = null, $email = null)
  62. {
  63. $this->name = $name;
  64. $this->link = $link;
  65. $this->email = $email;
  66. }
  67. public function __toString()
  68. {
  69. // There is no $this->data here
  70. return md5(serialize($this));
  71. }
  72. public function get_name()
  73. {
  74. if ($this->name !== null)
  75. {
  76. return $this->name;
  77. }
  78. else
  79. {
  80. return null;
  81. }
  82. }
  83. public function get_link()
  84. {
  85. if ($this->link !== null)
  86. {
  87. return $this->link;
  88. }
  89. else
  90. {
  91. return null;
  92. }
  93. }
  94. public function get_email()
  95. {
  96. if ($this->email !== null)
  97. {
  98. return $this->email;
  99. }
  100. else
  101. {
  102. return null;
  103. }
  104. }
  105. }
  106. interface SimplePie_Cache_Base
  107. {
  108. /**
  109. * Feed cache type
  110. */
  111. const TYPE_FEED = 'spc';
  112. /**
  113. * Image cache type
  114. */
  115. const TYPE_IMAGE = 'spi';
  116. /**
  117. * Create a new cache object
  118. *
  119. * @param string $location Location string (from SimplePie::$cache_location)
  120. * @param string $name Unique ID for the cache
  121. * @param string $type Either TYPE_FEED for SimplePie data, or TYPE_IMAGE for image data
  122. */
  123. public function __construct($location, $name, $type);
  124. /**
  125. * Save data to the cache
  126. *
  127. * @param array|SimplePie $data Data to store in the cache. If passed a SimplePie object, only cache the $data property
  128. */
  129. public function save($data);
  130. /**
  131. * Retrieve the data saved to the cache
  132. *
  133. * @return array Data for SimplePie::$data
  134. */
  135. public function load();
  136. /**
  137. * Retrieve the last modified time for the cache
  138. *
  139. * @return int Timestamp
  140. */
  141. public function mtime();
  142. /**
  143. * Set the last modified time to the current time
  144. *
  145. * @return bool Success status
  146. */
  147. public function touch();
  148. /**
  149. * Remove the cache
  150. *
  151. * @return bool Success status
  152. */
  153. public function unlink();
  154. }
  155. abstract class SimplePie_Cache_DB implements SimplePie_Cache_Base
  156. {
  157. protected static function prepare_simplepie_object_for_cache(&$data)
  158. {
  159. $items = $data->get_items();
  160. $items_by_id = array();
  161. if (!empty($items))
  162. {
  163. foreach ($items as $item)
  164. {
  165. $items_by_id[$item->get_id()] = $item;
  166. }
  167. if (count($items_by_id) !== count($items))
  168. {
  169. $items_by_id = array();
  170. foreach ($items as $item)
  171. {
  172. $items_by_id[$item->get_id(true)] = $item;
  173. }
  174. }
  175. if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  176. {
  177. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  178. }
  179. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  180. {
  181. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  182. }
  183. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  184. {
  185. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  186. }
  187. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
  188. {
  189. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
  190. }
  191. else
  192. {
  193. $channel = null;
  194. }
  195. if ($channel !== null)
  196. {
  197. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
  198. {
  199. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
  200. }
  201. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
  202. {
  203. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
  204. }
  205. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
  206. {
  207. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
  208. }
  209. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
  210. {
  211. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
  212. }
  213. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
  214. {
  215. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
  216. }
  217. }
  218. if (isset($data->data['items']))
  219. {
  220. unset($data->data['items']);
  221. }
  222. if (isset($data->data['ordered_items']))
  223. {
  224. unset($data->data['ordered_items']);
  225. }
  226. }
  227. return array(serialize($data->data), $items_by_id);
  228. }
  229. }
  230. class SimplePie_Cache_File implements SimplePie_Cache_Base
  231. {
  232. protected $location;
  233. protected $filename;
  234. protected $extension;
  235. protected $name;
  236. public function __construct($location, $filename, $extension)
  237. {
  238. $this->location = $location;
  239. $this->filename = $filename;
  240. $this->extension = $extension;
  241. $this->name = "$this->location/$this->filename.$this->extension";
  242. }
  243. public function save($data)
  244. {
  245. if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
  246. {
  247. if (is_a($data, 'SimplePie'))
  248. {
  249. $data = $data->data;
  250. }
  251. $data = serialize($data);
  252. return (bool) file_put_contents($this->name, $data);
  253. }
  254. return false;
  255. }
  256. public function load()
  257. {
  258. if (file_exists($this->name) && is_readable($this->name))
  259. {
  260. return unserialize(file_get_contents($this->name));
  261. }
  262. return false;
  263. }
  264. public function mtime()
  265. {
  266. if (file_exists($this->name))
  267. {
  268. return filemtime($this->name);
  269. }
  270. return false;
  271. }
  272. public function touch()
  273. {
  274. if (file_exists($this->name))
  275. {
  276. return touch($this->name);
  277. }
  278. return false;
  279. }
  280. public function unlink()
  281. {
  282. if (file_exists($this->name))
  283. {
  284. return unlink($this->name);
  285. }
  286. return false;
  287. }
  288. }
  289. class SimplePie_Cache_Memcache implements SimplePie_Cache_Base
  290. {
  291. protected $cache;
  292. protected $options;
  293. protected $name;
  294. public function __construct($url, $filename, $extension)
  295. {
  296. $this->options = array(
  297. 'host' => '127.0.0.1',
  298. 'port' => 11211,
  299. 'extras' => array(
  300. 'timeout' => 3600, // one hour
  301. 'prefix' => 'simplepie_',
  302. ),
  303. );
  304. $this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($url));
  305. $this->name = $this->options['extras']['prefix'] . md5("$filename:$extension");
  306. $this->cache = new Memcache();
  307. $this->cache->addServer($this->options['host'], (int) $this->options['port']);
  308. }
  309. public function save($data)
  310. {
  311. if (is_a($data, 'SimplePie'))
  312. {
  313. $data = $data->data;
  314. }
  315. return $this->cache->set($this->name, serialize($data), MEMCACHE_COMPRESSED, (int) $this->options['extras']['timeout']);
  316. }
  317. public function load()
  318. {
  319. $data = $this->cache->get($this->name);
  320. if ($data !== false)
  321. {
  322. return unserialize($data);
  323. }
  324. return false;
  325. }
  326. public function mtime()
  327. {
  328. $data = $this->cache->get($this->name);
  329. if ($data !== false)
  330. {
  331. // essentially ignore the mtime because Memcache expires on it's own
  332. return time();
  333. }
  334. return false;
  335. }
  336. public function touch()
  337. {
  338. $data = $this->cache->get($this->name);
  339. if ($data !== false)
  340. {
  341. return $this->cache->set($this->name, $data, MEMCACHE_COMPRESSED, (int) $this->duration);
  342. }
  343. return false;
  344. }
  345. public function unlink()
  346. {
  347. return $this->cache->delete($this->name, 0);
  348. }
  349. }
  350. class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
  351. {
  352. protected $mysql;
  353. protected $options;
  354. protected $id;
  355. public function __construct($url, $name, $extension)
  356. {
  357. $this->options = array(
  358. 'user' => null,
  359. 'pass' => null,
  360. 'host' => '127.0.0.1',
  361. 'port' => '3306',
  362. 'path' => '',
  363. 'extras' => array(
  364. 'prefix' => '',
  365. ),
  366. );
  367. $this->options = array_merge_recursive($this->options, SimplePie_Cache::parse_URL($url));
  368. // Path is prefixed with a "/"
  369. $this->options['dbname'] = substr($this->options['path'], 1);
  370. try
  371. {
  372. $this->mysql = new PDO("mysql:dbname={$this->options['dbname']};host={$this->options['host']};port={$this->options['port']}", $this->options['user'], $this->options['pass'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));
  373. }
  374. catch (PDOException $e)
  375. {
  376. $this->mysql = null;
  377. return;
  378. }
  379. $this->id = $name . $extension;
  380. if (!$query = $this->mysql->query('SHOW TABLES'))
  381. {
  382. $this->mysql = null;
  383. return;
  384. }
  385. $db = array();
  386. while ($row = $query->fetchColumn())
  387. {
  388. $db[] = $row;
  389. }
  390. if (!in_array($this->options['extras']['prefix'] . 'cache_data', $db))
  391. {
  392. $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'cache_data` (`id` TEXT CHARACTER SET utf8 NOT NULL, `items` SMALLINT NOT NULL DEFAULT 0, `data` BLOB NOT NULL, `mtime` INT UNSIGNED NOT NULL, UNIQUE (`id`(125)))');
  393. if ($query === false)
  394. {
  395. $this->mysql = null;
  396. }
  397. }
  398. if (!in_array($this->options['extras']['prefix'] . 'items', $db))
  399. {
  400. $query = $this->mysql->exec('CREATE TABLE `' . $this->options['extras']['prefix'] . 'items` (`feed_id` TEXT CHARACTER SET utf8 NOT NULL, `id` TEXT CHARACTER SET utf8 NOT NULL, `data` TEXT CHARACTER SET utf8 NOT NULL, `posted` INT UNSIGNED NOT NULL, INDEX `feed_id` (`feed_id`(125)))');
  401. if ($query === false)
  402. {
  403. $this->mysql = null;
  404. }
  405. }
  406. }
  407. public function save($data)
  408. {
  409. if ($this->mysql === null)
  410. {
  411. return false;
  412. }
  413. if (is_a($data, 'SimplePie'))
  414. {
  415. $data = clone $data;
  416. $prepared = self::prepare_simplepie_object_for_cache($data);
  417. $query = $this->mysql->prepare('SELECT COUNT(*) FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
  418. $query->bindValue(':feed', $this->id);
  419. if ($query->execute())
  420. {
  421. if ($query->fetchColumn() > 0)
  422. {
  423. $items = count($prepared[1]);
  424. if ($items)
  425. {
  426. $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = :items, `data` = :data, `mtime` = :time WHERE `id` = :feed';
  427. $query = $this->mysql->prepare($sql);
  428. $query->bindValue(':items', $items);
  429. }
  430. else
  431. {
  432. $sql = 'UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `data` = :data, `mtime` = :time WHERE `id` = :feed';
  433. $query = $this->mysql->prepare($sql);
  434. }
  435. $query->bindValue(':data', $prepared[0]);
  436. $query->bindValue(':time', time());
  437. $query->bindValue(':feed', $this->id);
  438. if (!$query->execute())
  439. {
  440. return false;
  441. }
  442. }
  443. else
  444. {
  445. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:feed, :count, :data, :time)');
  446. $query->bindValue(':feed', $this->id);
  447. $query->bindValue(':count', count($prepared[1]));
  448. $query->bindValue(':data', $prepared[0]);
  449. $query->bindValue(':time', time());
  450. if (!$query->execute())
  451. {
  452. return false;
  453. }
  454. }
  455. $ids = array_keys($prepared[1]);
  456. if (!empty($ids))
  457. {
  458. foreach ($ids as $id)
  459. {
  460. $database_ids[] = $this->mysql->quote($id);
  461. }
  462. $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `id` = ' . implode(' OR `id` = ', $database_ids) . ' AND `feed_id` = :feed');
  463. $query->bindValue(':feed', $this->id);
  464. if ($query->execute())
  465. {
  466. $existing_ids = array();
  467. while ($row = $query->fetchColumn())
  468. {
  469. $existing_ids[] = $row;
  470. }
  471. $new_ids = array_diff($ids, $existing_ids);
  472. foreach ($new_ids as $new_id)
  473. {
  474. if (!($date = $prepared[1][$new_id]->get_date('U')))
  475. {
  476. $date = time();
  477. }
  478. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(:feed, :id, :data, :date)');
  479. $query->bindValue(':feed', $this->id);
  480. $query->bindValue(':id', $new_id);
  481. $query->bindValue(':data', serialize($prepared[1][$new_id]->data));
  482. $query->bindValue(':date', $date);
  483. if (!$query->execute())
  484. {
  485. return false;
  486. }
  487. }
  488. return true;
  489. }
  490. }
  491. else
  492. {
  493. return true;
  494. }
  495. }
  496. }
  497. else
  498. {
  499. $query = $this->mysql->prepare('SELECT `id` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :feed');
  500. $query->bindValue(':feed', $this->id);
  501. if ($query->execute())
  502. {
  503. if ($query->rowCount() > 0)
  504. {
  505. $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `items` = 0, `data` = :data, `mtime` = :time WHERE `id` = :feed');
  506. $query->bindValue(':data', serialize($data));
  507. $query->bindValue(':time', time());
  508. $query->bindValue(':feed', $this->id);
  509. if ($this->execute())
  510. {
  511. return true;
  512. }
  513. }
  514. else
  515. {
  516. $query = $this->mysql->prepare('INSERT INTO `' . $this->options['extras']['prefix'] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(:id, 0, :data, :time)');
  517. $query->bindValue(':id', $this->id);
  518. $query->bindValue(':data', serialize($data));
  519. $query->bindValue(':time', time());
  520. if ($query->execute())
  521. {
  522. return true;
  523. }
  524. }
  525. }
  526. }
  527. return false;
  528. }
  529. public function load()
  530. {
  531. if ($this->mysql === null)
  532. {
  533. return false;
  534. }
  535. $query = $this->mysql->prepare('SELECT `items`, `data` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  536. $query->bindValue(':id', $this->id);
  537. if ($query->execute() && ($row = $query->fetch()))
  538. {
  539. $data = unserialize($row[1]);
  540. if (isset($this->options['items'][0]))
  541. {
  542. $items = (int) $this->options['items'][0];
  543. }
  544. else
  545. {
  546. $items = (int) $row[0];
  547. }
  548. if ($items !== 0)
  549. {
  550. if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  551. {
  552. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  553. }
  554. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  555. {
  556. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  557. }
  558. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  559. {
  560. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  561. }
  562. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
  563. {
  564. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
  565. }
  566. else
  567. {
  568. $feed = null;
  569. }
  570. if ($feed !== null)
  571. {
  572. $sql = 'SELECT `data` FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :feed ORDER BY `posted` DESC';
  573. if ($items > 0)
  574. {
  575. $sql .= ' LIMIT ' . $items;
  576. }
  577. $query = $this->mysql->prepare($sql);
  578. $query->bindValue(':feed', $this->id);
  579. if ($query->execute())
  580. {
  581. while ($row = $query->fetchColumn())
  582. {
  583. $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row);
  584. }
  585. }
  586. else
  587. {
  588. return false;
  589. }
  590. }
  591. }
  592. return $data;
  593. }
  594. return false;
  595. }
  596. public function mtime()
  597. {
  598. if ($this->mysql === null)
  599. {
  600. return false;
  601. }
  602. $query = $this->mysql->prepare('SELECT `mtime` FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  603. $query->bindValue(':id', $this->id);
  604. if ($query->execute() && ($time = $query->fetchColumn()))
  605. {
  606. return $time;
  607. }
  608. else
  609. {
  610. return false;
  611. }
  612. }
  613. public function touch()
  614. {
  615. if ($this->mysql === null)
  616. {
  617. return false;
  618. }
  619. $query = $this->mysql->prepare('UPDATE `' . $this->options['extras']['prefix'] . 'cache_data` SET `mtime` = :time WHERE `id` = :id');
  620. $query->bindValue(':time', time());
  621. $query->bindValue(':id', $this->id);
  622. if ($query->execute() && $query->rowCount() > 0)
  623. {
  624. return true;
  625. }
  626. else
  627. {
  628. return false;
  629. }
  630. }
  631. public function unlink()
  632. {
  633. if ($this->mysql === null)
  634. {
  635. return false;
  636. }
  637. $query = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'cache_data` WHERE `id` = :id');
  638. $query->bindValue(':id', $this->id);
  639. $query2 = $this->mysql->prepare('DELETE FROM `' . $this->options['extras']['prefix'] . 'items` WHERE `feed_id` = :id');
  640. $query2->bindValue(':id', $this->id);
  641. if ($query->execute() && $query2->execute())
  642. {
  643. return true;
  644. }
  645. else
  646. {
  647. return false;
  648. }
  649. }
  650. }
  651. class SimplePie_Cache
  652. {
  653. /**
  654. * Cache handler classes
  655. *
  656. * These receive 3 parameters to their constructor, as documented in
  657. * {@see register()}
  658. * @var array
  659. */
  660. protected static $handlers = array(
  661. 'mysql' => 'SimplePie_Cache_MySQL',
  662. 'memcache' => 'SimplePie_Cache_Memcache',
  663. );
  664. /**
  665. * Don't call the constructor. Please.
  666. */
  667. private function __construct() { }
  668. /**
  669. * Create a new SimplePie_Cache object
  670. */
  671. public static function create($location, $filename, $extension)
  672. {
  673. $type = explode(':', $location, 2);
  674. $type = $type[0];
  675. if (!empty(self::$handlers[$type]))
  676. {
  677. $class = self::$handlers[$type];
  678. return new $class($location, $filename, $extension);
  679. }
  680. return new SimplePie_Cache_File($location, $filename, $extension);
  681. }
  682. /**
  683. * Register a handler
  684. *
  685. * @param string $type DSN type to register for
  686. * @param string $class Name of handler class. Must implement SimplePie_Cache_Base
  687. */
  688. public static function register($type, $class)
  689. {
  690. self::$handlers[$type] = $class;
  691. }
  692. /**
  693. * Parse a URL into an array
  694. *
  695. * @param string $url
  696. * @return array
  697. */
  698. public static function parse_URL($url)
  699. {
  700. $params = parse_url($url);
  701. $params['extras'] = array();
  702. if (isset($params['query']))
  703. {
  704. parse_str($params['query'], $params['extras']);
  705. }
  706. return $params;
  707. }
  708. }
  709. class SimplePie_Caption
  710. {
  711. var $type;
  712. var $lang;
  713. var $startTime;
  714. var $endTime;
  715. var $text;
  716. // Constructor, used to input the data
  717. public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
  718. {
  719. $this->type = $type;
  720. $this->lang = $lang;
  721. $this->startTime = $startTime;
  722. $this->endTime = $endTime;
  723. $this->text = $text;
  724. }
  725. public function __toString()
  726. {
  727. // There is no $this->data here
  728. return md5(serialize($this));
  729. }
  730. public function get_endtime()
  731. {
  732. if ($this->endTime !== null)
  733. {
  734. return $this->endTime;
  735. }
  736. else
  737. {
  738. return null;
  739. }
  740. }
  741. public function get_language()
  742. {
  743. if ($this->lang !== null)
  744. {
  745. return $this->lang;
  746. }
  747. else
  748. {
  749. return null;
  750. }
  751. }
  752. public function get_starttime()
  753. {
  754. if ($this->startTime !== null)
  755. {
  756. return $this->startTime;
  757. }
  758. else
  759. {
  760. return null;
  761. }
  762. }
  763. public function get_text()
  764. {
  765. if ($this->text !== null)
  766. {
  767. return $this->text;
  768. }
  769. else
  770. {
  771. return null;
  772. }
  773. }
  774. public function get_type()
  775. {
  776. if ($this->type !== null)
  777. {
  778. return $this->type;
  779. }
  780. else
  781. {
  782. return null;
  783. }
  784. }
  785. }
  786. class SimplePie_Category
  787. {
  788. var $term;
  789. var $scheme;
  790. var $label;
  791. // Constructor, used to input the data
  792. public function __construct($term = null, $scheme = null, $label = null)
  793. {
  794. $this->term = $term;
  795. $this->scheme = $scheme;
  796. $this->label = $label;
  797. }
  798. public function __toString()
  799. {
  800. // There is no $this->data here
  801. return md5(serialize($this));
  802. }
  803. public function get_term()
  804. {
  805. if ($this->term !== null)
  806. {
  807. return $this->term;
  808. }
  809. else
  810. {
  811. return null;
  812. }
  813. }
  814. public function get_scheme()
  815. {
  816. if ($this->scheme !== null)
  817. {
  818. return $this->scheme;
  819. }
  820. else
  821. {
  822. return null;
  823. }
  824. }
  825. public function get_label()
  826. {
  827. if ($this->label !== null)
  828. {
  829. return $this->label;
  830. }
  831. else
  832. {
  833. return $this->get_term();
  834. }
  835. }
  836. }
  837. /**
  838. * Content-type sniffing
  839. *
  840. * Based on the rules in http://tools.ietf.org/html/draft-abarth-mime-sniff-06
  841. * @package SimplePie
  842. */
  843. class SimplePie_Content_Type_Sniffer
  844. {
  845. /**
  846. * File object
  847. *
  848. * @var SimplePie_File
  849. */
  850. var $file;
  851. /**
  852. * Create an instance of the class with the input file
  853. *
  854. * @param SimplePie_Content_Type_Sniffer $file Input file
  855. */
  856. public function __construct($file)
  857. {
  858. $this->file = $file;
  859. }
  860. /**
  861. * Get the Content-Type of the specified file
  862. *
  863. * @return string Actual Content-Type
  864. */
  865. public function get_type()
  866. {
  867. if (isset($this->file->headers['content-type']))
  868. {
  869. if (!isset($this->file->headers['content-encoding'])
  870. && ($this->file->headers['content-type'] === 'text/plain'
  871. || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
  872. || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'
  873. || $this->file->headers['content-type'] === 'text/plain; charset=UTF-8'))
  874. {
  875. return $this->text_or_binary();
  876. }
  877. if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
  878. {
  879. $official = substr($this->file->headers['content-type'], 0, $pos);
  880. }
  881. else
  882. {
  883. $official = $this->file->headers['content-type'];
  884. }
  885. $official = trim(strtolower($official));
  886. if ($official === 'unknown/unknown'
  887. || $official === 'application/unknown')
  888. {
  889. return $this->unknown();
  890. }
  891. elseif (substr($official, -4) === '+xml'
  892. || $official === 'text/xml'
  893. || $official === 'application/xml')
  894. {
  895. return $official;
  896. }
  897. elseif (substr($official, 0, 6) === 'image/')
  898. {
  899. if ($return = $this->image())
  900. {
  901. return $return;
  902. }
  903. else
  904. {
  905. return $official;
  906. }
  907. }
  908. elseif ($official === 'text/html')
  909. {
  910. return $this->feed_or_html();
  911. }
  912. else
  913. {
  914. return $official;
  915. }
  916. }
  917. else
  918. {
  919. return $this->unknown();
  920. }
  921. }
  922. /**
  923. * Sniff text or binary
  924. *
  925. * @return string Actual Content-Type
  926. */
  927. public function text_or_binary()
  928. {
  929. if (substr($this->file->body, 0, 2) === "\xFE\xFF"
  930. || substr($this->file->body, 0, 2) === "\xFF\xFE"
  931. || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
  932. || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
  933. {
  934. return 'text/plain';
  935. }
  936. elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
  937. {
  938. return 'application/octect-stream';
  939. }
  940. else
  941. {
  942. return 'text/plain';
  943. }
  944. }
  945. /**
  946. * Sniff unknown
  947. *
  948. * @return string Actual Content-Type
  949. */
  950. public function unknown()
  951. {
  952. $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
  953. if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
  954. || strtolower(substr($this->file->body, $ws, 5)) === '<html'
  955. || strtolower(substr($this->file->body, $ws, 7)) === '<script')
  956. {
  957. return 'text/html';
  958. }
  959. elseif (substr($this->file->body, 0, 5) === '%PDF-')
  960. {
  961. return 'application/pdf';
  962. }
  963. elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
  964. {
  965. return 'application/postscript';
  966. }
  967. elseif (substr($this->file->body, 0, 6) === 'GIF87a'
  968. || substr($this->file->body, 0, 6) === 'GIF89a')
  969. {
  970. return 'image/gif';
  971. }
  972. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  973. {
  974. return 'image/png';
  975. }
  976. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  977. {
  978. return 'image/jpeg';
  979. }
  980. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  981. {
  982. return 'image/bmp';
  983. }
  984. elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
  985. {
  986. return 'image/vnd.microsoft.icon';
  987. }
  988. else
  989. {
  990. return $this->text_or_binary();
  991. }
  992. }
  993. /**
  994. * Sniff images
  995. *
  996. * @return string Actual Content-Type
  997. */
  998. public function image()
  999. {
  1000. if (substr($this->file->body, 0, 6) === 'GIF87a'
  1001. || substr($this->file->body, 0, 6) === 'GIF89a')
  1002. {
  1003. return 'image/gif';
  1004. }
  1005. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  1006. {
  1007. return 'image/png';
  1008. }
  1009. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  1010. {
  1011. return 'image/jpeg';
  1012. }
  1013. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  1014. {
  1015. return 'image/bmp';
  1016. }
  1017. elseif (substr($this->file->body, 0, 4) === "\x00\x00\x01\x00")
  1018. {
  1019. return 'image/vnd.microsoft.icon';
  1020. }
  1021. else
  1022. {
  1023. return false;
  1024. }
  1025. }
  1026. /**
  1027. * Sniff HTML
  1028. *
  1029. * @return string Actual Content-Type
  1030. */
  1031. public function feed_or_html()
  1032. {
  1033. $len = strlen($this->file->body);
  1034. $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
  1035. while ($pos < $len)
  1036. {
  1037. switch ($this->file->body[$pos])
  1038. {
  1039. case "\x09":
  1040. case "\x0A":
  1041. case "\x0D":
  1042. case "\x20":
  1043. $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
  1044. continue 2;
  1045. case '<':
  1046. $pos++;
  1047. break;
  1048. default:
  1049. return 'text/html';
  1050. }
  1051. if (substr($this->file->body, $pos, 3) === '!--')
  1052. {
  1053. $pos += 3;
  1054. if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
  1055. {
  1056. $pos += 3;
  1057. }
  1058. else
  1059. {
  1060. return 'text/html';
  1061. }
  1062. }
  1063. elseif (substr($this->file->body, $pos, 1) === '!')
  1064. {
  1065. if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
  1066. {
  1067. $pos++;
  1068. }
  1069. else
  1070. {
  1071. return 'text/html';
  1072. }
  1073. }
  1074. elseif (substr($this->file->body, $pos, 1) === '?')
  1075. {
  1076. if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
  1077. {
  1078. $pos += 2;
  1079. }
  1080. else
  1081. {
  1082. return 'text/html';
  1083. }
  1084. }
  1085. elseif (substr($this->file->body, $pos, 3) === 'rss'
  1086. || substr($this->file->body, $pos, 7) === 'rdf:RDF')
  1087. {
  1088. return 'application/rss+xml';
  1089. }
  1090. elseif (substr($this->file->body, $pos, 4) === 'feed')
  1091. {
  1092. return 'application/atom+xml';
  1093. }
  1094. else
  1095. {
  1096. return 'text/html';
  1097. }
  1098. }
  1099. return 'text/html';
  1100. }
  1101. }
  1102. class SimplePie_Copyright
  1103. {
  1104. var $url;
  1105. var $label;
  1106. // Constructor, used to input the data
  1107. public function __construct($url = null, $label = null)
  1108. {
  1109. $this->url = $url;
  1110. $this->label = $label;
  1111. }
  1112. public function __toString()
  1113. {
  1114. // There is no $this->data here
  1115. return md5(serialize($this));
  1116. }
  1117. public function get_url()
  1118. {
  1119. if ($this->url !== null)
  1120. {
  1121. return $this->url;
  1122. }
  1123. else
  1124. {
  1125. return null;
  1126. }
  1127. }
  1128. public function get_attribution()
  1129. {
  1130. if ($this->label !== null)
  1131. {
  1132. return $this->label;
  1133. }
  1134. else
  1135. {
  1136. return null;
  1137. }
  1138. }
  1139. }
  1140. /**
  1141. * SimplePie Name
  1142. */
  1143. define('SIMPLEPIE_NAME', 'SimplePie');
  1144. /**
  1145. * SimplePie Version
  1146. */
  1147. define('SIMPLEPIE_VERSION', '1.3-dev');
  1148. /**
  1149. * SimplePie Build
  1150. * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::get_build() only every load of simplepie.inc)
  1151. */
  1152. define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::get_build()));
  1153. /**
  1154. * SimplePie Website URL
  1155. */
  1156. define('SIMPLEPIE_URL', 'http://simplepie.org');
  1157. /**
  1158. * SimplePie Useragent
  1159. * @see SimplePie::set_useragent()
  1160. */
  1161. define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
  1162. /**
  1163. * SimplePie Linkback
  1164. */
  1165. define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
  1166. /**
  1167. * No Autodiscovery
  1168. * @see SimplePie::set_autodiscovery_level()
  1169. */
  1170. define('SIMPLEPIE_LOCATOR_NONE', 0);
  1171. /**
  1172. * Feed Link Element Autodiscovery
  1173. * @see SimplePie::set_autodiscovery_level()
  1174. */
  1175. define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
  1176. /**
  1177. * Local Feed Extension Autodiscovery
  1178. * @see SimplePie::set_autodiscovery_level()
  1179. */
  1180. define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
  1181. /**
  1182. * Local Feed Body Autodiscovery
  1183. * @see SimplePie::set_autodiscovery_level()
  1184. */
  1185. define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
  1186. /**
  1187. * Remote Feed Extension Autodiscovery
  1188. * @see SimplePie::set_autodiscovery_level()
  1189. */
  1190. define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
  1191. /**
  1192. * Remote Feed Body Autodiscovery
  1193. * @see SimplePie::set_autodiscovery_level()
  1194. */
  1195. define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
  1196. /**
  1197. * All Feed Autodiscovery
  1198. * @see SimplePie::set_autodiscovery_level()
  1199. */
  1200. define('SIMPLEPIE_LOCATOR_ALL', 31);
  1201. /**
  1202. * No known feed type
  1203. */
  1204. define('SIMPLEPIE_TYPE_NONE', 0);
  1205. /**
  1206. * RSS 0.90
  1207. */
  1208. define('SIMPLEPIE_TYPE_RSS_090', 1);
  1209. /**
  1210. * RSS 0.91 (Netscape)
  1211. */
  1212. define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
  1213. /**
  1214. * RSS 0.91 (Userland)
  1215. */
  1216. define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
  1217. /**
  1218. * RSS 0.91 (both Netscape and Userland)
  1219. */
  1220. define('SIMPLEPIE_TYPE_RSS_091', 6);
  1221. /**
  1222. * RSS 0.92
  1223. */
  1224. define('SIMPLEPIE_TYPE_RSS_092', 8);
  1225. /**
  1226. * RSS 0.93
  1227. */
  1228. define('SIMPLEPIE_TYPE_RSS_093', 16);
  1229. /**
  1230. * RSS 0.94
  1231. */
  1232. define('SIMPLEPIE_TYPE_RSS_094', 32);
  1233. /**
  1234. * RSS 1.0
  1235. */
  1236. define('SIMPLEPIE_TYPE_RSS_10', 64);
  1237. /**
  1238. * RSS 2.0
  1239. */
  1240. define('SIMPLEPIE_TYPE_RSS_20', 128);
  1241. /**
  1242. * RDF-based RSS
  1243. */
  1244. define('SIMPLEPIE_TYPE_RSS_RDF', 65);
  1245. /**
  1246. * Non-RDF-based RSS (truly intended as syndication format)
  1247. */
  1248. define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
  1249. /**
  1250. * All RSS
  1251. */
  1252. define('SIMPLEPIE_TYPE_RSS_ALL', 255);
  1253. /**
  1254. * Atom 0.3
  1255. */
  1256. define('SIMPLEPIE_TYPE_ATOM_03', 256);
  1257. /**
  1258. * Atom 1.0
  1259. */
  1260. define('SIMPLEPIE_TYPE_ATOM_10', 512);
  1261. /**
  1262. * All Atom
  1263. */
  1264. define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
  1265. /**
  1266. * All feed types
  1267. */
  1268. define('SIMPLEPIE_TYPE_ALL', 1023);
  1269. /**
  1270. * No construct
  1271. */
  1272. define('SIMPLEPIE_CONSTRUCT_NONE', 0);
  1273. /**
  1274. * Text construct
  1275. */
  1276. define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
  1277. /**
  1278. * HTML construct
  1279. */
  1280. define('SIMPLEPIE_CONSTRUCT_HTML', 2);
  1281. /**
  1282. * XHTML construct
  1283. */
  1284. define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
  1285. /**
  1286. * base64-encoded construct
  1287. */
  1288. define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
  1289. /**
  1290. * IRI construct
  1291. */
  1292. define('SIMPLEPIE_CONSTRUCT_IRI', 16);
  1293. /**
  1294. * A construct that might be HTML
  1295. */
  1296. define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
  1297. /**
  1298. * All constructs
  1299. */
  1300. define('SIMPLEPIE_CONSTRUCT_ALL', 63);
  1301. /**
  1302. * Don't change case
  1303. */
  1304. define('SIMPLEPIE_SAME_CASE', 1);
  1305. /**
  1306. * Change to lowercase
  1307. */
  1308. define('SIMPLEPIE_LOWERCASE', 2);
  1309. /**
  1310. * Change to uppercase
  1311. */
  1312. define('SIMPLEPIE_UPPERCASE', 4);
  1313. /**
  1314. * PCRE for HTML attributes
  1315. */
  1316. define('SIMPLEPIE_PCRE_HTML_ATTRIBUTE', '((?:[\x09\x0A\x0B\x0C\x0D\x20]+[^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?)*)[\x09\x0A\x0B\x0C\x0D\x20]*');
  1317. /**
  1318. * PCRE for XML attributes
  1319. */
  1320. define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
  1321. /**
  1322. * XML Namespace
  1323. */
  1324. define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
  1325. /**
  1326. * Atom 1.0 Namespace
  1327. */
  1328. define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
  1329. /**
  1330. * Atom 0.3 Namespace
  1331. */
  1332. define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
  1333. /**
  1334. * RDF Namespace
  1335. */
  1336. define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  1337. /**
  1338. * RSS 0.90 Namespace
  1339. */
  1340. define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
  1341. /**
  1342. * RSS 1.0 Namespace
  1343. */
  1344. define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
  1345. /**
  1346. * RSS 1.0 Content Module Namespace
  1347. */
  1348. define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
  1349. /**
  1350. * RSS 2.0 Namespace
  1351. * (Stupid, I know, but I'm certain it will confuse people less with support.)
  1352. */
  1353. define('SIMPLEPIE_NAMESPACE_RSS_20', '');
  1354. /**
  1355. * DC 1.0 Namespace
  1356. */
  1357. define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
  1358. /**
  1359. * DC 1.1 Namespace
  1360. */
  1361. define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
  1362. /**
  1363. * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
  1364. */
  1365. define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
  1366. /**
  1367. * GeoRSS Namespace
  1368. */
  1369. define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
  1370. /**
  1371. * Media RSS Namespace
  1372. */
  1373. define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
  1374. /**
  1375. * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
  1376. */
  1377. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
  1378. /**
  1379. * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
  1380. */
  1381. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
  1382. /**
  1383. * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
  1384. */
  1385. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
  1386. /**
  1387. * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
  1388. */
  1389. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
  1390. /**
  1391. * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
  1392. */
  1393. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
  1394. /**
  1395. * iTunes RSS Namespace
  1396. */
  1397. define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
  1398. /**
  1399. * XHTML Namespace
  1400. */
  1401. define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  1402. /**
  1403. * IANA Link Relations Registry
  1404. */
  1405. define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
  1406. /**
  1407. * Whether we're running on PHP5
  1408. */
  1409. define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
  1410. /**
  1411. * No file source
  1412. */
  1413. define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
  1414. /**
  1415. * Remote file source
  1416. */
  1417. define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
  1418. /**
  1419. * Local file source
  1420. */
  1421. define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
  1422. /**
  1423. * fsockopen() file source
  1424. */
  1425. define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
  1426. /**
  1427. * cURL file source
  1428. */
  1429. define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
  1430. /**
  1431. * file_get_contents() file source
  1432. */
  1433. define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  1434. /**
  1435. * SimplePie
  1436. *
  1437. * @package SimplePie
  1438. */
  1439. class SimplePie_Core
  1440. {
  1441. /**
  1442. * @var array Raw data
  1443. * @access private
  1444. */
  1445. public $data = array();
  1446. /**
  1447. * @var mixed Error string
  1448. * @access private
  1449. */
  1450. public $error;
  1451. /**
  1452. * @var object Instance of SimplePie_Sanitize (or other class)
  1453. * @see SimplePie::set_sanitize_class()
  1454. * @access private
  1455. */
  1456. public $sanitize;
  1457. /**
  1458. * @var string SimplePie Useragent
  1459. * @see SimplePie::set_useragent()
  1460. * @access private
  1461. */
  1462. public $useragent = SIMPLEPIE_USERAGENT;
  1463. /**
  1464. * @var string Feed URL
  1465. * @see SimplePie::set_feed_url()
  1466. * @access private
  1467. */
  1468. public $feed_url;
  1469. /**
  1470. * @var object Instance of SimplePie_File to use as a feed
  1471. * @see SimplePie::set_file()
  1472. * @access private
  1473. */
  1474. public $file;
  1475. /**
  1476. * @var string Raw feed data
  1477. * @see SimplePie::set_raw_data()
  1478. * @access private
  1479. */
  1480. public $raw_data;
  1481. /**
  1482. * @var int Timeout for fetching remote files
  1483. * @see SimplePie::set_timeout()
  1484. * @access private
  1485. */
  1486. public $timeout = 10;
  1487. /**
  1488. * @var bool Forces fsockopen() to be used for remote files instead
  1489. * of cURL, even if a new enough version is installed
  1490. * @see SimplePie::force_fsockopen()
  1491. * @access private
  1492. */
  1493. public $force_fsockopen = false;
  1494. /**
  1495. * @var bool Force the given data/URL to be treated as a feed no matter what
  1496. * it appears like
  1497. * @see SimplePie::force_feed()
  1498. * @access private
  1499. */
  1500. public $force_feed = false;
  1501. /**
  1502. * @var bool Enable/Disable XML dump
  1503. * @see SimplePie::enable_xml_dump()
  1504. * @access private
  1505. */
  1506. public $xml_dump = false;
  1507. /**
  1508. * @var bool Enable/Disable Caching
  1509. * @see SimplePie::enable_cache()
  1510. * @access private
  1511. */
  1512. public $cache = true;
  1513. /**
  1514. * @var int Cache duration (in seconds)
  1515. * @see SimplePie::set_cache_duration()
  1516. * @access private
  1517. */
  1518. public $cache_duration = 3600;
  1519. /**
  1520. * @var int Auto-discovery cache duration (in seconds)
  1521. * @see SimplePie::set_autodiscovery_cache_duration()
  1522. * @access private
  1523. */
  1524. public $autodiscovery_cache_duration = 604800; // 7 Days.
  1525. /**
  1526. * @var string Cache location (relative to executing script)
  1527. * @see SimplePie::set_cache_location()
  1528. * @access private
  1529. */
  1530. public $cache_location = './cache';
  1531. /**
  1532. * @var string Function that creates the cache filename
  1533. * @see SimplePie::set_cache_name_function()
  1534. * @access private
  1535. */
  1536. public $cache_name_function = 'md5';
  1537. /**
  1538. * @var bool Reorder feed by date descending
  1539. * @see SimplePie::enable_order_by_date()
  1540. * @access private
  1541. */
  1542. public $order_by_date = true;
  1543. /**
  1544. * @var mixed Force input encoding to be set to the follow value
  1545. * (false, or anything type-cast to false, disables this feature)
  1546. * @see SimplePie::set_input_encoding()
  1547. * @access private
  1548. */
  1549. public $input_encoding = false;
  1550. /**
  1551. * @var int Feed Autodiscovery Level
  1552. * @see SimplePie::set_autodiscovery_level()
  1553. * @access private
  1554. */
  1555. public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
  1556. /**
  1557. * @var string Class used for caching feeds
  1558. * @see SimplePie::set_cache_class()
  1559. * @access private
  1560. */
  1561. public $cache_class = 'SimplePie_Cache';
  1562. /**
  1563. * @var string Class used for locating feeds
  1564. * @see SimplePie::set_locator_class()
  1565. * @access private
  1566. */
  1567. public $locator_class = 'SimplePie_Locator';
  1568. /**
  1569. * @var string Class used for parsing feeds
  1570. * @see SimplePie::set_parser_class()
  1571. * @access private
  1572. */
  1573. public $parser_class = 'SimplePie_Parser';
  1574. /**
  1575. * @var string Class used for fetching feeds
  1576. * @see SimplePie::set_file_class()
  1577. * @access private
  1578. */
  1579. public $file_class = 'SimplePie_File';
  1580. /**
  1581. * @var string Class used for items
  1582. * @see SimplePie::set_item_class()
  1583. * @access private
  1584. */
  1585. public $item_class = 'SimplePie_Item';
  1586. /**
  1587. * @var string Class used for authors
  1588. * @see SimplePie::set_author_class()
  1589. * @access private
  1590. */
  1591. public $author_class = 'SimplePie_Author';
  1592. /**
  1593. * @var string Class used for categories
  1594. * @see SimplePie::set_category_class()
  1595. * @access private
  1596. */
  1597. public $category_class = 'SimplePie_Category';
  1598. /**
  1599. * @var string Class used for enclosures
  1600. * @see SimplePie::set_enclosures_class()
  1601. * @access private
  1602. */
  1603. public $enclosure_class = 'SimplePie_Enclosure';
  1604. /**
  1605. * @var string Class used for Media RSS <media:text> captions
  1606. * @see SimplePie::set_caption_class()
  1607. * @access private
  1608. */
  1609. public $caption_class = 'SimplePie_Caption';
  1610. /**
  1611. * @var string Class used for Media RSS <media:copyright>
  1612. * @see SimplePie::set_copyright_class()
  1613. * @access private
  1614. */
  1615. public $copyright_class = 'SimplePie_Copyright';
  1616. /**
  1617. * @var string Class used for Media RSS <media:credit>
  1618. * @see SimplePie::set_credit_class()
  1619. * @access private
  1620. */
  1621. public $credit_class = 'SimplePie_Credit';
  1622. /**
  1623. * @var string Class used for Media RSS <media:rating>
  1624. * @see SimplePie::set_rating_class()
  1625. * @access private
  1626. */
  1627. public $rating_class = 'SimplePie_Rating';
  1628. /**
  1629. * @var string Class used for Media RSS <media:restriction>
  1630. * @see SimplePie::set_restriction_class()
  1631. * @access private
  1632. */
  1633. public $restriction_class = 'SimplePie_Restriction';
  1634. /**
  1635. * @var string Class used for content-type sniffing
  1636. * @see SimplePie::set_content_type_sniffer_class()
  1637. * @access private
  1638. */
  1639. public $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  1640. /**
  1641. * @var string Class used for item sources.
  1642. * @see SimplePie::set_source_class()
  1643. * @access private
  1644. */
  1645. public $source_class = 'SimplePie_Source';
  1646. /**
  1647. * @var int Maximum number of feeds to check with autodiscovery
  1648. * @see SimplePie::set_max_checked_feeds()
  1649. * @access private
  1650. */
  1651. public $max_checked_feeds = 10;
  1652. /**
  1653. * @var array All the feeds found during the autodiscovery process
  1654. * @see SimplePie::get_all_discovered_feeds()
  1655. * @access private
  1656. */
  1657. public $all_discovered_feeds = array();
  1658. /**
  1659. * @var string Web-accessible path to the handler_image.php file.
  1660. * @see SimplePie::set_image_handler()
  1661. * @access private
  1662. */
  1663. public $image_handler = '';
  1664. /**
  1665. * @var array Stores the URLs when multiple feeds are being initialized.
  1666. * @see SimplePie::set_feed_url()
  1667. * @access private
  1668. */
  1669. public $multifeed_url = array();
  1670. /**
  1671. * @var array Stores SimplePie objects when multiple feeds initialized.
  1672. * @access private
  1673. */
  1674. public $multifeed_objects = array();
  1675. /**
  1676. * @var array Stores the get_object_vars() array for use with multifeeds.
  1677. * @see SimplePie::set_feed_url()
  1678. * @access private
  1679. */
  1680. public $config_settings = null;
  1681. /**
  1682. * @var integer Stores the number of items to return per-feed with multifeeds.
  1683. * @see SimplePie::set_item_limit()
  1684. * @access private
  1685. */
  1686. public $item_limit = 0;
  1687. /**
  1688. * @var array Stores the default attributes to be stripped by strip_attributes().
  1689. * @see SimplePie::strip_attributes()
  1690. * @access private
  1691. */
  1692. public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  1693. /**
  1694. * @var array Stores the default tags to be stripped by strip_htmltags().
  1695. * @see SimplePie::strip_htmltags()
  1696. * @access private
  1697. */
  1698. public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  1699. /**
  1700. * The SimplePie class contains feed level data and options
  1701. *
  1702. * There are two ways that you can create a new SimplePie object. The first
  1703. * is by passing a feed URL as a parameter to the SimplePie constructor
  1704. * (as well as optionally setting the cache location and cache expiry). This
  1705. * will initialise the whole feed with all of the default settings, and you
  1706. * can begin accessing methods and properties immediately.
  1707. *
  1708. * The second way is to create the SimplePie object with no parameters
  1709. * at all. This will enable you to set configuration options. After setting
  1710. * them, you must initialise the feed using $feed->init(). At that point the
  1711. * object's methods and properties will be available to you. This format is
  1712. * what is used throughout this documentation.
  1713. *
  1714. * @access public
  1715. * @since 1.0 Preview Release
  1716. */
  1717. public function __construct()
  1718. {
  1719. if (version_compare(PHP_VERSION, '5.0', '<'))
  1720. {
  1721. trigger_error('PHP 4.x is no longer supported. Please upgrade to PHP 5.2 or newer.');
  1722. die();
  1723. }
  1724. // Other objects, instances created here so we can set options on them
  1725. $this->sanitize = new SimplePie_Sanitize();
  1726. if (func_num_args() > 0)
  1727. {
  1728. trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
  1729. }
  1730. }
  1731. /**
  1732. * Used for converting object to a string
  1733. */
  1734. public function __toString()
  1735. {
  1736. return md5(serialize($this->data));
  1737. }
  1738. /**
  1739. * Remove items that link back to this before destroying this object
  1740. */
  1741. public function __destruct()
  1742. {
  1743. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  1744. {
  1745. if (!empty($this->data['items']))
  1746. {
  1747. foreach ($this->data['items'] as $item)
  1748. {
  1749. $item->__destruct();
  1750. }
  1751. unset($item, $this->data['items']);
  1752. }
  1753. if (!empty($this->data['ordered_items']))
  1754. {
  1755. foreach ($this->data['ordered_items'] as $item)
  1756. {
  1757. $item->__destruct();
  1758. }
  1759. unset($item, $this->data['ordered_items']);
  1760. }
  1761. }
  1762. }
  1763. /**
  1764. * Force the given data/URL to be treated as a feed no matter what it
  1765. * appears like
  1766. *
  1767. * @access public
  1768. * @since 1.1
  1769. * @param bool $enable Force the given data/URL to be treated as a feed
  1770. */
  1771. public function force_feed($enable = false)
  1772. {
  1773. $this->force_feed = (bool) $enable;
  1774. }
  1775. /**
  1776. * This is the URL of the feed you want to parse.
  1777. *
  1778. * This allows you to enter the URL of the feed you want to parse, or the
  1779. * website you want to try to use auto-discovery on. This takes priority
  1780. * over any set raw data.
  1781. *
  1782. * You can set multiple feeds to mash together by passing an array instead
  1783. * of a string for the $url. Remember that with each additional feed comes
  1784. * additional processing and resources.
  1785. *
  1786. * @access public
  1787. * @since 1.0 Preview Release
  1788. * @param mixed $url This is the URL (or array of URLs) that you want to parse.
  1789. * @see SimplePie::set_raw_data()
  1790. */
  1791. public function set_feed_url($url)
  1792. {
  1793. if (is_array($url))
  1794. {
  1795. $this->multifeed_url = array();
  1796. foreach ($url as $value)
  1797. {
  1798. $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
  1799. }
  1800. }
  1801. else
  1802. {
  1803. $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
  1804. }
  1805. }
  1806. /**
  1807. * Provides an instance of SimplePie_File to use as a feed
  1808. *
  1809. * @access public
  1810. * @param object &$file Instance of SimplePie_File (or subclass)
  1811. * @return bool True on success, false on failure
  1812. */
  1813. public function set_file(&$file)
  1814. {
  1815. if (is_a($file, 'SimplePie_File'))
  1816. {
  1817. $this->feed_url = $file->url;
  1818. $this->file =& $file;
  1819. return true;
  1820. }
  1821. return false;
  1822. }
  1823. /**
  1824. * Allows you to use a string of RSS/Atom data instead of a remote feed.
  1825. *
  1826. * If you have a feed available as a string in PHP, you can tell SimplePie
  1827. * to parse that data string instead of a remote feed. Any set feed URL
  1828. * takes precedence.
  1829. *
  1830. * @access public
  1831. * @since 1.0 Beta 3
  1832. * @param string $data RSS or Atom data as a string.
  1833. * @see SimplePie::set_feed_url()
  1834. */
  1835. public function set_raw_data($data)
  1836. {
  1837. $this->raw_data = $data;
  1838. }
  1839. /**
  1840. * Allows you to override the default timeout for fetching remote feeds.
  1841. *
  1842. * This allows you to change the maximum time the feed's server to respond
  1843. * and send the feed back.
  1844. *
  1845. * @access public
  1846. * @since 1.0 Beta 3
  1847. * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
  1848. */
  1849. public function set_timeout($timeout = 10)
  1850. {
  1851. $this->timeout = (int) $timeout;
  1852. }
  1853. /**
  1854. * Forces SimplePie to use fsockopen() instead of the preferred cURL
  1855. * functions.
  1856. *
  1857. * @access public
  1858. * @since 1.0 Beta 3
  1859. * @param bool $enable Force fsockopen() to be used
  1860. */
  1861. public function force_fsockopen($enable = false)
  1862. {
  1863. $this->force_fsockopen = (bool) $enable;
  1864. }
  1865. /**
  1866. * Enables/disables caching in SimplePie.
  1867. *
  1868. * This option allows you to disable caching all-together in SimplePie.
  1869. * However, disabling the cache can lead to longer load times.
  1870. *
  1871. * @access public
  1872. * @since 1.0 Preview Release
  1873. * @param bool $enable Enable caching
  1874. */
  1875. public function enable_cache($enable = true)
  1876. {
  1877. $this->cache = (bool) $enable;
  1878. }
  1879. /**
  1880. * Set the length of time (in seconds) that the contents of a feed
  1881. * will be cached.
  1882. *
  1883. * @access public
  1884. * @param int $seconds The feed content cache duration.
  1885. */
  1886. public function set_cache_duration($seconds = 3600)
  1887. {
  1888. $this->cache_duration = (int) $seconds;
  1889. }
  1890. /**
  1891. * Set the length of time (in seconds) that the autodiscovered feed
  1892. * URL will be cached.
  1893. *
  1894. * @access public
  1895. * @param int $seconds The autodiscovered feed URL cache duration.
  1896. */
  1897. public function set_autodiscovery_cache_duration($seconds = 604800)
  1898. {
  1899. $this->autodiscovery_cache_duration = (int) $seconds;
  1900. }
  1901. /**
  1902. * Set the file system location where the cached files should be stored.
  1903. *
  1904. * @access public
  1905. * @param string $location The file system location.
  1906. */
  1907. public function set_cache_location($location = './cache')
  1908. {
  1909. $this->cache_location = (string) $location;
  1910. }
  1911. /**
  1912. * Determines whether feed items should be sorted into reverse chronological order.
  1913. *
  1914. * @access public
  1915. * @param bool $enable Sort as reverse chronological order.
  1916. */
  1917. public function enable_order_by_date($enable = true)
  1918. {
  1919. $this->order_by_date = (bool) $enable;
  1920. }
  1921. /**
  1922. * Allows you to override the character encoding reported by the feed.
  1923. *
  1924. * @access public
  1925. * @param string $encoding Character encoding.
  1926. */
  1927. public function set_input_encoding($encoding = false)
  1928. {
  1929. if ($encoding)
  1930. {
  1931. $this->input_encoding = (string) $encoding;
  1932. }
  1933. else
  1934. {
  1935. $this->input_encoding = false;
  1936. }
  1937. }
  1938. /**
  1939. * Set how much feed autodiscovery to do
  1940. *
  1941. * @access public
  1942. * @see SIMPLEPIE_LOCATOR_NONE
  1943. * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
  1944. * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
  1945. * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
  1946. * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
  1947. * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
  1948. * @see SIMPLEPIE_LOCATOR_ALL
  1949. * @param int $level Feed Autodiscovery Level (level can be a
  1950. * combination of the above constants, see bitwise OR operator)
  1951. */
  1952. public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
  1953. {
  1954. $this->autodiscovery = (int) $level;
  1955. }
  1956. /**
  1957. * Allows you to change which class SimplePie uses for caching.
  1958. * Useful when you are overloading or extending SimplePie's default classes.
  1959. *
  1960. * @access public
  1961. * @param string $class Name of custom class.
  1962. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1963. */
  1964. public function set_cache_class($class = 'SimplePie_Cache')
  1965. {
  1966. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
  1967. {
  1968. $this->cache_class = $class;
  1969. return true;
  1970. }
  1971. return false;
  1972. }
  1973. /**
  1974. * Allows you to change which class SimplePie uses for auto-discovery.
  1975. * Useful when you are overloading or extending SimplePie's default classes.
  1976. *
  1977. * @access public
  1978. * @param string $class Name of custom class.
  1979. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1980. */
  1981. public function set_locator_class($class = 'SimplePie_Locator')
  1982. {
  1983. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
  1984. {
  1985. $this->locator_class = $class;
  1986. return true;
  1987. }
  1988. return false;
  1989. }
  1990. /**
  1991. * Allows you to change which class SimplePie uses for XML parsing.
  1992. * Useful when you are overloading or extending SimplePie's default classes.
  1993. *
  1994. * @access public
  1995. * @param string $class Name of custom class.
  1996. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1997. */
  1998. public function set_parser_class($class = 'SimplePie_Parser')
  1999. {
  2000. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
  2001. {
  2002. $this->parser_class = $class;
  2003. return true;
  2004. }
  2005. return false;
  2006. }
  2007. /**
  2008. * Allows you to change which class SimplePie uses for remote file fetching.
  2009. * Useful when you are overloading or extending SimplePie's default classes.
  2010. *
  2011. * @access public
  2012. * @param string $class Name of custom class.
  2013. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2014. */
  2015. public function set_file_class($class = 'SimplePie_File')
  2016. {
  2017. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
  2018. {
  2019. $this->file_class = $class;
  2020. return true;
  2021. }
  2022. return false;
  2023. }
  2024. /**
  2025. * Allows you to change which class SimplePie uses for data sanitization.
  2026. * Useful when you are overloading or extending SimplePie's default classes.
  2027. *
  2028. * @access public
  2029. * @param string $class Name of custom class.
  2030. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2031. */
  2032. public function set_sanitize_class($class = 'SimplePie_Sanitize')
  2033. {
  2034. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
  2035. {
  2036. $this->sanitize = new $class();
  2037. return true;
  2038. }
  2039. return false;
  2040. }
  2041. /**
  2042. * Allows you to change which class SimplePie uses for handling feed items.
  2043. * Useful when you are overloading or extending SimplePie's default classes.
  2044. *
  2045. * @access public
  2046. * @param string $class Name of custom class.
  2047. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2048. */
  2049. public function set_item_class($class = 'SimplePie_Item')
  2050. {
  2051. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
  2052. {
  2053. $this->item_class = $class;
  2054. return true;
  2055. }
  2056. return false;
  2057. }
  2058. /**
  2059. * Allows you to change which class SimplePie uses for handling author data.
  2060. * Useful when you are overloading or extending SimplePie's default classes.
  2061. *
  2062. * @access public
  2063. * @param string $class Name of custom class.
  2064. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2065. */
  2066. public function set_author_class($class = 'SimplePie_Author')
  2067. {
  2068. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
  2069. {
  2070. $this->author_class = $class;
  2071. return true;
  2072. }
  2073. return false;
  2074. }
  2075. /**
  2076. * Allows you to change which class SimplePie uses for handling category data.
  2077. * Useful when you are overloading or extending SimplePie's default classes.
  2078. *
  2079. * @access public
  2080. * @param string $class Name of custom class.
  2081. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2082. */
  2083. public function set_category_class($class = 'SimplePie_Category')
  2084. {
  2085. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
  2086. {
  2087. $this->category_class = $class;
  2088. return true;
  2089. }
  2090. return false;
  2091. }
  2092. /**
  2093. * Allows you to change which class SimplePie uses for feed enclosures.
  2094. * Useful when you are overloading or extending SimplePie's default classes.
  2095. *
  2096. * @access public
  2097. * @param string $class Name of custom class.
  2098. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2099. */
  2100. public function set_enclosure_class($class = 'SimplePie_Enclosure')
  2101. {
  2102. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
  2103. {
  2104. $this->enclosure_class = $class;
  2105. return true;
  2106. }
  2107. return false;
  2108. }
  2109. /**
  2110. * Allows you to change which class SimplePie uses for <media:text> captions
  2111. * Useful when you are overloading or extending SimplePie's default classes.
  2112. *
  2113. * @access public
  2114. * @param string $class Name of custom class.
  2115. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2116. */
  2117. public function set_caption_class($class = 'SimplePie_Caption')
  2118. {
  2119. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
  2120. {
  2121. $this->caption_class = $class;
  2122. return true;
  2123. }
  2124. return false;
  2125. }
  2126. /**
  2127. * Allows you to change which class SimplePie uses for <media:copyright>
  2128. * Useful when you are overloading or extending SimplePie's default classes.
  2129. *
  2130. * @access public
  2131. * @param string $class Name of custom class.
  2132. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2133. */
  2134. public function set_copyright_class($class = 'SimplePie_Copyright')
  2135. {
  2136. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
  2137. {
  2138. $this->copyright_class = $class;
  2139. return true;
  2140. }
  2141. return false;
  2142. }
  2143. /**
  2144. * Allows you to change which class SimplePie uses for <media:credit>
  2145. * Useful when you are overloading or extending SimplePie's default classes.
  2146. *
  2147. * @access public
  2148. * @param string $class Name of custom class.
  2149. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2150. */
  2151. public function set_credit_class($class = 'SimplePie_Credit')
  2152. {
  2153. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
  2154. {
  2155. $this->credit_class = $class;
  2156. return true;
  2157. }
  2158. return false;
  2159. }
  2160. /**
  2161. * Allows you to change which class SimplePie uses for <media:rating>
  2162. * Useful when you are overloading or extending SimplePie's default classes.
  2163. *
  2164. * @access public
  2165. * @param string $class Name of custom class.
  2166. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2167. */
  2168. public function set_rating_class($class = 'SimplePie_Rating')
  2169. {
  2170. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
  2171. {
  2172. $this->rating_class = $class;
  2173. return true;
  2174. }
  2175. return false;
  2176. }
  2177. /**
  2178. * Allows you to change which class SimplePie uses for <media:restriction>
  2179. * Useful when you are overloading or extending SimplePie's default classes.
  2180. *
  2181. * @access public
  2182. * @param string $class Name of custom class.
  2183. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2184. */
  2185. public function set_restriction_class($class = 'SimplePie_Restriction')
  2186. {
  2187. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
  2188. {
  2189. $this->restriction_class = $class;
  2190. return true;
  2191. }
  2192. return false;
  2193. }
  2194. /**
  2195. * Allows you to change which class SimplePie uses for content-type sniffing.
  2196. * Useful when you are overloading or extending SimplePie's default classes.
  2197. *
  2198. * @access public
  2199. * @param string $class Name of custom class.
  2200. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2201. */
  2202. public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
  2203. {
  2204. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
  2205. {
  2206. $this->content_type_sniffer_class = $class;
  2207. return true;
  2208. }
  2209. return false;
  2210. }
  2211. /**
  2212. * Allows you to change which class SimplePie uses item sources.
  2213. * Useful when you are overloading or extending SimplePie's default classes.
  2214. *
  2215. * @access public
  2216. * @param string $class Name of custom class.
  2217. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  2218. */
  2219. public function set_source_class($class = 'SimplePie_Source')
  2220. {
  2221. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
  2222. {
  2223. $this->source_class = $class;
  2224. return true;
  2225. }
  2226. return false;
  2227. }
  2228. /**
  2229. * Allows you to override the default user agent string.
  2230. *
  2231. * @access public
  2232. * @param string $ua New user agent string.
  2233. */
  2234. public function set_useragent($ua = SIMPLEPIE_USERAGENT)
  2235. {
  2236. $this->useragent = (string) $ua;
  2237. }
  2238. /**
  2239. * Set callback function to create cache filename with
  2240. *
  2241. * @access public
  2242. * @param mixed $function Callback function
  2243. */
  2244. public function set_cache_name_function($function = 'md5')
  2245. {
  2246. if (is_callable($function))
  2247. {
  2248. $this->cache_name_function = $function;
  2249. }
  2250. }
  2251. /**
  2252. * Set options to make SP as fast as possible. Forgoes a
  2253. * substantial amount of data sanitization in favor of speed.
  2254. *
  2255. * @access public
  2256. * @param bool $set Whether to set them or not
  2257. */
  2258. public function set_stupidly_fast($set = false)
  2259. {
  2260. if ($set)
  2261. {
  2262. $this->enable_order_by_date(false);
  2263. $this->remove_div(false);
  2264. $this->strip_comments(false);
  2265. $this->strip_htmltags(false);
  2266. $this->strip_attributes(false);
  2267. $this->set_image_handler(false);
  2268. }
  2269. }
  2270. /**
  2271. * Set maximum number of feeds to check with autodiscovery
  2272. *
  2273. * @access public
  2274. * @param int $max Maximum number of feeds to check
  2275. */
  2276. public function set_max_checked_feeds($max = 10)
  2277. {
  2278. $this->max_checked_feeds = (int) $max;
  2279. }
  2280. public function remove_div($enable = true)
  2281. {
  2282. $this->sanitize->remove_div($enable);
  2283. }
  2284. public function strip_htmltags($tags = '', $encode = null)
  2285. {
  2286. if ($tags === '')
  2287. {
  2288. $tags = $this->strip_htmltags;
  2289. }
  2290. $this->sanitize->strip_htmltags($tags);
  2291. if ($encode !== null)
  2292. {
  2293. $this->sanitize->encode_instead_of_strip($tags);
  2294. }
  2295. }
  2296. public function encode_instead_of_strip($enable = true)
  2297. {
  2298. $this->sanitize->encode_instead_of_strip($enable);
  2299. }
  2300. public function strip_attributes($attribs = '')
  2301. {
  2302. if ($attribs === '')
  2303. {
  2304. $attribs = $this->strip_attributes;
  2305. }
  2306. $this->sanitize->strip_attributes($attribs);
  2307. }
  2308. public function set_output_encoding($encoding = 'UTF-8')
  2309. {
  2310. $this->sanitize->set_output_encoding($encoding);
  2311. }
  2312. public function strip_comments($strip = false)
  2313. {
  2314. $this->sanitize->strip_comments($strip);
  2315. }
  2316. /**
  2317. * Set element/attribute key/value pairs of HTML attributes
  2318. * containing URLs that need to be resolved relative to the feed
  2319. *
  2320. * @access public
  2321. * @since 1.0
  2322. * @param array $element_attribute Element/attribute key/value pairs
  2323. */
  2324. public function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
  2325. {
  2326. $this->sanitize->set_url_replacements($element_attribute);
  2327. }
  2328. /**
  2329. * Set the handler to enable the display of cached images.
  2330. *
  2331. * @access public
  2332. * @param str $page Web-accessible path to the handler_image.php file.
  2333. * @param str $qs The query string that the value should be passed to.
  2334. */
  2335. public function set_image_handler($page = false, $qs = 'i')
  2336. {
  2337. if ($page !== false)
  2338. {
  2339. $this->sanitize->set_image_handler($page . '?' . $qs . '=');
  2340. }
  2341. else
  2342. {
  2343. $this->image_handler = '';
  2344. }
  2345. }
  2346. /**
  2347. * Set the limit for items returned per-feed with multifeeds.
  2348. *
  2349. * @access public
  2350. * @param integer $limit The maximum number of items to return.
  2351. */
  2352. public function set_item_limit($limit = 0)
  2353. {
  2354. $this->item_limit = (int) $limit;
  2355. }
  2356. public function init()
  2357. {
  2358. // Check absolute bare minimum requirements.
  2359. if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
  2360. {
  2361. return false;
  2362. }
  2363. // Then check the xml extension is sane (i.e., libxml 2.7.x issue on PHP < 5.2.9 and libxml 2.7.0 to 2.7.2 on any version) if we don't have xmlreader.
  2364. elseif (!extension_loaded('xmlreader'))
  2365. {
  2366. static $xml_is_sane = null;
  2367. if ($xml_is_sane === null)
  2368. {
  2369. $parser_check = xml_parser_create();
  2370. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  2371. xml_parser_free($parser_check);
  2372. $xml_is_sane = isset($values[0]['value']);
  2373. }
  2374. if (!$xml_is_sane)
  2375. {
  2376. return false;
  2377. }
  2378. }
  2379. // Pass whatever was set with config options over to the sanitizer.
  2380. $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
  2381. $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
  2382. if ($this->feed_url !== null || $this->raw_data !== null)
  2383. {
  2384. $this->error = null;
  2385. $this->data = array();
  2386. $this->multifeed_objects = array();
  2387. $cache = false;
  2388. if ($this->feed_url !== null)
  2389. {
  2390. $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
  2391. // Decide whether to enable caching
  2392. if ($this->cache && $parsed_feed_url['scheme'] !== '')
  2393. {
  2394. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
  2395. }
  2396. // If it's enabled and we don't want an XML dump, use the cache
  2397. if ($cache && !$this->xml_dump)
  2398. {
  2399. // Load the Cache
  2400. $this->data = $cache->load();
  2401. if (!empty($this->data))
  2402. {
  2403. // If the cache is for an outdated build of SimplePie
  2404. if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
  2405. {
  2406. $cache->unlink();
  2407. $this->data = array();
  2408. }
  2409. // If we've hit a collision just rerun it with caching disabled
  2410. elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
  2411. {
  2412. $cache = false;
  2413. $this->data = array();
  2414. }
  2415. // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
  2416. elseif (isset($this->data['feed_url']))
  2417. {
  2418. // If the autodiscovery cache is still valid use it.
  2419. if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
  2420. {
  2421. // Do not need to do feed autodiscovery yet.
  2422. if ($this->data['feed_url'] === $this->data['url'])
  2423. {
  2424. $cache->unlink();
  2425. $this->data = array();
  2426. }
  2427. else
  2428. {
  2429. $this->set_feed_url($this->data['feed_url']);
  2430. return $this->init();
  2431. }
  2432. }
  2433. }
  2434. // Check if the cache has been updated
  2435. elseif ($cache->mtime() + $this->cache_duration < time())
  2436. {
  2437. // If we have last-modified and/or etag set
  2438. if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
  2439. {
  2440. $headers = array(
  2441. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  2442. );
  2443. if (isset($this->data['headers']['last-modified']))
  2444. {
  2445. $headers['if-modified-since'] = $this->data['headers']['last-modified'];
  2446. }
  2447. if (isset($this->data['headers']['etag']))
  2448. {
  2449. $headers['if-none-match'] = $this->data['headers']['etag'];
  2450. }
  2451. $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
  2452. if ($file->success)
  2453. {
  2454. if ($file->status_code === 304)
  2455. {
  2456. $cache->touch();
  2457. return true;
  2458. }
  2459. else
  2460. {
  2461. $headers = $file->headers;
  2462. }
  2463. }
  2464. else
  2465. {
  2466. unset($file);
  2467. }
  2468. }
  2469. }
  2470. // If the cache is still valid, just return true
  2471. else
  2472. {
  2473. $this->raw_data = false;
  2474. return true;
  2475. }
  2476. }
  2477. // If the cache is empty, delete it
  2478. else
  2479. {
  2480. $cache->unlink();
  2481. $this->data = array();
  2482. }
  2483. }
  2484. // If we don't already have the file (it'll only exist if we've opened it to check if the cache has been modified), open it.
  2485. if (!isset($file))
  2486. {
  2487. if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
  2488. {
  2489. $file =& $this->file;
  2490. }
  2491. else
  2492. {
  2493. $headers = array(
  2494. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  2495. );
  2496. $file = new $this->file_class($this->feed_url, $this->timeout, 5, $headers, $this->useragent, $this->force_fsockopen);
  2497. }
  2498. }
  2499. // If the file connection has an error, set SimplePie::error to that and quit
  2500. if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  2501. {
  2502. $this->error = $file->error;
  2503. if (!empty($this->data))
  2504. {
  2505. return true;
  2506. }
  2507. else
  2508. {
  2509. return false;
  2510. }
  2511. }
  2512. if (!$this->force_feed)
  2513. {
  2514. // Check if the supplied URL is a feed, if it isn't, look for it.
  2515. $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
  2516. if (!$locate->is_feed($file))
  2517. {
  2518. // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
  2519. unset($file);
  2520. if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
  2521. {
  2522. if ($cache)
  2523. {
  2524. $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
  2525. if (!$cache->save($this))
  2526. {
  2527. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  2528. }
  2529. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
  2530. }
  2531. $this->feed_url = $file->url;
  2532. }
  2533. else
  2534. {
  2535. $this->error = "A feed could not be found at $this->feed_url. A feed with an invalid mime type may fall victim to this error, or " . SIMPLEPIE_NAME . " was unable to auto-discover it.. Use force_feed() if you are certain this URL is a real feed.";
  2536. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  2537. return false;
  2538. }
  2539. }
  2540. $locate = null;
  2541. }
  2542. $headers = $file->headers;
  2543. $data = $file->body;
  2544. $sniffer = new $this->content_type_sniffer_class($file);
  2545. $sniffed = $sniffer->get_type();
  2546. }
  2547. else
  2548. {
  2549. $data = $this->raw_data;
  2550. }
  2551. // This is exposed via get_raw_data()
  2552. $this->raw_data = $data;
  2553. // Set up array of possible encodings
  2554. $encodings = array();
  2555. // First check to see if input has been overridden.
  2556. if ($this->input_encoding !== false)
  2557. {
  2558. $encodings[] = $this->input_encoding;
  2559. }
  2560. $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
  2561. $text_types = array('text/xml', 'text/xml-external-parsed-entity');
  2562. // RFC 3023 (only applies to sniffed content)
  2563. if (isset($sniffed))
  2564. {
  2565. if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
  2566. {
  2567. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  2568. {
  2569. $encodings[] = strtoupper($charset[1]);
  2570. }
  2571. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  2572. $encodings[] = 'UTF-8';
  2573. }
  2574. elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
  2575. {
  2576. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  2577. {
  2578. $encodings[] = $charset[1];
  2579. }
  2580. $encodings[] = 'US-ASCII';
  2581. }
  2582. // Text MIME-type default
  2583. elseif (substr($sniffed, 0, 5) === 'text/')
  2584. {
  2585. $encodings[] = 'US-ASCII';
  2586. }
  2587. }
  2588. // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
  2589. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  2590. $encodings[] = 'UTF-8';
  2591. $encodings[] = 'ISO-8859-1';
  2592. // There's no point in trying an encoding twice
  2593. $encodings = array_unique($encodings);
  2594. // If we want the XML, just output that with the most likely encoding and quit
  2595. if ($this->xml_dump)
  2596. {
  2597. header('Content-type: text/xml; charset=' . $encodings[0]);
  2598. echo $data;
  2599. exit;
  2600. }
  2601. // Loop through each possible encoding, till we return something, or run out of possibilities
  2602. foreach ($encodings as $encoding)
  2603. {
  2604. // Change the encoding to UTF-8 (as we always use UTF-8 internally)
  2605. if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
  2606. {
  2607. // Create new parser
  2608. $parser = new $this->parser_class();
  2609. // If it's parsed fine
  2610. if ($parser->parse($utf8_data, 'UTF-8'))
  2611. {
  2612. $this->data = $parser->get_data();
  2613. if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
  2614. {
  2615. if (isset($headers))
  2616. {
  2617. $this->data['headers'] = $headers;
  2618. }
  2619. $this->data['build'] = SIMPLEPIE_BUILD;
  2620. // Cache the file if caching is enabled
  2621. if ($cache && !$cache->save($this))
  2622. {
  2623. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  2624. }
  2625. return true;
  2626. }
  2627. else
  2628. {
  2629. $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
  2630. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  2631. return false;
  2632. }
  2633. }
  2634. }
  2635. }
  2636. if (isset($parser))
  2637. {
  2638. // We have an error, just set SimplePie_Misc::error to it and quit
  2639. $this->error = sprintf('This XML document is invalid, likely due to invalid characters. XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
  2640. }
  2641. else
  2642. {
  2643. $this->error = 'The data could not be converted to UTF-8. You MUST have either the iconv or mbstring extension installed. Upgrading to PHP 5.x (which includes iconv) is highly recommended.';
  2644. }
  2645. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  2646. return false;
  2647. }
  2648. elseif (!empty($this->multifeed_url))
  2649. {
  2650. $i = 0;
  2651. $success = 0;
  2652. $this->multifeed_objects = array();
  2653. foreach ($this->multifeed_url as $url)
  2654. {
  2655. $this->multifeed_objects[$i] = clone $this;
  2656. $this->multifeed_objects[$i]->set_feed_url($url);
  2657. $success |= $this->multifeed_objects[$i]->init();
  2658. $i++;
  2659. }
  2660. return (bool) $success;
  2661. }
  2662. else
  2663. {
  2664. return false;
  2665. }
  2666. }
  2667. /**
  2668. * Return the error message for the occured error
  2669. *
  2670. * @access public
  2671. * @return string Error message
  2672. */
  2673. public function error()
  2674. {
  2675. return $this->error;
  2676. }
  2677. /**
  2678. * Return the raw XML
  2679. *
  2680. * This is the same as setting `$xml_dump = true;`, but returns
  2681. * the data instead of printing it.
  2682. *
  2683. * @return string|boolean Raw XML data, false if the cache is used
  2684. */
  2685. public function get_raw_data()
  2686. {
  2687. return $this->raw_data;
  2688. }
  2689. public function get_encoding()
  2690. {
  2691. return $this->sanitize->output_encoding;
  2692. }
  2693. public function handle_content_type($mime = 'text/html')
  2694. {
  2695. if (!headers_sent())
  2696. {
  2697. $header = "Content-type: $mime;";
  2698. if ($this->get_encoding())
  2699. {
  2700. $header .= ' charset=' . $this->get_encoding();
  2701. }
  2702. else
  2703. {
  2704. $header .= ' charset=UTF-8';
  2705. }
  2706. header($header);
  2707. }
  2708. }
  2709. public function get_type()
  2710. {
  2711. if (!isset($this->data['type']))
  2712. {
  2713. $this->data['type'] = SIMPLEPIE_TYPE_ALL;
  2714. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
  2715. {
  2716. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
  2717. }
  2718. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
  2719. {
  2720. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
  2721. }
  2722. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
  2723. {
  2724. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
  2725. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
  2726. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
  2727. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
  2728. {
  2729. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
  2730. }
  2731. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
  2732. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
  2733. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
  2734. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
  2735. {
  2736. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
  2737. }
  2738. }
  2739. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
  2740. {
  2741. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
  2742. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  2743. {
  2744. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  2745. {
  2746. case '0.91':
  2747. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
  2748. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  2749. {
  2750. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  2751. {
  2752. case '0':
  2753. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
  2754. break;
  2755. case '24':
  2756. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
  2757. break;
  2758. }
  2759. }
  2760. break;
  2761. case '0.92':
  2762. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
  2763. break;
  2764. case '0.93':
  2765. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
  2766. break;
  2767. case '0.94':
  2768. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
  2769. break;
  2770. case '2.0':
  2771. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
  2772. break;
  2773. }
  2774. }
  2775. }
  2776. else
  2777. {
  2778. $this->data['type'] = SIMPLEPIE_TYPE_NONE;
  2779. }
  2780. }
  2781. return $this->data['type'];
  2782. }
  2783. /**
  2784. * @todo If we have a perm redirect we should return the new URL
  2785. * @todo When we make the above change, let's support <itunes:new-feed-url> as well
  2786. * @todo Also, |atom:link|@rel=self
  2787. */
  2788. public function subscribe_url()
  2789. {
  2790. if ($this->feed_url !== null)
  2791. {
  2792. return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
  2793. }
  2794. else
  2795. {
  2796. return null;
  2797. }
  2798. }
  2799. public function get_feed_tags($namespace, $tag)
  2800. {
  2801. $type = $this->get_type();
  2802. if ($type & SIMPLEPIE_TYPE_ATOM_10)
  2803. {
  2804. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
  2805. {
  2806. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
  2807. }
  2808. }
  2809. if ($type & SIMPLEPIE_TYPE_ATOM_03)
  2810. {
  2811. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
  2812. {
  2813. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
  2814. }
  2815. }
  2816. if ($type & SIMPLEPIE_TYPE_RSS_RDF)
  2817. {
  2818. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
  2819. {
  2820. return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
  2821. }
  2822. }
  2823. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  2824. {
  2825. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
  2826. {
  2827. return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
  2828. }
  2829. }
  2830. return null;
  2831. }
  2832. public function get_channel_tags($namespace, $tag)
  2833. {
  2834. $type = $this->get_type();
  2835. if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
  2836. {
  2837. if ($return = $this->get_feed_tags($namespace, $tag))
  2838. {
  2839. return $return;
  2840. }
  2841. }
  2842. if ($type & SIMPLEPIE_TYPE_RSS_10)
  2843. {
  2844. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
  2845. {
  2846. if (isset($channel[0]['child'][$namespace][$tag]))
  2847. {
  2848. return $channel[0]['child'][$namespace][$tag];
  2849. }
  2850. }
  2851. }
  2852. if ($type & SIMPLEPIE_TYPE_RSS_090)
  2853. {
  2854. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
  2855. {
  2856. if (isset($channel[0]['child'][$namespace][$tag]))
  2857. {
  2858. return $channel[0]['child'][$namespace][$tag];
  2859. }
  2860. }
  2861. }
  2862. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  2863. {
  2864. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
  2865. {
  2866. if (isset($channel[0]['child'][$namespace][$tag]))
  2867. {
  2868. return $channel[0]['child'][$namespace][$tag];
  2869. }
  2870. }
  2871. }
  2872. return null;
  2873. }
  2874. public function get_image_tags($namespace, $tag)
  2875. {
  2876. $type = $this->get_type();
  2877. if ($type & SIMPLEPIE_TYPE_RSS_10)
  2878. {
  2879. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
  2880. {
  2881. if (isset($image[0]['child'][$namespace][$tag]))
  2882. {
  2883. return $image[0]['child'][$namespace][$tag];
  2884. }
  2885. }
  2886. }
  2887. if ($type & SIMPLEPIE_TYPE_RSS_090)
  2888. {
  2889. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
  2890. {
  2891. if (isset($image[0]['child'][$namespace][$tag]))
  2892. {
  2893. return $image[0]['child'][$namespace][$tag];
  2894. }
  2895. }
  2896. }
  2897. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  2898. {
  2899. if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
  2900. {
  2901. if (isset($image[0]['child'][$namespace][$tag]))
  2902. {
  2903. return $image[0]['child'][$namespace][$tag];
  2904. }
  2905. }
  2906. }
  2907. return null;
  2908. }
  2909. public function get_base($element = array())
  2910. {
  2911. if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
  2912. {
  2913. return $element['xml_base'];
  2914. }
  2915. elseif ($this->get_link() !== null)
  2916. {
  2917. return $this->get_link();
  2918. }
  2919. else
  2920. {
  2921. return $this->subscribe_url();
  2922. }
  2923. }
  2924. public function sanitize($data, $type, $base = '')
  2925. {
  2926. return $this->sanitize->sanitize($data, $type, $base);
  2927. }
  2928. public function get_title()
  2929. {
  2930. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  2931. {
  2932. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2933. }
  2934. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  2935. {
  2936. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2937. }
  2938. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2939. {
  2940. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2941. }
  2942. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2943. {
  2944. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2945. }
  2946. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2947. {
  2948. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2949. }
  2950. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2951. {
  2952. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2953. }
  2954. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2955. {
  2956. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2957. }
  2958. else
  2959. {
  2960. return null;
  2961. }
  2962. }
  2963. public function get_category($key = 0)
  2964. {
  2965. $categories = $this->get_categories();
  2966. if (isset($categories[$key]))
  2967. {
  2968. return $categories[$key];
  2969. }
  2970. else
  2971. {
  2972. return null;
  2973. }
  2974. }
  2975. public function get_categories()
  2976. {
  2977. $categories = array();
  2978. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  2979. {
  2980. $term = null;
  2981. $scheme = null;
  2982. $label = null;
  2983. if (isset($category['attribs']['']['term']))
  2984. {
  2985. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  2986. }
  2987. if (isset($category['attribs']['']['scheme']))
  2988. {
  2989. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  2990. }
  2991. if (isset($category['attribs']['']['label']))
  2992. {
  2993. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  2994. }
  2995. $categories[] = new $this->category_class($term, $scheme, $label);
  2996. }
  2997. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  2998. {
  2999. // This is really the label, but keep this as the term also for BC.
  3000. // Label will also work on retrieving because that falls back to term.
  3001. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3002. if (isset($category['attribs']['']['domain']))
  3003. {
  3004. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  3005. }
  3006. else
  3007. {
  3008. $scheme = null;
  3009. }
  3010. $categories[] = new $this->category_class($term, $scheme, null);
  3011. }
  3012. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  3013. {
  3014. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3015. }
  3016. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  3017. {
  3018. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3019. }
  3020. if (!empty($categories))
  3021. {
  3022. return SimplePie_Misc::array_unique($categories);
  3023. }
  3024. else
  3025. {
  3026. return null;
  3027. }
  3028. }
  3029. public function get_author($key = 0)
  3030. {
  3031. $authors = $this->get_authors();
  3032. if (isset($authors[$key]))
  3033. {
  3034. return $authors[$key];
  3035. }
  3036. else
  3037. {
  3038. return null;
  3039. }
  3040. }
  3041. public function get_authors()
  3042. {
  3043. $authors = array();
  3044. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  3045. {
  3046. $name = null;
  3047. $uri = null;
  3048. $email = null;
  3049. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  3050. {
  3051. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3052. }
  3053. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  3054. {
  3055. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  3056. }
  3057. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  3058. {
  3059. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3060. }
  3061. if ($name !== null || $email !== null || $uri !== null)
  3062. {
  3063. $authors[] = new $this->author_class($name, $uri, $email);
  3064. }
  3065. }
  3066. if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  3067. {
  3068. $name = null;
  3069. $url = null;
  3070. $email = null;
  3071. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  3072. {
  3073. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3074. }
  3075. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  3076. {
  3077. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  3078. }
  3079. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  3080. {
  3081. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3082. }
  3083. if ($name !== null || $email !== null || $url !== null)
  3084. {
  3085. $authors[] = new $this->author_class($name, $url, $email);
  3086. }
  3087. }
  3088. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  3089. {
  3090. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3091. }
  3092. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  3093. {
  3094. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3095. }
  3096. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  3097. {
  3098. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3099. }
  3100. if (!empty($authors))
  3101. {
  3102. return SimplePie_Misc::array_unique($authors);
  3103. }
  3104. else
  3105. {
  3106. return null;
  3107. }
  3108. }
  3109. public function get_contributor($key = 0)
  3110. {
  3111. $contributors = $this->get_contributors();
  3112. if (isset($contributors[$key]))
  3113. {
  3114. return $contributors[$key];
  3115. }
  3116. else
  3117. {
  3118. return null;
  3119. }
  3120. }
  3121. public function get_contributors()
  3122. {
  3123. $contributors = array();
  3124. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  3125. {
  3126. $name = null;
  3127. $uri = null;
  3128. $email = null;
  3129. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  3130. {
  3131. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3132. }
  3133. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  3134. {
  3135. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  3136. }
  3137. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  3138. {
  3139. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3140. }
  3141. if ($name !== null || $email !== null || $uri !== null)
  3142. {
  3143. $contributors[] = new $this->author_class($name, $uri, $email);
  3144. }
  3145. }
  3146. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  3147. {
  3148. $name = null;
  3149. $url = null;
  3150. $email = null;
  3151. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  3152. {
  3153. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3154. }
  3155. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  3156. {
  3157. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  3158. }
  3159. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  3160. {
  3161. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3162. }
  3163. if ($name !== null || $email !== null || $url !== null)
  3164. {
  3165. $contributors[] = new $this->author_class($name, $url, $email);
  3166. }
  3167. }
  3168. if (!empty($contributors))
  3169. {
  3170. return SimplePie_Misc::array_unique($contributors);
  3171. }
  3172. else
  3173. {
  3174. return null;
  3175. }
  3176. }
  3177. public function get_link($key = 0, $rel = 'alternate')
  3178. {
  3179. $links = $this->get_links($rel);
  3180. if (isset($links[$key]))
  3181. {
  3182. return $links[$key];
  3183. }
  3184. else
  3185. {
  3186. return null;
  3187. }
  3188. }
  3189. /**
  3190. * Added for parity between the parent-level and the item/entry-level.
  3191. */
  3192. public function get_permalink()
  3193. {
  3194. return $this->get_link(0);
  3195. }
  3196. public function get_links($rel = 'alternate')
  3197. {
  3198. if (!isset($this->data['links']))
  3199. {
  3200. $this->data['links'] = array();
  3201. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  3202. {
  3203. foreach ($links as $link)
  3204. {
  3205. if (isset($link['attribs']['']['href']))
  3206. {
  3207. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3208. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3209. }
  3210. }
  3211. }
  3212. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  3213. {
  3214. foreach ($links as $link)
  3215. {
  3216. if (isset($link['attribs']['']['href']))
  3217. {
  3218. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3219. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3220. }
  3221. }
  3222. }
  3223. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  3224. {
  3225. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3226. }
  3227. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  3228. {
  3229. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3230. }
  3231. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  3232. {
  3233. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3234. }
  3235. $keys = array_keys($this->data['links']);
  3236. foreach ($keys as $key)
  3237. {
  3238. if (SimplePie_Misc::is_isegment_nz_nc($key))
  3239. {
  3240. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  3241. {
  3242. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  3243. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  3244. }
  3245. else
  3246. {
  3247. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  3248. }
  3249. }
  3250. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  3251. {
  3252. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  3253. }
  3254. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  3255. }
  3256. }
  3257. if (isset($this->data['links'][$rel]))
  3258. {
  3259. return $this->data['links'][$rel];
  3260. }
  3261. else
  3262. {
  3263. return null;
  3264. }
  3265. }
  3266. public function get_all_discovered_feeds()
  3267. {
  3268. return $this->all_discovered_feeds;
  3269. }
  3270. public function get_description()
  3271. {
  3272. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  3273. {
  3274. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3275. }
  3276. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  3277. {
  3278. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3279. }
  3280. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  3281. {
  3282. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  3283. }
  3284. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  3285. {
  3286. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  3287. }
  3288. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  3289. {
  3290. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3291. }
  3292. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  3293. {
  3294. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3295. }
  3296. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  3297. {
  3298. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3299. }
  3300. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  3301. {
  3302. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3303. }
  3304. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  3305. {
  3306. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3307. }
  3308. else
  3309. {
  3310. return null;
  3311. }
  3312. }
  3313. public function get_copyright()
  3314. {
  3315. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  3316. {
  3317. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3318. }
  3319. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  3320. {
  3321. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3322. }
  3323. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  3324. {
  3325. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3326. }
  3327. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  3328. {
  3329. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3330. }
  3331. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  3332. {
  3333. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3334. }
  3335. else
  3336. {
  3337. return null;
  3338. }
  3339. }
  3340. public function get_language()
  3341. {
  3342. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  3343. {
  3344. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3345. }
  3346. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  3347. {
  3348. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3349. }
  3350. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  3351. {
  3352. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3353. }
  3354. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
  3355. {
  3356. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3357. }
  3358. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
  3359. {
  3360. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3361. }
  3362. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
  3363. {
  3364. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3365. }
  3366. elseif (isset($this->data['headers']['content-language']))
  3367. {
  3368. return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
  3369. }
  3370. else
  3371. {
  3372. return null;
  3373. }
  3374. }
  3375. public function get_latitude()
  3376. {
  3377. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  3378. {
  3379. return (float) $return[0]['data'];
  3380. }
  3381. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  3382. {
  3383. return (float) $match[1];
  3384. }
  3385. else
  3386. {
  3387. return null;
  3388. }
  3389. }
  3390. public function get_longitude()
  3391. {
  3392. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  3393. {
  3394. return (float) $return[0]['data'];
  3395. }
  3396. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  3397. {
  3398. return (float) $return[0]['data'];
  3399. }
  3400. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  3401. {
  3402. return (float) $match[2];
  3403. }
  3404. else
  3405. {
  3406. return null;
  3407. }
  3408. }
  3409. public function get_image_title()
  3410. {
  3411. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  3412. {
  3413. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3414. }
  3415. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  3416. {
  3417. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3418. }
  3419. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  3420. {
  3421. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3422. }
  3423. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  3424. {
  3425. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3426. }
  3427. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  3428. {
  3429. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3430. }
  3431. else
  3432. {
  3433. return null;
  3434. }
  3435. }
  3436. public function get_image_url()
  3437. {
  3438. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  3439. {
  3440. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  3441. }
  3442. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  3443. {
  3444. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3445. }
  3446. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  3447. {
  3448. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3449. }
  3450. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
  3451. {
  3452. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3453. }
  3454. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
  3455. {
  3456. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3457. }
  3458. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  3459. {
  3460. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3461. }
  3462. else
  3463. {
  3464. return null;
  3465. }
  3466. }
  3467. public function get_image_link()
  3468. {
  3469. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  3470. {
  3471. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3472. }
  3473. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  3474. {
  3475. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3476. }
  3477. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  3478. {
  3479. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  3480. }
  3481. else
  3482. {
  3483. return null;
  3484. }
  3485. }
  3486. public function get_image_width()
  3487. {
  3488. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
  3489. {
  3490. return round($return[0]['data']);
  3491. }
  3492. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  3493. {
  3494. return 88.0;
  3495. }
  3496. else
  3497. {
  3498. return null;
  3499. }
  3500. }
  3501. public function get_image_height()
  3502. {
  3503. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
  3504. {
  3505. return round($return[0]['data']);
  3506. }
  3507. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  3508. {
  3509. return 31.0;
  3510. }
  3511. else
  3512. {
  3513. return null;
  3514. }
  3515. }
  3516. public function get_item_quantity($max = 0)
  3517. {
  3518. $max = (int) $max;
  3519. $qty = count($this->get_items());
  3520. if ($max === 0)
  3521. {
  3522. return $qty;
  3523. }
  3524. else
  3525. {
  3526. return ($qty > $max) ? $max : $qty;
  3527. }
  3528. }
  3529. public function get_item($key = 0)
  3530. {
  3531. $items = $this->get_items();
  3532. if (isset($items[$key]))
  3533. {
  3534. return $items[$key];
  3535. }
  3536. else
  3537. {
  3538. return null;
  3539. }
  3540. }
  3541. public function get_items($start = 0, $end = 0)
  3542. {
  3543. if (!isset($this->data['items']))
  3544. {
  3545. if (!empty($this->multifeed_objects))
  3546. {
  3547. $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
  3548. }
  3549. else
  3550. {
  3551. $this->data['items'] = array();
  3552. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
  3553. {
  3554. $keys = array_keys($items);
  3555. foreach ($keys as $key)
  3556. {
  3557. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  3558. }
  3559. }
  3560. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
  3561. {
  3562. $keys = array_keys($items);
  3563. foreach ($keys as $key)
  3564. {
  3565. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  3566. }
  3567. }
  3568. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
  3569. {
  3570. $keys = array_keys($items);
  3571. foreach ($keys as $key)
  3572. {
  3573. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  3574. }
  3575. }
  3576. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
  3577. {
  3578. $keys = array_keys($items);
  3579. foreach ($keys as $key)
  3580. {
  3581. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  3582. }
  3583. }
  3584. if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
  3585. {
  3586. $keys = array_keys($items);
  3587. foreach ($keys as $key)
  3588. {
  3589. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  3590. }
  3591. }
  3592. }
  3593. }
  3594. if (!empty($this->data['items']))
  3595. {
  3596. // If we want to order it by date, check if all items have a date, and then sort it
  3597. if ($this->order_by_date && empty($this->multifeed_objects))
  3598. {
  3599. if (!isset($this->data['ordered_items']))
  3600. {
  3601. $do_sort = true;
  3602. foreach ($this->data['items'] as $item)
  3603. {
  3604. if (!$item->get_date('U'))
  3605. {
  3606. $do_sort = false;
  3607. break;
  3608. }
  3609. }
  3610. $item = null;
  3611. $this->data['ordered_items'] = $this->data['items'];
  3612. if ($do_sort)
  3613. {
  3614. usort($this->data['ordered_items'], array(&$this, 'sort_items'));
  3615. }
  3616. }
  3617. $items = $this->data['ordered_items'];
  3618. }
  3619. else
  3620. {
  3621. $items = $this->data['items'];
  3622. }
  3623. // Slice the data as desired
  3624. if ($end === 0)
  3625. {
  3626. return array_slice($items, $start);
  3627. }
  3628. else
  3629. {
  3630. return array_slice($items, $start, $end);
  3631. }
  3632. }
  3633. else
  3634. {
  3635. return array();
  3636. }
  3637. }
  3638. /**
  3639. * @static
  3640. */
  3641. public function sort_items($a, $b)
  3642. {
  3643. return $a->get_date('U') <= $b->get_date('U');
  3644. }
  3645. /**
  3646. * @static
  3647. */
  3648. public function merge_items($urls, $start = 0, $end = 0, $limit = 0)
  3649. {
  3650. if (is_array($urls) && sizeof($urls) > 0)
  3651. {
  3652. $items = array();
  3653. foreach ($urls as $arg)
  3654. {
  3655. if (is_a($arg, 'SimplePie'))
  3656. {
  3657. $items = array_merge($items, $arg->get_items(0, $limit));
  3658. }
  3659. else
  3660. {
  3661. trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
  3662. }
  3663. }
  3664. $do_sort = true;
  3665. foreach ($items as $item)
  3666. {
  3667. if (!$item->get_date('U'))
  3668. {
  3669. $do_sort = false;
  3670. break;
  3671. }
  3672. }
  3673. $item = null;
  3674. if ($do_sort)
  3675. {
  3676. usort($items, array('SimplePie', 'sort_items'));
  3677. }
  3678. if ($end === 0)
  3679. {
  3680. return array_slice($items, $start);
  3681. }
  3682. else
  3683. {
  3684. return array_slice($items, $start, $end);
  3685. }
  3686. }
  3687. else
  3688. {
  3689. trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
  3690. return array();
  3691. }
  3692. }
  3693. }
  3694. class SimplePie_Credit
  3695. {
  3696. var $role;
  3697. var $scheme;
  3698. var $name;
  3699. // Constructor, used to input the data
  3700. public function __construct($role = null, $scheme = null, $name = null)
  3701. {
  3702. $this->role = $role;
  3703. $this->scheme = $scheme;
  3704. $this->name = $name;
  3705. }
  3706. public function __toString()
  3707. {
  3708. // There is no $this->data here
  3709. return md5(serialize($this));
  3710. }
  3711. public function get_role()
  3712. {
  3713. if ($this->role !== null)
  3714. {
  3715. return $this->role;
  3716. }
  3717. else
  3718. {
  3719. return null;
  3720. }
  3721. }
  3722. public function get_scheme()
  3723. {
  3724. if ($this->scheme !== null)
  3725. {
  3726. return $this->scheme;
  3727. }
  3728. else
  3729. {
  3730. return null;
  3731. }
  3732. }
  3733. public function get_name()
  3734. {
  3735. if ($this->name !== null)
  3736. {
  3737. return $this->name;
  3738. }
  3739. else
  3740. {
  3741. return null;
  3742. }
  3743. }
  3744. }
  3745. /**
  3746. * Decode HTML Entities
  3747. *
  3748. * This implements HTML5 as of revision 967 (2007-06-28)
  3749. *
  3750. * @package SimplePie
  3751. */
  3752. class SimplePie_Decode_HTML_Entities
  3753. {
  3754. /**
  3755. * Data to be parsed
  3756. *
  3757. * @access private
  3758. * @var string
  3759. */
  3760. var $data = '';
  3761. /**
  3762. * Currently consumed bytes
  3763. *
  3764. * @access private
  3765. * @var string
  3766. */
  3767. var $consumed = '';
  3768. /**
  3769. * Position of the current byte being parsed
  3770. *
  3771. * @access private
  3772. * @var int
  3773. */
  3774. var $position = 0;
  3775. /**
  3776. * Create an instance of the class with the input data
  3777. *
  3778. * @access public
  3779. * @param string $data Input data
  3780. */
  3781. public function __construct($data)
  3782. {
  3783. $this->data = $data;
  3784. }
  3785. /**
  3786. * Parse the input data
  3787. *
  3788. * @access public
  3789. * @return string Output data
  3790. */
  3791. public function parse()
  3792. {
  3793. while (($this->position = strpos($this->data, '&', $this->position)) !== false)
  3794. {
  3795. $this->consume();
  3796. $this->entity();
  3797. $this->consumed = '';
  3798. }
  3799. return $this->data;
  3800. }
  3801. /**
  3802. * Consume the next byte
  3803. *
  3804. * @access private
  3805. * @return mixed The next byte, or false, if there is no more data
  3806. */
  3807. public function consume()
  3808. {
  3809. if (isset($this->data[$this->position]))
  3810. {
  3811. $this->consumed .= $this->data[$this->position];
  3812. return $this->data[$this->position++];
  3813. }
  3814. else
  3815. {
  3816. return false;
  3817. }
  3818. }
  3819. /**
  3820. * Consume a range of characters
  3821. *
  3822. * @access private
  3823. * @param string $chars Characters to consume
  3824. * @return mixed A series of characters that match the range, or false
  3825. */
  3826. public function consume_range($chars)
  3827. {
  3828. if ($len = strspn($this->data, $chars, $this->position))
  3829. {
  3830. $data = substr($this->data, $this->position, $len);
  3831. $this->consumed .= $data;
  3832. $this->position += $len;
  3833. return $data;
  3834. }
  3835. else
  3836. {
  3837. return false;
  3838. }
  3839. }
  3840. /**
  3841. * Unconsume one byte
  3842. *
  3843. * @access private
  3844. */
  3845. public function unconsume()
  3846. {
  3847. $this->consumed = substr($this->consumed, 0, -1);
  3848. $this->position--;
  3849. }
  3850. /**
  3851. * Decode an entity
  3852. *
  3853. * @access private
  3854. */
  3855. public function entity()
  3856. {
  3857. switch ($this->consume())
  3858. {
  3859. case "\x09":
  3860. case "\x0A":
  3861. case "\x0B":
  3862. case "\x0B":
  3863. case "\x0C":
  3864. case "\x20":
  3865. case "\x3C":
  3866. case "\x26":
  3867. case false:
  3868. break;
  3869. case "\x23":
  3870. switch ($this->consume())
  3871. {
  3872. case "\x78":
  3873. case "\x58":
  3874. $range = '0123456789ABCDEFabcdef';
  3875. $hex = true;
  3876. break;
  3877. default:
  3878. $range = '0123456789';
  3879. $hex = false;
  3880. $this->unconsume();
  3881. break;
  3882. }
  3883. if ($codepoint = $this->consume_range($range))
  3884. {
  3885. static $windows_1252_specials = array(0x0D => "\x0A", 0x80 => "\xE2\x82\xAC", 0x81 => "\xEF\xBF\xBD", 0x82 => "\xE2\x80\x9A", 0x83 => "\xC6\x92", 0x84 => "\xE2\x80\x9E", 0x85 => "\xE2\x80\xA6", 0x86 => "\xE2\x80\xA0", 0x87 => "\xE2\x80\xA1", 0x88 => "\xCB\x86", 0x89 => "\xE2\x80\xB0", 0x8A => "\xC5\xA0", 0x8B => "\xE2\x80\xB9", 0x8C => "\xC5\x92", 0x8D => "\xEF\xBF\xBD", 0x8E => "\xC5\xBD", 0x8F => "\xEF\xBF\xBD", 0x90 => "\xEF\xBF\xBD", 0x91 => "\xE2\x80\x98", 0x92 => "\xE2\x80\x99", 0x93 => "\xE2\x80\x9C", 0x94 => "\xE2\x80\x9D", 0x95 => "\xE2\x80\xA2", 0x96 => "\xE2\x80\x93", 0x97 => "\xE2\x80\x94", 0x98 => "\xCB\x9C", 0x99 => "\xE2\x84\xA2", 0x9A => "\xC5\xA1", 0x9B => "\xE2\x80\xBA", 0x9C => "\xC5\x93", 0x9D => "\xEF\xBF\xBD", 0x9E => "\xC5\xBE", 0x9F => "\xC5\xB8");
  3886. if ($hex)
  3887. {
  3888. $codepoint = hexdec($codepoint);
  3889. }
  3890. else
  3891. {
  3892. $codepoint = intval($codepoint);
  3893. }
  3894. if (isset($windows_1252_specials[$codepoint]))
  3895. {
  3896. $replacement = $windows_1252_specials[$codepoint];
  3897. }
  3898. else
  3899. {
  3900. $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
  3901. }
  3902. if (!in_array($this->consume(), array(';', false), true))
  3903. {
  3904. $this->unconsume();
  3905. }
  3906. $consumed_length = strlen($this->consumed);
  3907. $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
  3908. $this->position += strlen($replacement) - $consumed_length;
  3909. }
  3910. break;
  3911. default:
  3912. static $entities = array('Aacute' => "\xC3\x81", 'aacute' => "\xC3\xA1", 'Aacute;' => "\xC3\x81", 'aacute;' => "\xC3\xA1", 'Acirc' => "\xC3\x82", 'acirc' => "\xC3\xA2", 'Acirc;' => "\xC3\x82", 'acirc;' => "\xC3\xA2", 'acute' => "\xC2\xB4", 'acute;' => "\xC2\xB4", 'AElig' => "\xC3\x86", 'aelig' => "\xC3\xA6", 'AElig;' => "\xC3\x86", 'aelig;' => "\xC3\xA6", 'Agrave' => "\xC3\x80", 'agrave' => "\xC3\xA0", 'Agrave;' => "\xC3\x80", 'agrave;' => "\xC3\xA0", 'alefsym;' => "\xE2\x84\xB5", 'Alpha;' => "\xCE\x91", 'alpha;' => "\xCE\xB1", 'AMP' => "\x26", 'amp' => "\x26", 'AMP;' => "\x26", 'amp;' => "\x26", 'and;' => "\xE2\x88\xA7", 'ang;' => "\xE2\x88\xA0", 'apos;' => "\x27", 'Aring' => "\xC3\x85", 'aring' => "\xC3\xA5", 'Aring;' => "\xC3\x85", 'aring;' => "\xC3\xA5", 'asymp;' => "\xE2\x89\x88", 'Atilde' => "\xC3\x83", 'atilde' => "\xC3\xA3", 'Atilde;' => "\xC3\x83", 'atilde;' => "\xC3\xA3", 'Auml' => "\xC3\x84", 'auml' => "\xC3\xA4", 'Auml;' => "\xC3\x84", 'auml;' => "\xC3\xA4", 'bdquo;' => "\xE2\x80\x9E", 'Beta;' => "\xCE\x92", 'beta;' => "\xCE\xB2", 'brvbar' => "\xC2\xA6", 'brvbar;' => "\xC2\xA6", 'bull;' => "\xE2\x80\xA2", 'cap;' => "\xE2\x88\xA9", 'Ccedil' => "\xC3\x87", 'ccedil' => "\xC3\xA7", 'Ccedil;' => "\xC3\x87", 'ccedil;' => "\xC3\xA7", 'cedil' => "\xC2\xB8", 'cedil;' => "\xC2\xB8", 'cent' => "\xC2\xA2", 'cent;' => "\xC2\xA2", 'Chi;' => "\xCE\xA7", 'chi;' => "\xCF\x87", 'circ;' => "\xCB\x86", 'clubs;' => "\xE2\x99\xA3", 'cong;' => "\xE2\x89\x85", 'COPY' => "\xC2\xA9", 'copy' => "\xC2\xA9", 'COPY;' => "\xC2\xA9", 'copy;' => "\xC2\xA9", 'crarr;' => "\xE2\x86\xB5", 'cup;' => "\xE2\x88\xAA", 'curren' => "\xC2\xA4", 'curren;' => "\xC2\xA4", 'Dagger;' => "\xE2\x80\xA1", 'dagger;' => "\xE2\x80\xA0", 'dArr;' => "\xE2\x87\x93", 'darr;' => "\xE2\x86\x93", 'deg' => "\xC2\xB0", 'deg;' => "\xC2\xB0", 'Delta;' => "\xCE\x94", 'delta;' => "\xCE\xB4", 'diams;' => "\xE2\x99\xA6", 'divide' => "\xC3\xB7", 'divide;' => "\xC3\xB7", 'Eacute' => "\xC3\x89", 'eacute' => "\xC3\xA9", 'Eacute;' => "\xC3\x89", 'eacute;' => "\xC3\xA9", 'Ecirc' => "\xC3\x8A", 'ecirc' => "\xC3\xAA", 'Ecirc;' => "\xC3\x8A", 'ecirc;' => "\xC3\xAA", 'Egrave' => "\xC3\x88", 'egrave' => "\xC3\xA8", 'Egrave;' => "\xC3\x88", 'egrave;' => "\xC3\xA8", 'empty;' => "\xE2\x88\x85", 'emsp;' => "\xE2\x80\x83", 'ensp;' => "\xE2\x80\x82", 'Epsilon;' => "\xCE\x95", 'epsilon;' => "\xCE\xB5", 'equiv;' => "\xE2\x89\xA1", 'Eta;' => "\xCE\x97", 'eta;' => "\xCE\xB7", 'ETH' => "\xC3\x90", 'eth' => "\xC3\xB0", 'ETH;' => "\xC3\x90", 'eth;' => "\xC3\xB0", 'Euml' => "\xC3\x8B", 'euml' => "\xC3\xAB", 'Euml;' => "\xC3\x8B", 'euml;' => "\xC3\xAB", 'euro;' => "\xE2\x82\xAC", 'exist;' => "\xE2\x88\x83", 'fnof;' => "\xC6\x92", 'forall;' => "\xE2\x88\x80", 'frac12' => "\xC2\xBD", 'frac12;' => "\xC2\xBD", 'frac14' => "\xC2\xBC", 'frac14;' => "\xC2\xBC", 'frac34' => "\xC2\xBE", 'frac34;' => "\xC2\xBE", 'frasl;' => "\xE2\x81\x84", 'Gamma;' => "\xCE\x93", 'gamma;' => "\xCE\xB3", 'ge;' => "\xE2\x89\xA5", 'GT' => "\x3E", 'gt' => "\x3E", 'GT;' => "\x3E", 'gt;' => "\x3E", 'hArr;' => "\xE2\x87\x94", 'harr;' => "\xE2\x86\x94", 'hearts;' => "\xE2\x99\xA5", 'hellip;' => "\xE2\x80\xA6", 'Iacute' => "\xC3\x8D", 'iacute' => "\xC3\xAD", 'Iacute;' => "\xC3\x8D", 'iacute;' => "\xC3\xAD", 'Icirc' => "\xC3\x8E", 'icirc' => "\xC3\xAE", 'Icirc;' => "\xC3\x8E", 'icirc;' => "\xC3\xAE", 'iexcl' => "\xC2\xA1", 'iexcl;' => "\xC2\xA1", 'Igrave' => "\xC3\x8C", 'igrave' => "\xC3\xAC", 'Igrave;' => "\xC3\x8C", 'igrave;' => "\xC3\xAC", 'image;' => "\xE2\x84\x91", 'infin;' => "\xE2\x88\x9E", 'int;' => "\xE2\x88\xAB", 'Iota;' => "\xCE\x99", 'iota;' => "\xCE\xB9", 'iquest' => "\xC2\xBF", 'iquest;' => "\xC2\xBF", 'isin;' => "\xE2\x88\x88", 'Iuml' => "\xC3\x8F", 'iuml' => "\xC3\xAF", 'Iuml;' => "\xC3\x8F", 'iuml;' => "\xC3\xAF", 'Kappa;' => "\xCE\x9A", 'kappa;' => "\xCE\xBA", 'Lambda;' => "\xCE\x9B", 'lambda;' => "\xCE\xBB", 'lang;' => "\xE3\x80\x88", 'laquo' => "\xC2\xAB", 'laquo;' => "\xC2\xAB", 'lArr;' => "\xE2\x87\x90", 'larr;' => "\xE2\x86\x90", 'lceil;' => "\xE2\x8C\x88", 'ldquo;' => "\xE2\x80\x9C", 'le;' => "\xE2\x89\xA4", 'lfloor;' => "\xE2\x8C\x8A", 'lowast;' => "\xE2\x88\x97", 'loz;' => "\xE2\x97\x8A", 'lrm;' => "\xE2\x80\x8E", 'lsaquo;' => "\xE2\x80\xB9", 'lsquo;' => "\xE2\x80\x98", 'LT' => "\x3C", 'lt' => "\x3C", 'LT;' => "\x3C", 'lt;' => "\x3C", 'macr' => "\xC2\xAF", 'macr;' => "\xC2\xAF", 'mdash;' => "\xE2\x80\x94", 'micro' => "\xC2\xB5", 'micro;' => "\xC2\xB5", 'middot' => "\xC2\xB7", 'middot;' => "\xC2\xB7", 'minus;' => "\xE2\x88\x92", 'Mu;' => "\xCE\x9C", 'mu;' => "\xCE\xBC", 'nabla;' => "\xE2\x88\x87", 'nbsp' => "\xC2\xA0", 'nbsp;' => "\xC2\xA0", 'ndash;' => "\xE2\x80\x93", 'ne;' => "\xE2\x89\xA0", 'ni;' => "\xE2\x88\x8B", 'not' => "\xC2\xAC", 'not;' => "\xC2\xAC", 'notin;' => "\xE2\x88\x89", 'nsub;' => "\xE2\x8A\x84", 'Ntilde' => "\xC3\x91", 'ntilde' => "\xC3\xB1", 'Ntilde;' => "\xC3\x91", 'ntilde;' => "\xC3\xB1", 'Nu;' => "\xCE\x9D", 'nu;' => "\xCE\xBD", 'Oacute' => "\xC3\x93", 'oacute' => "\xC3\xB3", 'Oacute;' => "\xC3\x93", 'oacute;' => "\xC3\xB3", 'Ocirc' => "\xC3\x94", 'ocirc' => "\xC3\xB4", 'Ocirc;' => "\xC3\x94", 'ocirc;' => "\xC3\xB4", 'OElig;' => "\xC5\x92", 'oelig;' => "\xC5\x93", 'Ograve' => "\xC3\x92", 'ograve' => "\xC3\xB2", 'Ograve;' => "\xC3\x92", 'ograve;' => "\xC3\xB2", 'oline;' => "\xE2\x80\xBE", 'Omega;' => "\xCE\xA9", 'omega;' => "\xCF\x89", 'Omicron;' => "\xCE\x9F", 'omicron;' => "\xCE\xBF", 'oplus;' => "\xE2\x8A\x95", 'or;' => "\xE2\x88\xA8", 'ordf' => "\xC2\xAA", 'ordf;' => "\xC2\xAA", 'ordm' => "\xC2\xBA", 'ordm;' => "\xC2\xBA", 'Oslash' => "\xC3\x98", 'oslash' => "\xC3\xB8", 'Oslash;' => "\xC3\x98", 'oslash;' => "\xC3\xB8", 'Otilde' => "\xC3\x95", 'otilde' => "\xC3\xB5", 'Otilde;' => "\xC3\x95", 'otilde;' => "\xC3\xB5", 'otimes;' => "\xE2\x8A\x97", 'Ouml' => "\xC3\x96", 'ouml' => "\xC3\xB6", 'Ouml;' => "\xC3\x96", 'ouml;' => "\xC3\xB6", 'para' => "\xC2\xB6", 'para;' => "\xC2\xB6", 'part;' => "\xE2\x88\x82", 'permil;' => "\xE2\x80\xB0", 'perp;' => "\xE2\x8A\xA5", 'Phi;' => "\xCE\xA6", 'phi;' => "\xCF\x86", 'Pi;' => "\xCE\xA0", 'pi;' => "\xCF\x80", 'piv;' => "\xCF\x96", 'plusmn' => "\xC2\xB1", 'plusmn;' => "\xC2\xB1", 'pound' => "\xC2\xA3", 'pound;' => "\xC2\xA3", 'Prime;' => "\xE2\x80\xB3", 'prime;' => "\xE2\x80\xB2", 'prod;' => "\xE2\x88\x8F", 'prop;' => "\xE2\x88\x9D", 'Psi;' => "\xCE\xA8", 'psi;' => "\xCF\x88", 'QUOT' => "\x22", 'quot' => "\x22", 'QUOT;' => "\x22", 'quot;' => "\x22", 'radic;' => "\xE2\x88\x9A", 'rang;' => "\xE3\x80\x89", 'raquo' => "\xC2\xBB", 'raquo;' => "\xC2\xBB", 'rArr;' => "\xE2\x87\x92", 'rarr;' => "\xE2\x86\x92", 'rceil;' => "\xE2\x8C\x89", 'rdquo;' => "\xE2\x80\x9D", 'real;' => "\xE2\x84\x9C", 'REG' => "\xC2\xAE", 'reg' => "\xC2\xAE", 'REG;' => "\xC2\xAE", 'reg;' => "\xC2\xAE", 'rfloor;' => "\xE2\x8C\x8B", 'Rho;' => "\xCE\xA1", 'rho;' => "\xCF\x81", 'rlm;' => "\xE2\x80\x8F", 'rsaquo;' => "\xE2\x80\xBA", 'rsquo;' => "\xE2\x80\x99", 'sbquo;' => "\xE2\x80\x9A", 'Scaron;' => "\xC5\xA0", 'scaron;' => "\xC5\xA1", 'sdot;' => "\xE2\x8B\x85", 'sect' => "\xC2\xA7", 'sect;' => "\xC2\xA7", 'shy' => "\xC2\xAD", 'shy;' => "\xC2\xAD", 'Sigma;' => "\xCE\xA3", 'sigma;' => "\xCF\x83", 'sigmaf;' => "\xCF\x82", 'sim;' => "\xE2\x88\xBC", 'spades;' => "\xE2\x99\xA0", 'sub;' => "\xE2\x8A\x82", 'sube;' => "\xE2\x8A\x86", 'sum;' => "\xE2\x88\x91", 'sup;' => "\xE2\x8A\x83", 'sup1' => "\xC2\xB9", 'sup1;' => "\xC2\xB9", 'sup2' => "\xC2\xB2", 'sup2;' => "\xC2\xB2", 'sup3' => "\xC2\xB3", 'sup3;' => "\xC2\xB3", 'supe;' => "\xE2\x8A\x87", 'szlig' => "\xC3\x9F", 'szlig;' => "\xC3\x9F", 'Tau;' => "\xCE\xA4", 'tau;' => "\xCF\x84", 'there4;' => "\xE2\x88\xB4", 'Theta;' => "\xCE\x98", 'theta;' => "\xCE\xB8", 'thetasym;' => "\xCF\x91", 'thinsp;' => "\xE2\x80\x89", 'THORN' => "\xC3\x9E", 'thorn' => "\xC3\xBE", 'THORN;' => "\xC3\x9E", 'thorn;' => "\xC3\xBE", 'tilde;' => "\xCB\x9C", 'times' => "\xC3\x97", 'times;' => "\xC3\x97", 'TRADE;' => "\xE2\x84\xA2", 'trade;' => "\xE2\x84\xA2", 'Uacute' => "\xC3\x9A", 'uacute' => "\xC3\xBA", 'Uacute;' => "\xC3\x9A", 'uacute;' => "\xC3\xBA", 'uArr;' => "\xE2\x87\x91", 'uarr;' => "\xE2\x86\x91", 'Ucirc' => "\xC3\x9B", 'ucirc' => "\xC3\xBB", 'Ucirc;' => "\xC3\x9B", 'ucirc;' => "\xC3\xBB", 'Ugrave' => "\xC3\x99", 'ugrave' => "\xC3\xB9", 'Ugrave;' => "\xC3\x99", 'ugrave;' => "\xC3\xB9", 'uml' => "\xC2\xA8", 'uml;' => "\xC2\xA8", 'upsih;' => "\xCF\x92", 'Upsilon;' => "\xCE\xA5", 'upsilon;' => "\xCF\x85", 'Uuml' => "\xC3\x9C", 'uuml' => "\xC3\xBC", 'Uuml;' => "\xC3\x9C", 'uuml;' => "\xC3\xBC", 'weierp;' => "\xE2\x84\x98", 'Xi;' => "\xCE\x9E", 'xi;' => "\xCE\xBE", 'Yacute' => "\xC3\x9D", 'yacute' => "\xC3\xBD", 'Yacute;' => "\xC3\x9D", 'yacute;' => "\xC3\xBD", 'yen' => "\xC2\xA5", 'yen;' => "\xC2\xA5", 'yuml' => "\xC3\xBF", 'Yuml;' => "\xC5\xB8", 'yuml;' => "\xC3\xBF", 'Zeta;' => "\xCE\x96", 'zeta;' => "\xCE\xB6", 'zwj;' => "\xE2\x80\x8D", 'zwnj;' => "\xE2\x80\x8C");
  3913. for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
  3914. {
  3915. $consumed = substr($this->consumed, 1);
  3916. if (isset($entities[$consumed]))
  3917. {
  3918. $match = $consumed;
  3919. }
  3920. }
  3921. if ($match !== null)
  3922. {
  3923. $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
  3924. $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
  3925. }
  3926. break;
  3927. }
  3928. }
  3929. }
  3930. class SimplePie_Enclosure
  3931. {
  3932. var $bitrate;
  3933. var $captions;
  3934. var $categories;
  3935. var $channels;
  3936. var $copyright;
  3937. var $credits;
  3938. var $description;
  3939. var $duration;
  3940. var $expression;
  3941. var $framerate;
  3942. var $handler;
  3943. var $hashes;
  3944. var $height;
  3945. var $javascript;
  3946. var $keywords;
  3947. var $lang;
  3948. var $length;
  3949. var $link;
  3950. var $medium;
  3951. var $player;
  3952. var $ratings;
  3953. var $restrictions;
  3954. var $samplingrate;
  3955. var $thumbnails;
  3956. var $title;
  3957. var $type;
  3958. var $width;
  3959. // Constructor, used to input the data
  3960. public function __construct($link = null, $type = null, $length = null, $javascript = null, $bitrate = null, $captions = null, $categories = null, $channels = null, $copyright = null, $credits = null, $description = null, $duration = null, $expression = null, $framerate = null, $hashes = null, $height = null, $keywords = null, $lang = null, $medium = null, $player = null, $ratings = null, $restrictions = null, $samplingrate = null, $thumbnails = null, $title = null, $width = null)
  3961. {
  3962. $this->bitrate = $bitrate;
  3963. $this->captions = $captions;
  3964. $this->categories = $categories;
  3965. $this->channels = $channels;
  3966. $this->copyright = $copyright;
  3967. $this->credits = $credits;
  3968. $this->description = $description;
  3969. $this->duration = $duration;
  3970. $this->expression = $expression;
  3971. $this->framerate = $framerate;
  3972. $this->hashes = $hashes;
  3973. $this->height = $height;
  3974. $this->keywords = $keywords;
  3975. $this->lang = $lang;
  3976. $this->length = $length;
  3977. $this->link = $link;
  3978. $this->medium = $medium;
  3979. $this->player = $player;
  3980. $this->ratings = $ratings;
  3981. $this->restrictions = $restrictions;
  3982. $this->samplingrate = $samplingrate;
  3983. $this->thumbnails = $thumbnails;
  3984. $this->title = $title;
  3985. $this->type = $type;
  3986. $this->width = $width;
  3987. if (class_exists('idna_convert'))
  3988. {
  3989. $idn = new idna_convert();
  3990. $parsed = SimplePie_Misc::parse_url($link);
  3991. $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  3992. }
  3993. $this->handler = $this->get_handler(); // Needs to load last
  3994. }
  3995. public function __toString()
  3996. {
  3997. // There is no $this->data here
  3998. return md5(serialize($this));
  3999. }
  4000. public function get_bitrate()
  4001. {
  4002. if ($this->bitrate !== null)
  4003. {
  4004. return $this->bitrate;
  4005. }
  4006. else
  4007. {
  4008. return null;
  4009. }
  4010. }
  4011. public function get_caption($key = 0)
  4012. {
  4013. $captions = $this->get_captions();
  4014. if (isset($captions[$key]))
  4015. {
  4016. return $captions[$key];
  4017. }
  4018. else
  4019. {
  4020. return null;
  4021. }
  4022. }
  4023. public function get_captions()
  4024. {
  4025. if ($this->captions !== null)
  4026. {
  4027. return $this->captions;
  4028. }
  4029. else
  4030. {
  4031. return null;
  4032. }
  4033. }
  4034. public function get_category($key = 0)
  4035. {
  4036. $categories = $this->get_categories();
  4037. if (isset($categories[$key]))
  4038. {
  4039. return $categories[$key];
  4040. }
  4041. else
  4042. {
  4043. return null;
  4044. }
  4045. }
  4046. public function get_categories()
  4047. {
  4048. if ($this->categories !== null)
  4049. {
  4050. return $this->categories;
  4051. }
  4052. else
  4053. {
  4054. return null;
  4055. }
  4056. }
  4057. public function get_channels()
  4058. {
  4059. if ($this->channels !== null)
  4060. {
  4061. return $this->channels;
  4062. }
  4063. else
  4064. {
  4065. return null;
  4066. }
  4067. }
  4068. public function get_copyright()
  4069. {
  4070. if ($this->copyright !== null)
  4071. {
  4072. return $this->copyright;
  4073. }
  4074. else
  4075. {
  4076. return null;
  4077. }
  4078. }
  4079. public function get_credit($key = 0)
  4080. {
  4081. $credits = $this->get_credits();
  4082. if (isset($credits[$key]))
  4083. {
  4084. return $credits[$key];
  4085. }
  4086. else
  4087. {
  4088. return null;
  4089. }
  4090. }
  4091. public function get_credits()
  4092. {
  4093. if ($this->credits !== null)
  4094. {
  4095. return $this->credits;
  4096. }
  4097. else
  4098. {
  4099. return null;
  4100. }
  4101. }
  4102. public function get_description()
  4103. {
  4104. if ($this->description !== null)
  4105. {
  4106. return $this->description;
  4107. }
  4108. else
  4109. {
  4110. return null;
  4111. }
  4112. }
  4113. public function get_duration($convert = false)
  4114. {
  4115. if ($this->duration !== null)
  4116. {
  4117. if ($convert)
  4118. {
  4119. $time = SimplePie_Misc::time_hms($this->duration);
  4120. return $time;
  4121. }
  4122. else
  4123. {
  4124. return $this->duration;
  4125. }
  4126. }
  4127. else
  4128. {
  4129. return null;
  4130. }
  4131. }
  4132. public function get_expression()
  4133. {
  4134. if ($this->expression !== null)
  4135. {
  4136. return $this->expression;
  4137. }
  4138. else
  4139. {
  4140. return 'full';
  4141. }
  4142. }
  4143. public function get_extension()
  4144. {
  4145. if ($this->link !== null)
  4146. {
  4147. $url = SimplePie_Misc::parse_url($this->link);
  4148. if ($url['path'] !== '')
  4149. {
  4150. return pathinfo($url['path'], PATHINFO_EXTENSION);
  4151. }
  4152. }
  4153. return null;
  4154. }
  4155. public function get_framerate()
  4156. {
  4157. if ($this->framerate !== null)
  4158. {
  4159. return $this->framerate;
  4160. }
  4161. else
  4162. {
  4163. return null;
  4164. }
  4165. }
  4166. public function get_handler()
  4167. {
  4168. return $this->get_real_type(true);
  4169. }
  4170. public function get_hash($key = 0)
  4171. {
  4172. $hashes = $this->get_hashes();
  4173. if (isset($hashes[$key]))
  4174. {
  4175. return $hashes[$key];
  4176. }
  4177. else
  4178. {
  4179. return null;
  4180. }
  4181. }
  4182. public function get_hashes()
  4183. {
  4184. if ($this->hashes !== null)
  4185. {
  4186. return $this->hashes;
  4187. }
  4188. else
  4189. {
  4190. return null;
  4191. }
  4192. }
  4193. public function get_height()
  4194. {
  4195. if ($this->height !== null)
  4196. {
  4197. return $this->height;
  4198. }
  4199. else
  4200. {
  4201. return null;
  4202. }
  4203. }
  4204. public function get_language()
  4205. {
  4206. if ($this->lang !== null)
  4207. {
  4208. return $this->lang;
  4209. }
  4210. else
  4211. {
  4212. return null;
  4213. }
  4214. }
  4215. public function get_keyword($key = 0)
  4216. {
  4217. $keywords = $this->get_keywords();
  4218. if (isset($keywords[$key]))
  4219. {
  4220. return $keywords[$key];
  4221. }
  4222. else
  4223. {
  4224. return null;
  4225. }
  4226. }
  4227. public function get_keywords()
  4228. {
  4229. if ($this->keywords !== null)
  4230. {
  4231. return $this->keywords;
  4232. }
  4233. else
  4234. {
  4235. return null;
  4236. }
  4237. }
  4238. public function get_length()
  4239. {
  4240. if ($this->length !== null)
  4241. {
  4242. return $this->length;
  4243. }
  4244. else
  4245. {
  4246. return null;
  4247. }
  4248. }
  4249. public function get_link()
  4250. {
  4251. if ($this->link !== null)
  4252. {
  4253. return urldecode($this->link);
  4254. }
  4255. else
  4256. {
  4257. return null;
  4258. }
  4259. }
  4260. public function get_medium()
  4261. {
  4262. if ($this->medium !== null)
  4263. {
  4264. return $this->medium;
  4265. }
  4266. else
  4267. {
  4268. return null;
  4269. }
  4270. }
  4271. public function get_player()
  4272. {
  4273. if ($this->player !== null)
  4274. {
  4275. return $this->player;
  4276. }
  4277. else
  4278. {
  4279. return null;
  4280. }
  4281. }
  4282. public function get_rating($key = 0)
  4283. {
  4284. $ratings = $this->get_ratings();
  4285. if (isset($ratings[$key]))
  4286. {
  4287. return $ratings[$key];
  4288. }
  4289. else
  4290. {
  4291. return null;
  4292. }
  4293. }
  4294. public function get_ratings()
  4295. {
  4296. if ($this->ratings !== null)
  4297. {
  4298. return $this->ratings;
  4299. }
  4300. else
  4301. {
  4302. return null;
  4303. }
  4304. }
  4305. public function get_restriction($key = 0)
  4306. {
  4307. $restrictions = $this->get_restrictions();
  4308. if (isset($restrictions[$key]))
  4309. {
  4310. return $restrictions[$key];
  4311. }
  4312. else
  4313. {
  4314. return null;
  4315. }
  4316. }
  4317. public function get_restrictions()
  4318. {
  4319. if ($this->restrictions !== null)
  4320. {
  4321. return $this->restrictions;
  4322. }
  4323. else
  4324. {
  4325. return null;
  4326. }
  4327. }
  4328. public function get_sampling_rate()
  4329. {
  4330. if ($this->samplingrate !== null)
  4331. {
  4332. return $this->samplingrate;
  4333. }
  4334. else
  4335. {
  4336. return null;
  4337. }
  4338. }
  4339. public function get_size()
  4340. {
  4341. $length = $this->get_length();
  4342. if ($length !== null)
  4343. {
  4344. return round($length/1048576, 2);
  4345. }
  4346. else
  4347. {
  4348. return null;
  4349. }
  4350. }
  4351. public function get_thumbnail($key = 0)
  4352. {
  4353. $thumbnails = $this->get_thumbnails();
  4354. if (isset($thumbnails[$key]))
  4355. {
  4356. return $thumbnails[$key];
  4357. }
  4358. else
  4359. {
  4360. return null;
  4361. }
  4362. }
  4363. public function get_thumbnails()
  4364. {
  4365. if ($this->thumbnails !== null)
  4366. {
  4367. return $this->thumbnails;
  4368. }
  4369. else
  4370. {
  4371. return null;
  4372. }
  4373. }
  4374. public function get_title()
  4375. {
  4376. if ($this->title !== null)
  4377. {
  4378. return $this->title;
  4379. }
  4380. else
  4381. {
  4382. return null;
  4383. }
  4384. }
  4385. public function get_type()
  4386. {
  4387. if ($this->type !== null)
  4388. {
  4389. return $this->type;
  4390. }
  4391. else
  4392. {
  4393. return null;
  4394. }
  4395. }
  4396. public function get_width()
  4397. {
  4398. if ($this->width !== null)
  4399. {
  4400. return $this->width;
  4401. }
  4402. else
  4403. {
  4404. return null;
  4405. }
  4406. }
  4407. public function native_embed($options='')
  4408. {
  4409. return $this->embed($options, true);
  4410. }
  4411. /**
  4412. * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
  4413. */
  4414. public function embed($options = '', $native = false)
  4415. {
  4416. // Set up defaults
  4417. $audio = '';
  4418. $video = '';
  4419. $alt = '';
  4420. $altclass = '';
  4421. $loop = 'false';
  4422. $width = 'auto';
  4423. $height = 'auto';
  4424. $bgcolor = '#ffffff';
  4425. $mediaplayer = '';
  4426. $widescreen = false;
  4427. $handler = $this->get_handler();
  4428. $type = $this->get_real_type();
  4429. // Process options and reassign values as necessary
  4430. if (is_array($options))
  4431. {
  4432. extract($options);
  4433. }
  4434. else
  4435. {
  4436. $options = explode(',', $options);
  4437. foreach($options as $option)
  4438. {
  4439. $opt = explode(':', $option, 2);
  4440. if (isset($opt[0], $opt[1]))
  4441. {
  4442. $opt[0] = trim($opt[0]);
  4443. $opt[1] = trim($opt[1]);
  4444. switch ($opt[0])
  4445. {
  4446. case 'audio':
  4447. $audio = $opt[1];
  4448. break;
  4449. case 'video':
  4450. $video = $opt[1];
  4451. break;
  4452. case 'alt':
  4453. $alt = $opt[1];
  4454. break;
  4455. case 'altclass':
  4456. $altclass = $opt[1];
  4457. break;
  4458. case 'loop':
  4459. $loop = $opt[1];
  4460. break;
  4461. case 'width':
  4462. $width = $opt[1];
  4463. break;
  4464. case 'height':
  4465. $height = $opt[1];
  4466. break;
  4467. case 'bgcolor':
  4468. $bgcolor = $opt[1];
  4469. break;
  4470. case 'mediaplayer':
  4471. $mediaplayer = $opt[1];
  4472. break;
  4473. case 'widescreen':
  4474. $widescreen = $opt[1];
  4475. break;
  4476. }
  4477. }
  4478. }
  4479. }
  4480. $mime = explode('/', $type, 2);
  4481. $mime = $mime[0];
  4482. // Process values for 'auto'
  4483. if ($width === 'auto')
  4484. {
  4485. if ($mime === 'video')
  4486. {
  4487. if ($height === 'auto')
  4488. {
  4489. $width = 480;
  4490. }
  4491. elseif ($widescreen)
  4492. {
  4493. $width = round((intval($height)/9)*16);
  4494. }
  4495. else
  4496. {
  4497. $width = round((intval($height)/3)*4);
  4498. }
  4499. }
  4500. else
  4501. {
  4502. $width = '100%';
  4503. }
  4504. }
  4505. if ($height === 'auto')
  4506. {
  4507. if ($mime === 'audio')
  4508. {
  4509. $height = 0;
  4510. }
  4511. elseif ($mime === 'video')
  4512. {
  4513. if ($width === 'auto')
  4514. {
  4515. if ($widescreen)
  4516. {
  4517. $height = 270;
  4518. }
  4519. else
  4520. {
  4521. $height = 360;
  4522. }
  4523. }
  4524. elseif ($widescreen)
  4525. {
  4526. $height = round((intval($width)/16)*9);
  4527. }
  4528. else
  4529. {
  4530. $height = round((intval($width)/4)*3);
  4531. }
  4532. }
  4533. else
  4534. {
  4535. $height = 376;
  4536. }
  4537. }
  4538. elseif ($mime === 'audio')
  4539. {
  4540. $height = 0;
  4541. }
  4542. // Set proper placeholder value
  4543. if ($mime === 'audio')
  4544. {
  4545. $placeholder = $audio;
  4546. }
  4547. elseif ($mime === 'video')
  4548. {
  4549. $placeholder = $video;
  4550. }
  4551. $embed = '';
  4552. // Odeo Feed MP3's
  4553. if ($handler === 'odeo')
  4554. {
  4555. if ($native)
  4556. {
  4557. $embed .= '<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://adobe.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url=' . $this->get_link() . '"></embed>';
  4558. }
  4559. else
  4560. {
  4561. $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
  4562. }
  4563. }
  4564. // Flash
  4565. elseif ($handler === 'flash')
  4566. {
  4567. if ($native)
  4568. {
  4569. $embed .= "<embed src=\"" . $this->get_link() . "\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"$type\" quality=\"high\" width=\"$width\" height=\"$height\" bgcolor=\"$bgcolor\" loop=\"$loop\"></embed>";
  4570. }
  4571. else
  4572. {
  4573. $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
  4574. }
  4575. }
  4576. // Flash Media Player file types.
  4577. // Preferred handler for MP3 file types.
  4578. elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
  4579. {
  4580. $height += 20;
  4581. if ($native)
  4582. {
  4583. $embed .= "<embed src=\"$mediaplayer\" pluginspage=\"http://adobe.com/go/getflashplayer\" type=\"application/x-shockwave-flash\" quality=\"high\" width=\"$width\" height=\"$height\" wmode=\"transparent\" flashvars=\"file=" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "&autostart=false&repeat=$loop&showdigits=true&showfsbutton=false\"></embed>";
  4584. }
  4585. else
  4586. {
  4587. $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
  4588. }
  4589. }
  4590. // QuickTime 7 file types. Need to test with QuickTime 6.
  4591. // Only handle MP3's if the Flash Media Player is not present.
  4592. elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
  4593. {
  4594. $height += 16;
  4595. if ($native)
  4596. {
  4597. if ($placeholder !== '')
  4598. {
  4599. $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" href=\"" . $this->get_link() . "\" src=\"$placeholder\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"false\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
  4600. }
  4601. else
  4602. {
  4603. $embed .= "<embed type=\"$type\" style=\"cursor:hand; cursor:pointer;\" src=\"" . $this->get_link() . "\" width=\"$width\" height=\"$height\" autoplay=\"false\" target=\"myself\" controller=\"true\" loop=\"$loop\" scale=\"aspect\" bgcolor=\"$bgcolor\" pluginspage=\"http://apple.com/quicktime/download/\"></embed>";
  4604. }
  4605. }
  4606. else
  4607. {
  4608. $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
  4609. }
  4610. }
  4611. // Windows Media
  4612. elseif ($handler === 'wmedia')
  4613. {
  4614. $height += 45;
  4615. if ($native)
  4616. {
  4617. $embed .= "<embed type=\"application/x-mplayer2\" src=\"" . $this->get_link() . "\" autosize=\"1\" width=\"$width\" height=\"$height\" showcontrols=\"1\" showstatusbar=\"0\" showdisplay=\"0\" autostart=\"0\"></embed>";
  4618. }
  4619. else
  4620. {
  4621. $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
  4622. }
  4623. }
  4624. // Everything else
  4625. else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
  4626. return $embed;
  4627. }
  4628. public function get_real_type($find_handler = false)
  4629. {
  4630. // If it's Odeo, let's get it out of the way.
  4631. if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
  4632. {
  4633. return 'odeo';
  4634. }
  4635. // Mime-types by handler.
  4636. $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
  4637. $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
  4638. $types_quicktime = array('audio/3gpp', 'audio/3gpp2', 'audio/aac', 'audio/x-aac', 'audio/aiff', 'audio/x-aiff', 'audio/mid', 'audio/midi', 'audio/x-midi', 'audio/mp4', 'audio/m4a', 'audio/x-m4a', 'audio/wav', 'audio/x-wav', 'video/3gpp', 'video/3gpp2', 'video/m4v', 'video/x-m4v', 'video/mp4', 'video/mpeg', 'video/x-mpeg', 'video/quicktime', 'video/sd-video'); // QuickTime
  4639. $types_wmedia = array('application/asx', 'application/x-mplayer2', 'audio/x-ms-wma', 'audio/x-ms-wax', 'video/x-ms-asf-plugin', 'video/x-ms-asf', 'video/x-ms-wm', 'video/x-ms-wmv', 'video/x-ms-wvx'); // Windows Media
  4640. $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
  4641. if ($this->get_type() !== null)
  4642. {
  4643. $type = strtolower($this->type);
  4644. }
  4645. else
  4646. {
  4647. $type = null;
  4648. }
  4649. // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
  4650. if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
  4651. {
  4652. switch (strtolower($this->get_extension()))
  4653. {
  4654. // Audio mime-types
  4655. case 'aac':
  4656. case 'adts':
  4657. $type = 'audio/acc';
  4658. break;
  4659. case 'aif':
  4660. case 'aifc':
  4661. case 'aiff':
  4662. case 'cdda':
  4663. $type = 'audio/aiff';
  4664. break;
  4665. case 'bwf':
  4666. $type = 'audio/wav';
  4667. break;
  4668. case 'kar':
  4669. case 'mid':
  4670. case 'midi':
  4671. case 'smf':
  4672. $type = 'audio/midi';
  4673. break;
  4674. case 'm4a':
  4675. $type = 'audio/x-m4a';
  4676. break;
  4677. case 'mp3':
  4678. case 'swa':
  4679. $type = 'audio/mp3';
  4680. break;
  4681. case 'wav':
  4682. $type = 'audio/wav';
  4683. break;
  4684. case 'wax':
  4685. $type = 'audio/x-ms-wax';
  4686. break;
  4687. case 'wma':
  4688. $type = 'audio/x-ms-wma';
  4689. break;
  4690. // Video mime-types
  4691. case '3gp':
  4692. case '3gpp':
  4693. $type = 'video/3gpp';
  4694. break;
  4695. case '3g2':
  4696. case '3gp2':
  4697. $type = 'video/3gpp2';
  4698. break;
  4699. case 'asf':
  4700. $type = 'video/x-ms-asf';
  4701. break;
  4702. case 'flv':
  4703. $type = 'video/x-flv';
  4704. break;
  4705. case 'm1a':
  4706. case 'm1s':
  4707. case 'm1v':
  4708. case 'm15':
  4709. case 'm75':
  4710. case 'mp2':
  4711. case 'mpa':
  4712. case 'mpeg':
  4713. case 'mpg':
  4714. case 'mpm':
  4715. case 'mpv':
  4716. $type = 'video/mpeg';
  4717. break;
  4718. case 'm4v':
  4719. $type = 'video/x-m4v';
  4720. break;
  4721. case 'mov':
  4722. case 'qt':
  4723. $type = 'video/quicktime';
  4724. break;
  4725. case 'mp4':
  4726. case 'mpg4':
  4727. $type = 'video/mp4';
  4728. break;
  4729. case 'sdv':
  4730. $type = 'video/sd-video';
  4731. break;
  4732. case 'wm':
  4733. $type = 'video/x-ms-wm';
  4734. break;
  4735. case 'wmv':
  4736. $type = 'video/x-ms-wmv';
  4737. break;
  4738. case 'wvx':
  4739. $type = 'video/x-ms-wvx';
  4740. break;
  4741. // Flash mime-types
  4742. case 'spl':
  4743. $type = 'application/futuresplash';
  4744. break;
  4745. case 'swf':
  4746. $type = 'application/x-shockwave-flash';
  4747. break;
  4748. }
  4749. }
  4750. if ($find_handler)
  4751. {
  4752. if (in_array($type, $types_flash))
  4753. {
  4754. return 'flash';
  4755. }
  4756. elseif (in_array($type, $types_fmedia))
  4757. {
  4758. return 'fmedia';
  4759. }
  4760. elseif (in_array($type, $types_quicktime))
  4761. {
  4762. return 'quicktime';
  4763. }
  4764. elseif (in_array($type, $types_wmedia))
  4765. {
  4766. return 'wmedia';
  4767. }
  4768. elseif (in_array($type, $types_mp3))
  4769. {
  4770. return 'mp3';
  4771. }
  4772. else
  4773. {
  4774. return null;
  4775. }
  4776. }
  4777. else
  4778. {
  4779. return $type;
  4780. }
  4781. }
  4782. }
  4783. /**
  4784. * @todo Move to properly supporting RFC2616 (HTTP/1.1)
  4785. */
  4786. class SimplePie_File
  4787. {
  4788. var $url;
  4789. var $useragent;
  4790. var $success = true;
  4791. var $headers = array();
  4792. var $body;
  4793. var $status_code;
  4794. var $redirects = 0;
  4795. var $error;
  4796. var $method = SIMPLEPIE_FILE_SOURCE_NONE;
  4797. public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  4798. {
  4799. if (class_exists('idna_convert'))
  4800. {
  4801. $idn = new idna_convert();
  4802. $parsed = SimplePie_Misc::parse_url($url);
  4803. $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  4804. }
  4805. $this->url = $url;
  4806. $this->useragent = $useragent;
  4807. if (preg_match('/^http(s)?:\/\//i', $url))
  4808. {
  4809. if ($useragent === null)
  4810. {
  4811. $useragent = ini_get('user_agent');
  4812. $this->useragent = $useragent;
  4813. }
  4814. if (!is_array($headers))
  4815. {
  4816. $headers = array();
  4817. }
  4818. if (!$force_fsockopen && function_exists('curl_exec'))
  4819. {
  4820. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
  4821. $fp = curl_init();
  4822. $headers2 = array();
  4823. foreach ($headers as $key => $value)
  4824. {
  4825. $headers2[] = "$key: $value";
  4826. }
  4827. if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
  4828. {
  4829. curl_setopt($fp, CURLOPT_ENCODING, '');
  4830. }
  4831. curl_setopt($fp, CURLOPT_URL, $url);
  4832. curl_setopt($fp, CURLOPT_HEADER, 1);
  4833. curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
  4834. curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
  4835. curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
  4836. curl_setopt($fp, CURLOPT_REFERER, $url);
  4837. curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
  4838. curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
  4839. if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
  4840. {
  4841. curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
  4842. curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
  4843. }
  4844. $this->headers = curl_exec($fp);
  4845. if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
  4846. {
  4847. curl_setopt($fp, CURLOPT_ENCODING, 'none');
  4848. $this->headers = curl_exec($fp);
  4849. }
  4850. if (curl_errno($fp))
  4851. {
  4852. $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
  4853. $this->success = false;
  4854. }
  4855. else
  4856. {
  4857. $info = curl_getinfo($fp);
  4858. curl_close($fp);
  4859. $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
  4860. $this->headers = array_pop($this->headers);
  4861. $parser = new SimplePie_HTTP_Parser($this->headers);
  4862. if ($parser->parse())
  4863. {
  4864. $this->headers = $parser->headers;
  4865. $this->body = $parser->body;
  4866. $this->status_code = $parser->status_code;
  4867. if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
  4868. {
  4869. $this->redirects++;
  4870. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  4871. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  4872. }
  4873. }
  4874. }
  4875. }
  4876. else
  4877. {
  4878. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
  4879. $url_parts = parse_url($url);
  4880. $socket_host = $url_parts['host'];
  4881. if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
  4882. {
  4883. $socket_host = "ssl://$url_parts[host]";
  4884. $url_parts['port'] = 443;
  4885. }
  4886. if (!isset($url_parts['port']))
  4887. {
  4888. $url_parts['port'] = 80;
  4889. }
  4890. $fp = @fsockopen($socket_host, $url_parts['port'], $errno, $errstr, $timeout);
  4891. if (!$fp)
  4892. {
  4893. $this->error = 'fsockopen error: ' . $errstr;
  4894. $this->success = false;
  4895. }
  4896. else
  4897. {
  4898. stream_set_timeout($fp, $timeout);
  4899. if (isset($url_parts['path']))
  4900. {
  4901. if (isset($url_parts['query']))
  4902. {
  4903. $get = "$url_parts[path]?$url_parts[query]";
  4904. }
  4905. else
  4906. {
  4907. $get = $url_parts['path'];
  4908. }
  4909. }
  4910. else
  4911. {
  4912. $get = '/';
  4913. }
  4914. $out = "GET $get HTTP/1.1\r\n";
  4915. $out .= "Host: $url_parts[host]\r\n";
  4916. $out .= "User-Agent: $useragent\r\n";
  4917. if (extension_loaded('zlib'))
  4918. {
  4919. $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
  4920. }
  4921. if (isset($url_parts['user']) && isset($url_parts['pass']))
  4922. {
  4923. $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
  4924. }
  4925. foreach ($headers as $key => $value)
  4926. {
  4927. $out .= "$key: $value\r\n";
  4928. }
  4929. $out .= "Connection: Close\r\n\r\n";
  4930. fwrite($fp, $out);
  4931. $info = stream_get_meta_data($fp);
  4932. $this->headers = '';
  4933. while (!$info['eof'] && !$info['timed_out'])
  4934. {
  4935. $this->headers .= fread($fp, 1160);
  4936. $info = stream_get_meta_data($fp);
  4937. }
  4938. if (!$info['timed_out'])
  4939. {
  4940. $parser = new SimplePie_HTTP_Parser($this->headers);
  4941. if ($parser->parse())
  4942. {
  4943. $this->headers = $parser->headers;
  4944. $this->body = $parser->body;
  4945. $this->status_code = $parser->status_code;
  4946. if ((in_array($this->status_code, array(300, 301, 302, 303, 307)) || $this->status_code > 307 && $this->status_code < 400) && isset($this->headers['location']) && $this->redirects < $redirects)
  4947. {
  4948. $this->redirects++;
  4949. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  4950. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  4951. }
  4952. if (isset($this->headers['content-encoding']))
  4953. {
  4954. // Hey, we act dumb elsewhere, so let's do that here too
  4955. switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
  4956. {
  4957. case 'gzip':
  4958. case 'x-gzip':
  4959. $decoder = new SimplePie_gzdecode($this->body);
  4960. if (!$decoder->parse())
  4961. {
  4962. $this->error = 'Unable to decode HTTP "gzip" stream';
  4963. $this->success = false;
  4964. }
  4965. else
  4966. {
  4967. $this->body = $decoder->data;
  4968. }
  4969. break;
  4970. case 'deflate':
  4971. if (($body = gzuncompress($this->body)) === false)
  4972. {
  4973. if (($body = gzinflate($this->body)) === false)
  4974. {
  4975. $this->error = 'Unable to decode HTTP "deflate" stream';
  4976. $this->success = false;
  4977. }
  4978. }
  4979. $this->body = $body;
  4980. break;
  4981. default:
  4982. $this->error = 'Unknown content coding';
  4983. $this->success = false;
  4984. }
  4985. }
  4986. }
  4987. }
  4988. else
  4989. {
  4990. $this->error = 'fsocket timed out';
  4991. $this->success = false;
  4992. }
  4993. fclose($fp);
  4994. }
  4995. }
  4996. }
  4997. else
  4998. {
  4999. $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
  5000. if (!$this->body = file_get_contents($url))
  5001. {
  5002. $this->error = 'file_get_contents could not read the file';
  5003. $this->success = false;
  5004. }
  5005. }
  5006. }
  5007. }
  5008. /**
  5009. * gzdecode
  5010. *
  5011. * @package SimplePie
  5012. */
  5013. class SimplePie_gzdecode
  5014. {
  5015. /**
  5016. * Compressed data
  5017. *
  5018. * @access private
  5019. * @see gzdecode::$data
  5020. */
  5021. var $compressed_data;
  5022. /**
  5023. * Size of compressed data
  5024. *
  5025. * @access private
  5026. */
  5027. var $compressed_size;
  5028. /**
  5029. * Minimum size of a valid gzip string
  5030. *
  5031. * @access private
  5032. */
  5033. var $min_compressed_size = 18;
  5034. /**
  5035. * Current position of pointer
  5036. *
  5037. * @access private
  5038. */
  5039. var $position = 0;
  5040. /**
  5041. * Flags (FLG)
  5042. *
  5043. * @access private
  5044. */
  5045. var $flags;
  5046. /**
  5047. * Uncompressed data
  5048. *
  5049. * @access public
  5050. * @see gzdecode::$compressed_data
  5051. */
  5052. var $data;
  5053. /**
  5054. * Modified time
  5055. *
  5056. * @access public
  5057. */
  5058. var $MTIME;
  5059. /**
  5060. * Extra Flags
  5061. *
  5062. * @access public
  5063. */
  5064. var $XFL;
  5065. /**
  5066. * Operating System
  5067. *
  5068. * @access public
  5069. */
  5070. var $OS;
  5071. /**
  5072. * Subfield ID 1
  5073. *
  5074. * @access public
  5075. * @see gzdecode::$extra_field
  5076. * @see gzdecode::$SI2
  5077. */
  5078. var $SI1;
  5079. /**
  5080. * Subfield ID 2
  5081. *
  5082. * @access public
  5083. * @see gzdecode::$extra_field
  5084. * @see gzdecode::$SI1
  5085. */
  5086. var $SI2;
  5087. /**
  5088. * Extra field content
  5089. *
  5090. * @access public
  5091. * @see gzdecode::$SI1
  5092. * @see gzdecode::$SI2
  5093. */
  5094. var $extra_field;
  5095. /**
  5096. * Original filename
  5097. *
  5098. * @access public
  5099. */
  5100. var $filename;
  5101. /**
  5102. * Human readable comment
  5103. *
  5104. * @access public
  5105. */
  5106. var $comment;
  5107. /**
  5108. * Don't allow anything to be set
  5109. *
  5110. * @access public
  5111. */
  5112. public function __set($name, $value)
  5113. {
  5114. trigger_error("Cannot write property $name", E_USER_ERROR);
  5115. }
  5116. /**
  5117. * Set the compressed string and related properties
  5118. *
  5119. * @access public
  5120. */
  5121. public function __construct($data)
  5122. {
  5123. $this->compressed_data = $data;
  5124. $this->compressed_size = strlen($data);
  5125. }
  5126. /**
  5127. * Decode the GZIP stream
  5128. *
  5129. * @access public
  5130. */
  5131. public function parse()
  5132. {
  5133. if ($this->compressed_size >= $this->min_compressed_size)
  5134. {
  5135. // Check ID1, ID2, and CM
  5136. if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
  5137. {
  5138. return false;
  5139. }
  5140. // Get the FLG (FLaGs)
  5141. $this->flags = ord($this->compressed_data[3]);
  5142. // FLG bits above (1 << 4) are reserved
  5143. if ($this->flags > 0x1F)
  5144. {
  5145. return false;
  5146. }
  5147. // Advance the pointer after the above
  5148. $this->position += 4;
  5149. // MTIME
  5150. $mtime = substr($this->compressed_data, $this->position, 4);
  5151. // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
  5152. if (current(unpack('S', "\x00\x01")) === 1)
  5153. {
  5154. $mtime = strrev($mtime);
  5155. }
  5156. $this->MTIME = current(unpack('l', $mtime));
  5157. $this->position += 4;
  5158. // Get the XFL (eXtra FLags)
  5159. $this->XFL = ord($this->compressed_data[$this->position++]);
  5160. // Get the OS (Operating System)
  5161. $this->OS = ord($this->compressed_data[$this->position++]);
  5162. // Parse the FEXTRA
  5163. if ($this->flags & 4)
  5164. {
  5165. // Read subfield IDs
  5166. $this->SI1 = $this->compressed_data[$this->position++];
  5167. $this->SI2 = $this->compressed_data[$this->position++];
  5168. // SI2 set to zero is reserved for future use
  5169. if ($this->SI2 === "\x00")
  5170. {
  5171. return false;
  5172. }
  5173. // Get the length of the extra field
  5174. $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  5175. $this->position += 2;
  5176. // Check the length of the string is still valid
  5177. $this->min_compressed_size += $len + 4;
  5178. if ($this->compressed_size >= $this->min_compressed_size)
  5179. {
  5180. // Set the extra field to the given data
  5181. $this->extra_field = substr($this->compressed_data, $this->position, $len);
  5182. $this->position += $len;
  5183. }
  5184. else
  5185. {
  5186. return false;
  5187. }
  5188. }
  5189. // Parse the FNAME
  5190. if ($this->flags & 8)
  5191. {
  5192. // Get the length of the filename
  5193. $len = strcspn($this->compressed_data, "\x00", $this->position);
  5194. // Check the length of the string is still valid
  5195. $this->min_compressed_size += $len + 1;
  5196. if ($this->compressed_size >= $this->min_compressed_size)
  5197. {
  5198. // Set the original filename to the given string
  5199. $this->filename = substr($this->compressed_data, $this->position, $len);
  5200. $this->position += $len + 1;
  5201. }
  5202. else
  5203. {
  5204. return false;
  5205. }
  5206. }
  5207. // Parse the FCOMMENT
  5208. if ($this->flags & 16)
  5209. {
  5210. // Get the length of the comment
  5211. $len = strcspn($this->compressed_data, "\x00", $this->position);
  5212. // Check the length of the string is still valid
  5213. $this->min_compressed_size += $len + 1;
  5214. if ($this->compressed_size >= $this->min_compressed_size)
  5215. {
  5216. // Set the original comment to the given string
  5217. $this->comment = substr($this->compressed_data, $this->position, $len);
  5218. $this->position += $len + 1;
  5219. }
  5220. else
  5221. {
  5222. return false;
  5223. }
  5224. }
  5225. // Parse the FHCRC
  5226. if ($this->flags & 2)
  5227. {
  5228. // Check the length of the string is still valid
  5229. $this->min_compressed_size += $len + 2;
  5230. if ($this->compressed_size >= $this->min_compressed_size)
  5231. {
  5232. // Read the CRC
  5233. $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  5234. // Check the CRC matches
  5235. if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
  5236. {
  5237. $this->position += 2;
  5238. }
  5239. else
  5240. {
  5241. return false;
  5242. }
  5243. }
  5244. else
  5245. {
  5246. return false;
  5247. }
  5248. }
  5249. // Decompress the actual data
  5250. if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
  5251. {
  5252. return false;
  5253. }
  5254. else
  5255. {
  5256. $this->position = $this->compressed_size - 8;
  5257. }
  5258. // Check CRC of data
  5259. $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  5260. $this->position += 4;
  5261. /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
  5262. {
  5263. return false;
  5264. }*/
  5265. // Check ISIZE of data
  5266. $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  5267. $this->position += 4;
  5268. if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
  5269. {
  5270. return false;
  5271. }
  5272. // Wow, against all odds, we've actually got a valid gzip string
  5273. return true;
  5274. }
  5275. else
  5276. {
  5277. return false;
  5278. }
  5279. }
  5280. }
  5281. /**
  5282. * HTTP Response Parser
  5283. *
  5284. * @package SimplePie
  5285. */
  5286. class SimplePie_HTTP_Parser
  5287. {
  5288. /**
  5289. * HTTP Version
  5290. *
  5291. * @var float
  5292. */
  5293. public $http_version = 0.0;
  5294. /**
  5295. * Status code
  5296. *
  5297. * @var int
  5298. */
  5299. public $status_code = 0;
  5300. /**
  5301. * Reason phrase
  5302. *
  5303. * @var string
  5304. */
  5305. public $reason = '';
  5306. /**
  5307. * Key/value pairs of the headers
  5308. *
  5309. * @var array
  5310. */
  5311. public $headers = array();
  5312. /**
  5313. * Body of the response
  5314. *
  5315. * @var string
  5316. */
  5317. public $body = '';
  5318. /**
  5319. * Current state of the state machine
  5320. *
  5321. * @var string
  5322. */
  5323. protected $state = 'http_version';
  5324. /**
  5325. * Input data
  5326. *
  5327. * @var string
  5328. */
  5329. protected $data = '';
  5330. /**
  5331. * Input data length (to avoid calling strlen() everytime this is needed)
  5332. *
  5333. * @var int
  5334. */
  5335. protected $data_length = 0;
  5336. /**
  5337. * Current position of the pointer
  5338. *
  5339. * @var int
  5340. */
  5341. protected $position = 0;
  5342. /**
  5343. * Name of the hedaer currently being parsed
  5344. *
  5345. * @var string
  5346. */
  5347. protected $name = '';
  5348. /**
  5349. * Value of the hedaer currently being parsed
  5350. *
  5351. * @var string
  5352. */
  5353. protected $value = '';
  5354. /**
  5355. * Create an instance of the class with the input data
  5356. *
  5357. * @param string $data Input data
  5358. */
  5359. public function __construct($data)
  5360. {
  5361. $this->data = $data;
  5362. $this->data_length = strlen($this->data);
  5363. }
  5364. /**
  5365. * Parse the input data
  5366. *
  5367. * @return bool true on success, false on failure
  5368. */
  5369. public function parse()
  5370. {
  5371. while ($this->state && $this->state !== 'emit' && $this->has_data())
  5372. {
  5373. $state = $this->state;
  5374. $this->$state();
  5375. }
  5376. $this->data = '';
  5377. if ($this->state === 'emit' || $this->state === 'body')
  5378. {
  5379. return true;
  5380. }
  5381. else
  5382. {
  5383. $this->http_version = '';
  5384. $this->status_code = '';
  5385. $this->reason = '';
  5386. $this->headers = array();
  5387. $this->body = '';
  5388. return false;
  5389. }
  5390. }
  5391. /**
  5392. * Check whether there is data beyond the pointer
  5393. *
  5394. * @return bool true if there is further data, false if not
  5395. */
  5396. protected function has_data()
  5397. {
  5398. return (bool) ($this->position < $this->data_length);
  5399. }
  5400. /**
  5401. * See if the next character is LWS
  5402. *
  5403. * @return bool true if the next character is LWS, false if not
  5404. */
  5405. protected function is_linear_whitespace()
  5406. {
  5407. return (bool) ($this->data[$this->position] === "\x09"
  5408. || $this->data[$this->position] === "\x20"
  5409. || ($this->data[$this->position] === "\x0A"
  5410. && isset($this->data[$this->position + 1])
  5411. && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
  5412. }
  5413. /**
  5414. * Parse the HTTP version
  5415. */
  5416. protected function http_version()
  5417. {
  5418. if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
  5419. {
  5420. $len = strspn($this->data, '0123456789.', 5);
  5421. $this->http_version = substr($this->data, 5, $len);
  5422. $this->position += 5 + $len;
  5423. if (substr_count($this->http_version, '.') <= 1)
  5424. {
  5425. $this->http_version = (float) $this->http_version;
  5426. $this->position += strspn($this->data, "\x09\x20", $this->position);
  5427. $this->state = 'status';
  5428. }
  5429. else
  5430. {
  5431. $this->state = false;
  5432. }
  5433. }
  5434. else
  5435. {
  5436. $this->state = false;
  5437. }
  5438. }
  5439. /**
  5440. * Parse the status code
  5441. */
  5442. protected function status()
  5443. {
  5444. if ($len = strspn($this->data, '0123456789', $this->position))
  5445. {
  5446. $this->status_code = (int) substr($this->data, $this->position, $len);
  5447. $this->position += $len;
  5448. $this->state = 'reason';
  5449. }
  5450. else
  5451. {
  5452. $this->state = false;
  5453. }
  5454. }
  5455. /**
  5456. * Parse the reason phrase
  5457. */
  5458. protected function reason()
  5459. {
  5460. $len = strcspn($this->data, "\x0A", $this->position);
  5461. $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
  5462. $this->position += $len + 1;
  5463. $this->state = 'new_line';
  5464. }
  5465. /**
  5466. * Deal with a new line, shifting data around as needed
  5467. */
  5468. protected function new_line()
  5469. {
  5470. $this->value = trim($this->value, "\x0D\x20");
  5471. if ($this->name !== '' && $this->value !== '')
  5472. {
  5473. $this->name = strtolower($this->name);
  5474. // We should only use the last Content-Type header. c.f. issue #1
  5475. if (isset($this->headers[$this->name]) && $this->name !== 'content-type')
  5476. {
  5477. $this->headers[$this->name] .= ', ' . $this->value;
  5478. }
  5479. else
  5480. {
  5481. $this->headers[$this->name] = $this->value;
  5482. }
  5483. }
  5484. $this->name = '';
  5485. $this->value = '';
  5486. if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
  5487. {
  5488. $this->position += 2;
  5489. $this->state = 'body';
  5490. }
  5491. elseif ($this->data[$this->position] === "\x0A")
  5492. {
  5493. $this->position++;
  5494. $this->state = 'body';
  5495. }
  5496. else
  5497. {
  5498. $this->state = 'name';
  5499. }
  5500. }
  5501. /**
  5502. * Parse a header name
  5503. */
  5504. protected function name()
  5505. {
  5506. $len = strcspn($this->data, "\x0A:", $this->position);
  5507. if (isset($this->data[$this->position + $len]))
  5508. {
  5509. if ($this->data[$this->position + $len] === "\x0A")
  5510. {
  5511. $this->position += $len;
  5512. $this->state = 'new_line';
  5513. }
  5514. else
  5515. {
  5516. $this->name = substr($this->data, $this->position, $len);
  5517. $this->position += $len + 1;
  5518. $this->state = 'value';
  5519. }
  5520. }
  5521. else
  5522. {
  5523. $this->state = false;
  5524. }
  5525. }
  5526. /**
  5527. * Parse LWS, replacing consecutive LWS characters with a single space
  5528. */
  5529. protected function linear_whitespace()
  5530. {
  5531. do
  5532. {
  5533. if (substr($this->data, $this->position, 2) === "\x0D\x0A")
  5534. {
  5535. $this->position += 2;
  5536. }
  5537. elseif ($this->data[$this->position] === "\x0A")
  5538. {
  5539. $this->position++;
  5540. }
  5541. $this->position += strspn($this->data, "\x09\x20", $this->position);
  5542. } while ($this->has_data() && $this->is_linear_whitespace());
  5543. $this->value .= "\x20";
  5544. }
  5545. /**
  5546. * See what state to move to while within non-quoted header values
  5547. */
  5548. protected function value()
  5549. {
  5550. if ($this->is_linear_whitespace())
  5551. {
  5552. $this->linear_whitespace();
  5553. }
  5554. else
  5555. {
  5556. switch ($this->data[$this->position])
  5557. {
  5558. case '"':
  5559. // Workaround for ETags: we have to include the quotes as
  5560. // part of the tag.
  5561. if (strtolower($this->name) === 'etag')
  5562. {
  5563. $this->value .= '"';
  5564. $this->position++;
  5565. $this->state = 'value_char';
  5566. break;
  5567. }
  5568. $this->position++;
  5569. $this->state = 'quote';
  5570. break;
  5571. case "\x0A":
  5572. $this->position++;
  5573. $this->state = 'new_line';
  5574. break;
  5575. default:
  5576. $this->state = 'value_char';
  5577. break;
  5578. }
  5579. }
  5580. }
  5581. /**
  5582. * Parse a header value while outside quotes
  5583. */
  5584. protected function value_char()
  5585. {
  5586. $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
  5587. $this->value .= substr($this->data, $this->position, $len);
  5588. $this->position += $len;
  5589. $this->state = 'value';
  5590. }
  5591. /**
  5592. * See what state to move to while within quoted header values
  5593. */
  5594. protected function quote()
  5595. {
  5596. if ($this->is_linear_whitespace())
  5597. {
  5598. $this->linear_whitespace();
  5599. }
  5600. else
  5601. {
  5602. switch ($this->data[$this->position])
  5603. {
  5604. case '"':
  5605. $this->position++;
  5606. $this->state = 'value';
  5607. break;
  5608. case "\x0A":
  5609. $this->position++;
  5610. $this->state = 'new_line';
  5611. break;
  5612. case '\\':
  5613. $this->position++;
  5614. $this->state = 'quote_escaped';
  5615. break;
  5616. default:
  5617. $this->state = 'quote_char';
  5618. break;
  5619. }
  5620. }
  5621. }
  5622. /**
  5623. * Parse a header value while within quotes
  5624. */
  5625. protected function quote_char()
  5626. {
  5627. $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
  5628. $this->value .= substr($this->data, $this->position, $len);
  5629. $this->position += $len;
  5630. $this->state = 'value';
  5631. }
  5632. /**
  5633. * Parse an escaped character within quotes
  5634. */
  5635. protected function quote_escaped()
  5636. {
  5637. $this->value .= $this->data[$this->position];
  5638. $this->position++;
  5639. $this->state = 'quote';
  5640. }
  5641. /**
  5642. * Parse the body
  5643. */
  5644. protected function body()
  5645. {
  5646. $this->body = substr($this->data, $this->position);
  5647. if (!empty($this->headers['transfer-encoding']))
  5648. {
  5649. unset($this->headers['transfer-encoding']);
  5650. $this->state = 'chunked';
  5651. }
  5652. else
  5653. {
  5654. $this->state = 'emit';
  5655. }
  5656. }
  5657. /**
  5658. * Parsed a "Transfer-Encoding: chunked" body
  5659. */
  5660. protected function chunked()
  5661. {
  5662. if (!preg_match('/^[0-9a-f]+(\s|\r|\n)+/mi', trim($this->body)))
  5663. {
  5664. $this->state = 'emit';
  5665. return;
  5666. }
  5667. $decoded = '';
  5668. $encoded = $this->body;
  5669. while (true)
  5670. {
  5671. $is_chunked = (bool) preg_match( '/^([0-9a-f]+)(\s|\r|\n)+/mi', $encoded, $matches );
  5672. if (!$is_chunked)
  5673. {
  5674. // Looks like it's not chunked after all
  5675. $this->state = 'emit';
  5676. return;
  5677. }
  5678. $length = hexdec($matches[1]);
  5679. $chunk_length = strlen($matches[0]);
  5680. $decoded .= $part = substr($encoded, $chunk_length, $length);
  5681. $encoded = ltrim(substr($encoded, $chunk_length + $length), "\r\n");
  5682. if (trim($encoded) === '0')
  5683. {
  5684. $this->state = 'emit';
  5685. $this->body = $decoded;
  5686. return;
  5687. }
  5688. }
  5689. }
  5690. }
  5691. /**
  5692. * IRI parser/serialiser
  5693. *
  5694. * @package SimplePie
  5695. */
  5696. class SimplePie_IRI
  5697. {
  5698. /**
  5699. * Scheme
  5700. *
  5701. * @access private
  5702. * @var string
  5703. */
  5704. var $scheme;
  5705. /**
  5706. * User Information
  5707. *
  5708. * @access private
  5709. * @var string
  5710. */
  5711. var $userinfo;
  5712. /**
  5713. * Host
  5714. *
  5715. * @access private
  5716. * @var string
  5717. */
  5718. var $host;
  5719. /**
  5720. * Port
  5721. *
  5722. * @access private
  5723. * @var string
  5724. */
  5725. var $port;
  5726. /**
  5727. * Path
  5728. *
  5729. * @access private
  5730. * @var string
  5731. */
  5732. var $path;
  5733. /**
  5734. * Query
  5735. *
  5736. * @access private
  5737. * @var string
  5738. */
  5739. var $query;
  5740. /**
  5741. * Fragment
  5742. *
  5743. * @access private
  5744. * @var string
  5745. */
  5746. var $fragment;
  5747. /**
  5748. * Whether the object represents a valid IRI
  5749. *
  5750. * @access private
  5751. * @var array
  5752. */
  5753. var $valid = array();
  5754. /**
  5755. * Return the entire IRI when you try and read the object as a string
  5756. *
  5757. * @access public
  5758. * @return string
  5759. */
  5760. public function __toString()
  5761. {
  5762. return $this->get_iri();
  5763. }
  5764. /**
  5765. * Create a new IRI object, from a specified string
  5766. *
  5767. * @access public
  5768. * @param string $iri
  5769. * @return SimplePie_IRI
  5770. */
  5771. public function __construct($iri)
  5772. {
  5773. $iri = (string) $iri;
  5774. if ($iri !== '')
  5775. {
  5776. $parsed = $this->parse_iri($iri);
  5777. $this->set_scheme($parsed['scheme']);
  5778. $this->set_authority($parsed['authority']);
  5779. $this->set_path($parsed['path']);
  5780. $this->set_query($parsed['query']);
  5781. $this->set_fragment($parsed['fragment']);
  5782. }
  5783. }
  5784. /**
  5785. * Create a new IRI object by resolving a relative IRI
  5786. *
  5787. * @static
  5788. * @access public
  5789. * @param SimplePie_IRI $base Base IRI
  5790. * @param string $relative Relative IRI
  5791. * @return SimplePie_IRI
  5792. */
  5793. public static function absolutize($base, $relative)
  5794. {
  5795. $relative = (string) $relative;
  5796. if ($relative !== '')
  5797. {
  5798. $relative = new SimplePie_IRI($relative);
  5799. if ($relative->get_scheme() !== null)
  5800. {
  5801. $target = $relative;
  5802. }
  5803. elseif ($base->get_iri() !== null)
  5804. {
  5805. if ($relative->get_authority() !== null)
  5806. {
  5807. $target = $relative;
  5808. $target->set_scheme($base->get_scheme());
  5809. }
  5810. else
  5811. {
  5812. $target = new SimplePie_IRI('');
  5813. $target->set_scheme($base->get_scheme());
  5814. $target->set_userinfo($base->get_userinfo());
  5815. $target->set_host($base->get_host());
  5816. $target->set_port($base->get_port());
  5817. if ($relative->get_path() !== null)
  5818. {
  5819. if (strpos($relative->get_path(), '/') === 0)
  5820. {
  5821. $target->set_path($relative->get_path());
  5822. }
  5823. elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
  5824. {
  5825. $target->set_path('/' . $relative->get_path());
  5826. }
  5827. elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
  5828. {
  5829. $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
  5830. }
  5831. else
  5832. {
  5833. $target->set_path($relative->get_path());
  5834. }
  5835. $target->set_query($relative->get_query());
  5836. }
  5837. else
  5838. {
  5839. $target->set_path($base->get_path());
  5840. if ($relative->get_query() !== null)
  5841. {
  5842. $target->set_query($relative->get_query());
  5843. }
  5844. elseif ($base->get_query() !== null)
  5845. {
  5846. $target->set_query($base->get_query());
  5847. }
  5848. }
  5849. }
  5850. $target->set_fragment($relative->get_fragment());
  5851. }
  5852. else
  5853. {
  5854. // No base URL, just return the relative URL
  5855. $target = $relative;
  5856. }
  5857. }
  5858. else
  5859. {
  5860. $target = $base;
  5861. }
  5862. return $target;
  5863. }
  5864. /**
  5865. * Parse an IRI into scheme/authority/path/query/fragment segments
  5866. *
  5867. * @access private
  5868. * @param string $iri
  5869. * @return array
  5870. */
  5871. public function parse_iri($iri)
  5872. {
  5873. preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
  5874. for ($i = count($match); $i <= 9; $i++)
  5875. {
  5876. $match[$i] = '';
  5877. }
  5878. return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
  5879. }
  5880. /**
  5881. * Remove dot segments from a path
  5882. *
  5883. * @access private
  5884. * @param string $input
  5885. * @return string
  5886. */
  5887. public function remove_dot_segments($input)
  5888. {
  5889. $output = '';
  5890. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  5891. {
  5892. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  5893. if (strpos($input, '../') === 0)
  5894. {
  5895. $input = substr($input, 3);
  5896. }
  5897. elseif (strpos($input, './') === 0)
  5898. {
  5899. $input = substr($input, 2);
  5900. }
  5901. // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
  5902. elseif (strpos($input, '/./') === 0)
  5903. {
  5904. $input = substr_replace($input, '/', 0, 3);
  5905. }
  5906. elseif ($input === '/.')
  5907. {
  5908. $input = '/';
  5909. }
  5910. // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
  5911. elseif (strpos($input, '/../') === 0)
  5912. {
  5913. $input = substr_replace($input, '/', 0, 4);
  5914. $output = substr_replace($output, '', strrpos($output, '/'));
  5915. }
  5916. elseif ($input === '/..')
  5917. {
  5918. $input = '/';
  5919. $output = substr_replace($output, '', strrpos($output, '/'));
  5920. }
  5921. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  5922. elseif ($input === '.' || $input === '..')
  5923. {
  5924. $input = '';
  5925. }
  5926. // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
  5927. elseif (($pos = strpos($input, '/', 1)) !== false)
  5928. {
  5929. $output .= substr($input, 0, $pos);
  5930. $input = substr_replace($input, '', 0, $pos);
  5931. }
  5932. else
  5933. {
  5934. $output .= $input;
  5935. $input = '';
  5936. }
  5937. }
  5938. return $output . $input;
  5939. }
  5940. /**
  5941. * Replace invalid character with percent encoding
  5942. *
  5943. * @param string $string Input string
  5944. * @param string $valid_chars Valid characters not in iunreserved or iprivate (this is ASCII-only)
  5945. * @param int $case Normalise case
  5946. * @param bool $iprivate Allow iprivate
  5947. * @return string
  5948. */
  5949. protected function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE, $iprivate = false)
  5950. {
  5951. // Normalize as many pct-encoded sections as possible
  5952. $string = preg_replace_callback('/(?:%[A-Fa-f0-9]{2})+/', array(&$this, 'remove_iunreserved_percent_encoded'), $string);
  5953. // Replace invalid percent characters
  5954. $string = preg_replace('/%(?![A-Fa-f0-9]{2})/', '%25', $string);
  5955. // Add unreserved and % to $valid_chars (the latter is safe because all
  5956. // pct-encoded sections are now valid).
  5957. $valid_chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~%';
  5958. // Now replace any bytes that aren't allowed with their pct-encoded versions
  5959. $position = 0;
  5960. $strlen = strlen($string);
  5961. while (($position += strspn($string, $valid_chars, $position)) < $strlen)
  5962. {
  5963. $value = ord($string[$position]);
  5964. // Start position
  5965. $start = $position;
  5966. // By default we are valid
  5967. $valid = true;
  5968. // No one byte sequences are valid due to the while.
  5969. // Two byte sequence:
  5970. if (($value & 0xE0) === 0xC0)
  5971. {
  5972. $character = ($value & 0x1F) << 6;
  5973. $length = 2;
  5974. $remaining = 1;
  5975. }
  5976. // Three byte sequence:
  5977. elseif (($value & 0xF0) === 0xE0)
  5978. {
  5979. $character = ($value & 0x0F) << 12;
  5980. $length = 3;
  5981. $remaining = 2;
  5982. }
  5983. // Four byte sequence:
  5984. elseif (($value & 0xF8) === 0xF0)
  5985. {
  5986. $character = ($value & 0x07) << 18;
  5987. $length = 4;
  5988. $remaining = 3;
  5989. }
  5990. // Invalid byte:
  5991. else
  5992. {
  5993. $valid = false;
  5994. $length = 1;
  5995. $remaining = 0;
  5996. }
  5997. if ($remaining)
  5998. {
  5999. if ($position + $length <= $strlen)
  6000. {
  6001. for ($position++; $remaining; $position++)
  6002. {
  6003. $value = ord($string[$position]);
  6004. // Check that the byte is valid, then add it to the character:
  6005. if (($value & 0xC0) === 0x80)
  6006. {
  6007. $character |= ($value & 0x3F) << (--$remaining * 6);
  6008. }
  6009. // If it is invalid, count the sequence as invalid and reprocess the current byte:
  6010. else
  6011. {
  6012. $valid = false;
  6013. $position--;
  6014. break;
  6015. }
  6016. }
  6017. }
  6018. else
  6019. {
  6020. $position = $strlen - 1;
  6021. $valid = false;
  6022. }
  6023. }
  6024. // Percent encode anything invalid or not in ucschar
  6025. if (
  6026. // Invalid sequences
  6027. !$valid
  6028. // Non-shortest form sequences are invalid
  6029. || $length > 1 && $character <= 0x7F
  6030. || $length > 2 && $character <= 0x7FF
  6031. || $length > 3 && $character <= 0xFFFF
  6032. // Outside of range of ucschar codepoints
  6033. // Noncharacters
  6034. || ($character & 0xFFFE) === 0xFFFE
  6035. || $character >= 0xFDD0 && $character <= 0xFDEF
  6036. || (
  6037. // Everything else not in ucschar
  6038. $character > 0xD7FF && $character < 0xF900
  6039. || $character < 0xA0
  6040. || $character > 0xEFFFD
  6041. )
  6042. && (
  6043. // Everything not in iprivate, if it applies
  6044. !$iprivate
  6045. || $character < 0xE000
  6046. || $character > 0x10FFFD
  6047. )
  6048. )
  6049. {
  6050. // If we were a character, pretend we weren't, but rather an error.
  6051. if ($valid)
  6052. $position--;
  6053. for ($j = $start; $j <= $position; $j++)
  6054. {
  6055. $string = substr_replace($string, sprintf('%%%02X', ord($string[$j])), $j, 1);
  6056. $j += 2;
  6057. $position += 2;
  6058. $strlen += 2;
  6059. }
  6060. }
  6061. }
  6062. // Normalise case
  6063. if ($case & SIMPLEPIE_LOWERCASE)
  6064. {
  6065. $string = strtolower($string);
  6066. }
  6067. elseif ($case & SIMPLEPIE_UPPERCASE)
  6068. {
  6069. $string = strtoupper($string);
  6070. }
  6071. return $string;
  6072. }
  6073. /**
  6074. * Callback function for preg_replace_callback.
  6075. *
  6076. * Removes sequences of percent encoded bytes that represent UTF-8
  6077. * encoded characters in iunreserved
  6078. *
  6079. * @param array $match PCRE match
  6080. * @return string Replacement
  6081. */
  6082. protected function remove_iunreserved_percent_encoded($match)
  6083. {
  6084. // As we just have valid percent encoded sequences we can just explode
  6085. // and ignore the first member of the returned array (an empty string).
  6086. $bytes = explode('%', $match[0]);
  6087. // Initialize the new string (this is what will be returned) and that
  6088. // there are no bytes remaining in the current sequence (unsurprising
  6089. // at the first byte!).
  6090. $string = '';
  6091. $remaining = 0;
  6092. // Loop over each and every byte, and set $value to its value
  6093. for ($i = 1, $len = count($bytes); $i < $len; $i++)
  6094. {
  6095. $value = hexdec($bytes[$i]);
  6096. // If we're the first byte of sequence:
  6097. if (!$remaining)
  6098. {
  6099. // Start position
  6100. $start = $i;
  6101. // By default we are valid
  6102. $valid = true;
  6103. // One byte sequence:
  6104. if ($value <= 0x7F)
  6105. {
  6106. $character = $value;
  6107. $length = 1;
  6108. }
  6109. // Two byte sequence:
  6110. elseif (($value & 0xE0) === 0xC0)
  6111. {
  6112. $character = ($value & 0x1F) << 6;
  6113. $length = 2;
  6114. $remaining = 1;
  6115. }
  6116. // Three byte sequence:
  6117. elseif (($value & 0xF0) === 0xE0)
  6118. {
  6119. $character = ($value & 0x0F) << 12;
  6120. $length = 3;
  6121. $remaining = 2;
  6122. }
  6123. // Four byte sequence:
  6124. elseif (($value & 0xF8) === 0xF0)
  6125. {
  6126. $character = ($value & 0x07) << 18;
  6127. $length = 4;
  6128. $remaining = 3;
  6129. }
  6130. // Invalid byte:
  6131. else
  6132. {
  6133. $valid = false;
  6134. $remaining = 0;
  6135. }
  6136. }
  6137. // Continuation byte:
  6138. else
  6139. {
  6140. // Check that the byte is valid, then add it to the character:
  6141. if (($value & 0xC0) === 0x80)
  6142. {
  6143. $remaining--;
  6144. $character |= ($value & 0x3F) << ($remaining * 6);
  6145. }
  6146. // If it is invalid, count the sequence as invalid and reprocess the current byte as the start of a sequence:
  6147. else
  6148. {
  6149. $valid = false;
  6150. $remaining = 0;
  6151. $i--;
  6152. }
  6153. }
  6154. // If we've reached the end of the current byte sequence, append it to Unicode::$data
  6155. if (!$remaining)
  6156. {
  6157. // Percent encode anything invalid or not in iunreserved
  6158. if (
  6159. // Invalid sequences
  6160. !$valid
  6161. // Non-shortest form sequences are invalid
  6162. || $length > 1 && $character <= 0x7F
  6163. || $length > 2 && $character <= 0x7FF
  6164. || $length > 3 && $character <= 0xFFFF
  6165. // Outside of range of iunreserved codepoints
  6166. || $character < 0x2D
  6167. || $character > 0xEFFFD
  6168. // Noncharacters
  6169. || ($character & 0xFFFE) === 0xFFFE
  6170. || $character >= 0xFDD0 && $character <= 0xFDEF
  6171. // Everything else not in iunreserved (this is all BMP)
  6172. || $character === 0x2F
  6173. || $character > 0x39 && $character < 0x41
  6174. || $character > 0x5A && $character < 0x61
  6175. || $character > 0x7A && $character < 0x7E
  6176. || $character > 0x7E && $character < 0xA0
  6177. || $character > 0xD7FF && $character < 0xF900
  6178. )
  6179. {
  6180. for ($j = $start; $j <= $i; $j++)
  6181. {
  6182. $string .= '%' . strtoupper($bytes[$j]);
  6183. }
  6184. }
  6185. else
  6186. {
  6187. for ($j = $start; $j <= $i; $j++)
  6188. {
  6189. $string .= chr(hexdec($bytes[$j]));
  6190. }
  6191. }
  6192. }
  6193. }
  6194. // If we have any bytes left over they are invalid (i.e., we are
  6195. // mid-way through a multi-byte sequence)
  6196. if ($remaining)
  6197. {
  6198. for ($j = $start; $j < $len; $j++)
  6199. {
  6200. $string .= '%' . strtoupper($bytes[$j]);
  6201. }
  6202. }
  6203. return $string;
  6204. }
  6205. /**
  6206. * Check if the object represents a valid IRI
  6207. *
  6208. * @access public
  6209. * @return bool
  6210. */
  6211. public function is_valid()
  6212. {
  6213. return array_sum($this->valid) === count($this->valid);
  6214. }
  6215. /**
  6216. * Set the scheme. Returns true on success, false on failure (if there are
  6217. * any invalid characters).
  6218. *
  6219. * @access public
  6220. * @param string $scheme
  6221. * @return bool
  6222. */
  6223. public function set_scheme($scheme)
  6224. {
  6225. if ($scheme === null || $scheme === '')
  6226. {
  6227. $this->scheme = null;
  6228. }
  6229. else
  6230. {
  6231. $len = strlen($scheme);
  6232. switch (true)
  6233. {
  6234. case $len > 1:
  6235. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
  6236. {
  6237. $this->scheme = null;
  6238. $this->valid[__FUNCTION__] = false;
  6239. return false;
  6240. }
  6241. case $len > 0:
  6242. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
  6243. {
  6244. $this->scheme = null;
  6245. $this->valid[__FUNCTION__] = false;
  6246. return false;
  6247. }
  6248. }
  6249. $this->scheme = strtolower($scheme);
  6250. }
  6251. $this->valid[__FUNCTION__] = true;
  6252. return true;
  6253. }
  6254. /**
  6255. * Set the authority. Returns true on success, false on failure (if there are
  6256. * any invalid characters).
  6257. *
  6258. * @access public
  6259. * @param string $authority
  6260. * @return bool
  6261. */
  6262. public function set_authority($authority)
  6263. {
  6264. if (($userinfo_end = strrpos($authority, '@')) !== false)
  6265. {
  6266. $userinfo = substr($authority, 0, $userinfo_end);
  6267. $authority = substr($authority, $userinfo_end + 1);
  6268. }
  6269. else
  6270. {
  6271. $userinfo = null;
  6272. }
  6273. if (($port_start = strpos($authority, ':')) !== false)
  6274. {
  6275. $port = substr($authority, $port_start + 1);
  6276. if ($port === false)
  6277. {
  6278. $port = null;
  6279. }
  6280. $authority = substr($authority, 0, $port_start);
  6281. }
  6282. else
  6283. {
  6284. $port = null;
  6285. }
  6286. return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
  6287. }
  6288. /**
  6289. * Set the userinfo.
  6290. *
  6291. * @access public
  6292. * @param string $userinfo
  6293. * @return bool
  6294. */
  6295. public function set_userinfo($userinfo)
  6296. {
  6297. if ($userinfo === null || $userinfo === '')
  6298. {
  6299. $this->userinfo = null;
  6300. }
  6301. else
  6302. {
  6303. $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
  6304. }
  6305. $this->valid[__FUNCTION__] = true;
  6306. return true;
  6307. }
  6308. /**
  6309. * Set the host. Returns true on success, false on failure (if there are
  6310. * any invalid characters).
  6311. *
  6312. * @access public
  6313. * @param string $host
  6314. * @return bool
  6315. */
  6316. public function set_host($host)
  6317. {
  6318. if ($host === null || $host === '')
  6319. {
  6320. $this->host = null;
  6321. $this->valid[__FUNCTION__] = true;
  6322. return true;
  6323. }
  6324. elseif ($host[0] === '[' && substr($host, -1) === ']')
  6325. {
  6326. if (SimplePie_Net_IPv6::checkIPv6(substr($host, 1, -1)))
  6327. {
  6328. $this->host = $host;
  6329. $this->valid[__FUNCTION__] = true;
  6330. return true;
  6331. }
  6332. else
  6333. {
  6334. $this->host = null;
  6335. $this->valid[__FUNCTION__] = false;
  6336. return false;
  6337. }
  6338. }
  6339. else
  6340. {
  6341. $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
  6342. $this->valid[__FUNCTION__] = true;
  6343. return true;
  6344. }
  6345. }
  6346. /**
  6347. * Set the port. Returns true on success, false on failure (if there are
  6348. * any invalid characters).
  6349. *
  6350. * @access public
  6351. * @param string $port
  6352. * @return bool
  6353. */
  6354. public function set_port($port)
  6355. {
  6356. if ($port === null || $port === '')
  6357. {
  6358. $this->port = null;
  6359. $this->valid[__FUNCTION__] = true;
  6360. return true;
  6361. }
  6362. elseif (strspn($port, '0123456789') === strlen($port))
  6363. {
  6364. $this->port = (int) $port;
  6365. $this->valid[__FUNCTION__] = true;
  6366. return true;
  6367. }
  6368. else
  6369. {
  6370. $this->port = null;
  6371. $this->valid[__FUNCTION__] = false;
  6372. return false;
  6373. }
  6374. }
  6375. /**
  6376. * Set the path.
  6377. *
  6378. * @access public
  6379. * @param string $path
  6380. * @return bool
  6381. */
  6382. public function set_path($path)
  6383. {
  6384. if ($path === null || $path === '')
  6385. {
  6386. $this->path = null;
  6387. $this->valid[__FUNCTION__] = true;
  6388. return true;
  6389. }
  6390. elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
  6391. {
  6392. $this->path = null;
  6393. $this->valid[__FUNCTION__] = false;
  6394. return false;
  6395. }
  6396. else
  6397. {
  6398. $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
  6399. if ($this->scheme !== null)
  6400. {
  6401. $this->path = $this->remove_dot_segments($this->path);
  6402. }
  6403. $this->valid[__FUNCTION__] = true;
  6404. return true;
  6405. }
  6406. }
  6407. /**
  6408. * Set the query.
  6409. *
  6410. * @access public
  6411. * @param string $query
  6412. * @return bool
  6413. */
  6414. public function set_query($query)
  6415. {
  6416. if ($query === null || $query === '')
  6417. {
  6418. $this->query = null;
  6419. }
  6420. else
  6421. {
  6422. $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
  6423. }
  6424. $this->valid[__FUNCTION__] = true;
  6425. return true;
  6426. }
  6427. /**
  6428. * Set the fragment.
  6429. *
  6430. * @access public
  6431. * @param string $fragment
  6432. * @return bool
  6433. */
  6434. public function set_fragment($fragment)
  6435. {
  6436. if ($fragment === null || $fragment === '')
  6437. {
  6438. $this->fragment = null;
  6439. }
  6440. else
  6441. {
  6442. $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
  6443. }
  6444. $this->valid[__FUNCTION__] = true;
  6445. return true;
  6446. }
  6447. /**
  6448. * Get the complete IRI
  6449. *
  6450. * @access public
  6451. * @return string
  6452. */
  6453. public function get_iri()
  6454. {
  6455. $iri = '';
  6456. if ($this->scheme !== null)
  6457. {
  6458. $iri .= $this->scheme . ':';
  6459. }
  6460. if (($authority = $this->get_authority()) !== null)
  6461. {
  6462. $iri .= '//' . $authority;
  6463. }
  6464. if ($this->path !== null)
  6465. {
  6466. $iri .= $this->path;
  6467. }
  6468. if ($this->query !== null)
  6469. {
  6470. $iri .= '?' . $this->query;
  6471. }
  6472. if ($this->fragment !== null)
  6473. {
  6474. $iri .= '#' . $this->fragment;
  6475. }
  6476. if ($iri !== '')
  6477. {
  6478. return $iri;
  6479. }
  6480. else
  6481. {
  6482. return null;
  6483. }
  6484. }
  6485. /**
  6486. * Get the scheme
  6487. *
  6488. * @access public
  6489. * @return string
  6490. */
  6491. public function get_scheme()
  6492. {
  6493. return $this->scheme;
  6494. }
  6495. /**
  6496. * Get the complete authority
  6497. *
  6498. * @access public
  6499. * @return string
  6500. */
  6501. public function get_authority()
  6502. {
  6503. $authority = '';
  6504. if ($this->userinfo !== null)
  6505. {
  6506. $authority .= $this->userinfo . '@';
  6507. }
  6508. if ($this->host !== null)
  6509. {
  6510. $authority .= $this->host;
  6511. }
  6512. if ($this->port !== null)
  6513. {
  6514. $authority .= ':' . $this->port;
  6515. }
  6516. if ($authority !== '')
  6517. {
  6518. return $authority;
  6519. }
  6520. else
  6521. {
  6522. return null;
  6523. }
  6524. }
  6525. /**
  6526. * Get the user information
  6527. *
  6528. * @access public
  6529. * @return string
  6530. */
  6531. public function get_userinfo()
  6532. {
  6533. return $this->userinfo;
  6534. }
  6535. /**
  6536. * Get the host
  6537. *
  6538. * @access public
  6539. * @return string
  6540. */
  6541. public function get_host()
  6542. {
  6543. return $this->host;
  6544. }
  6545. /**
  6546. * Get the port
  6547. *
  6548. * @access public
  6549. * @return string
  6550. */
  6551. public function get_port()
  6552. {
  6553. return $this->port;
  6554. }
  6555. /**
  6556. * Get the path
  6557. *
  6558. * @access public
  6559. * @return string
  6560. */
  6561. public function get_path()
  6562. {
  6563. return $this->path;
  6564. }
  6565. /**
  6566. * Get the query
  6567. *
  6568. * @access public
  6569. * @return string
  6570. */
  6571. public function get_query()
  6572. {
  6573. return $this->query;
  6574. }
  6575. /**
  6576. * Get the fragment
  6577. *
  6578. * @access public
  6579. * @return string
  6580. */
  6581. public function get_fragment()
  6582. {
  6583. return $this->fragment;
  6584. }
  6585. }
  6586. class SimplePie_Item
  6587. {
  6588. var $feed;
  6589. var $data = array();
  6590. public function __construct($feed, $data)
  6591. {
  6592. $this->feed = $feed;
  6593. $this->data = $data;
  6594. }
  6595. public function __toString()
  6596. {
  6597. return md5(serialize($this->data));
  6598. }
  6599. /**
  6600. * Remove items that link back to this before destroying this object
  6601. */
  6602. public function __destruct()
  6603. {
  6604. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  6605. {
  6606. unset($this->feed);
  6607. }
  6608. }
  6609. public function get_item_tags($namespace, $tag)
  6610. {
  6611. if (isset($this->data['child'][$namespace][$tag]))
  6612. {
  6613. return $this->data['child'][$namespace][$tag];
  6614. }
  6615. else
  6616. {
  6617. return null;
  6618. }
  6619. }
  6620. public function get_base($element = array())
  6621. {
  6622. return $this->feed->get_base($element);
  6623. }
  6624. public function sanitize($data, $type, $base = '')
  6625. {
  6626. return $this->feed->sanitize($data, $type, $base);
  6627. }
  6628. public function get_feed()
  6629. {
  6630. return $this->feed;
  6631. }
  6632. public function get_id($hash = false)
  6633. {
  6634. if (!$hash)
  6635. {
  6636. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
  6637. {
  6638. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6639. }
  6640. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
  6641. {
  6642. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6643. }
  6644. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  6645. {
  6646. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6647. }
  6648. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
  6649. {
  6650. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6651. }
  6652. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
  6653. {
  6654. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6655. }
  6656. elseif (isset($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about']))
  6657. {
  6658. return $this->sanitize($this->data['attribs'][SIMPLEPIE_NAMESPACE_RDF]['about'], SIMPLEPIE_CONSTRUCT_TEXT);
  6659. }
  6660. elseif (($return = $this->get_permalink()) !== null)
  6661. {
  6662. return $return;
  6663. }
  6664. elseif (($return = $this->get_title()) !== null)
  6665. {
  6666. return $return;
  6667. }
  6668. }
  6669. if ($this->get_permalink() !== null || $this->get_title() !== null)
  6670. {
  6671. return md5($this->get_permalink() . $this->get_title());
  6672. }
  6673. else
  6674. {
  6675. return md5(serialize($this->data));
  6676. }
  6677. }
  6678. public function get_title()
  6679. {
  6680. if (!isset($this->data['title']))
  6681. {
  6682. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  6683. {
  6684. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6685. }
  6686. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  6687. {
  6688. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6689. }
  6690. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  6691. {
  6692. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  6693. }
  6694. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  6695. {
  6696. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  6697. }
  6698. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  6699. {
  6700. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  6701. }
  6702. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  6703. {
  6704. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6705. }
  6706. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  6707. {
  6708. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6709. }
  6710. else
  6711. {
  6712. $this->data['title'] = null;
  6713. }
  6714. }
  6715. return $this->data['title'];
  6716. }
  6717. public function get_description($description_only = false)
  6718. {
  6719. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
  6720. {
  6721. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6722. }
  6723. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
  6724. {
  6725. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6726. }
  6727. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  6728. {
  6729. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  6730. }
  6731. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  6732. {
  6733. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  6734. }
  6735. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  6736. {
  6737. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6738. }
  6739. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  6740. {
  6741. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6742. }
  6743. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  6744. {
  6745. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  6746. }
  6747. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  6748. {
  6749. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6750. }
  6751. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  6752. {
  6753. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
  6754. }
  6755. elseif (!$description_only)
  6756. {
  6757. return $this->get_content(true);
  6758. }
  6759. else
  6760. {
  6761. return null;
  6762. }
  6763. }
  6764. public function get_content($content_only = false)
  6765. {
  6766. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
  6767. {
  6768. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6769. }
  6770. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
  6771. {
  6772. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  6773. }
  6774. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
  6775. {
  6776. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  6777. }
  6778. elseif (!$content_only)
  6779. {
  6780. return $this->get_description(true);
  6781. }
  6782. else
  6783. {
  6784. return null;
  6785. }
  6786. }
  6787. public function get_category($key = 0)
  6788. {
  6789. $categories = $this->get_categories();
  6790. if (isset($categories[$key]))
  6791. {
  6792. return $categories[$key];
  6793. }
  6794. else
  6795. {
  6796. return null;
  6797. }
  6798. }
  6799. public function get_categories()
  6800. {
  6801. $categories = array();
  6802. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  6803. {
  6804. $term = null;
  6805. $scheme = null;
  6806. $label = null;
  6807. if (isset($category['attribs']['']['term']))
  6808. {
  6809. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  6810. }
  6811. if (isset($category['attribs']['']['scheme']))
  6812. {
  6813. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  6814. }
  6815. if (isset($category['attribs']['']['label']))
  6816. {
  6817. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  6818. }
  6819. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  6820. }
  6821. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  6822. {
  6823. // This is really the label, but keep this as the term also for BC.
  6824. // Label will also work on retrieving because that falls back to term.
  6825. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6826. if (isset($category['attribs']['']['domain']))
  6827. {
  6828. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  6829. }
  6830. else
  6831. {
  6832. $scheme = null;
  6833. }
  6834. $categories[] = new $this->feed->category_class($term, $scheme, null);
  6835. }
  6836. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  6837. {
  6838. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  6839. }
  6840. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  6841. {
  6842. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  6843. }
  6844. if (!empty($categories))
  6845. {
  6846. return SimplePie_Misc::array_unique($categories);
  6847. }
  6848. else
  6849. {
  6850. return null;
  6851. }
  6852. }
  6853. public function get_author($key = 0)
  6854. {
  6855. $authors = $this->get_authors();
  6856. if (isset($authors[$key]))
  6857. {
  6858. return $authors[$key];
  6859. }
  6860. else
  6861. {
  6862. return null;
  6863. }
  6864. }
  6865. public function get_contributor($key = 0)
  6866. {
  6867. $contributors = $this->get_contributors();
  6868. if (isset($contributors[$key]))
  6869. {
  6870. return $contributors[$key];
  6871. }
  6872. else
  6873. {
  6874. return null;
  6875. }
  6876. }
  6877. public function get_contributors()
  6878. {
  6879. $contributors = array();
  6880. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  6881. {
  6882. $name = null;
  6883. $uri = null;
  6884. $email = null;
  6885. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  6886. {
  6887. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6888. }
  6889. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  6890. {
  6891. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  6892. }
  6893. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  6894. {
  6895. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6896. }
  6897. if ($name !== null || $email !== null || $uri !== null)
  6898. {
  6899. $contributors[] = new $this->feed->author_class($name, $uri, $email);
  6900. }
  6901. }
  6902. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  6903. {
  6904. $name = null;
  6905. $url = null;
  6906. $email = null;
  6907. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  6908. {
  6909. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6910. }
  6911. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  6912. {
  6913. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  6914. }
  6915. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  6916. {
  6917. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6918. }
  6919. if ($name !== null || $email !== null || $url !== null)
  6920. {
  6921. $contributors[] = new $this->feed->author_class($name, $url, $email);
  6922. }
  6923. }
  6924. if (!empty($contributors))
  6925. {
  6926. return SimplePie_Misc::array_unique($contributors);
  6927. }
  6928. else
  6929. {
  6930. return null;
  6931. }
  6932. }
  6933. public function get_authors()
  6934. {
  6935. $authors = array();
  6936. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  6937. {
  6938. $name = null;
  6939. $uri = null;
  6940. $email = null;
  6941. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  6942. {
  6943. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6944. }
  6945. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  6946. {
  6947. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  6948. }
  6949. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  6950. {
  6951. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6952. }
  6953. if ($name !== null || $email !== null || $uri !== null)
  6954. {
  6955. $authors[] = new $this->feed->author_class($name, $uri, $email);
  6956. }
  6957. }
  6958. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  6959. {
  6960. $name = null;
  6961. $url = null;
  6962. $email = null;
  6963. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  6964. {
  6965. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6966. }
  6967. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  6968. {
  6969. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  6970. }
  6971. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  6972. {
  6973. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  6974. }
  6975. if ($name !== null || $email !== null || $url !== null)
  6976. {
  6977. $authors[] = new $this->feed->author_class($name, $url, $email);
  6978. }
  6979. }
  6980. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
  6981. {
  6982. $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  6983. }
  6984. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  6985. {
  6986. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  6987. }
  6988. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  6989. {
  6990. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  6991. }
  6992. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  6993. {
  6994. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  6995. }
  6996. if (!empty($authors))
  6997. {
  6998. return SimplePie_Misc::array_unique($authors);
  6999. }
  7000. elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
  7001. {
  7002. return $authors;
  7003. }
  7004. elseif ($authors = $this->feed->get_authors())
  7005. {
  7006. return $authors;
  7007. }
  7008. else
  7009. {
  7010. return null;
  7011. }
  7012. }
  7013. public function get_copyright()
  7014. {
  7015. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  7016. {
  7017. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  7018. }
  7019. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  7020. {
  7021. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7022. }
  7023. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  7024. {
  7025. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7026. }
  7027. else
  7028. {
  7029. return null;
  7030. }
  7031. }
  7032. public function get_date($date_format = 'j F Y, g:i a')
  7033. {
  7034. if (!isset($this->data['date']))
  7035. {
  7036. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
  7037. {
  7038. $this->data['date']['raw'] = $return[0]['data'];
  7039. }
  7040. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
  7041. {
  7042. $this->data['date']['raw'] = $return[0]['data'];
  7043. }
  7044. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
  7045. {
  7046. $this->data['date']['raw'] = $return[0]['data'];
  7047. }
  7048. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
  7049. {
  7050. $this->data['date']['raw'] = $return[0]['data'];
  7051. }
  7052. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
  7053. {
  7054. $this->data['date']['raw'] = $return[0]['data'];
  7055. }
  7056. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
  7057. {
  7058. $this->data['date']['raw'] = $return[0]['data'];
  7059. }
  7060. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
  7061. {
  7062. $this->data['date']['raw'] = $return[0]['data'];
  7063. }
  7064. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
  7065. {
  7066. $this->data['date']['raw'] = $return[0]['data'];
  7067. }
  7068. if (!empty($this->data['date']['raw']))
  7069. {
  7070. $parser = SimplePie_Parse_Date::get();
  7071. $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
  7072. }
  7073. else
  7074. {
  7075. $this->data['date'] = null;
  7076. }
  7077. }
  7078. if ($this->data['date'])
  7079. {
  7080. $date_format = (string) $date_format;
  7081. switch ($date_format)
  7082. {
  7083. case '':
  7084. return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
  7085. case 'U':
  7086. return $this->data['date']['parsed'];
  7087. default:
  7088. return date($date_format, $this->data['date']['parsed']);
  7089. }
  7090. }
  7091. else
  7092. {
  7093. return null;
  7094. }
  7095. }
  7096. public function get_local_date($date_format = '%c')
  7097. {
  7098. if (!$date_format)
  7099. {
  7100. return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
  7101. }
  7102. elseif (($date = $this->get_date('U')) !== null && $date !== false)
  7103. {
  7104. return strftime($date_format, $date);
  7105. }
  7106. else
  7107. {
  7108. return null;
  7109. }
  7110. }
  7111. public function get_permalink()
  7112. {
  7113. $link = $this->get_link();
  7114. $enclosure = $this->get_enclosure(0);
  7115. if ($link !== null)
  7116. {
  7117. return $link;
  7118. }
  7119. elseif ($enclosure !== null)
  7120. {
  7121. return $enclosure->get_link();
  7122. }
  7123. else
  7124. {
  7125. return null;
  7126. }
  7127. }
  7128. public function get_link($key = 0, $rel = 'alternate')
  7129. {
  7130. $links = $this->get_links($rel);
  7131. if ($links[$key] !== null)
  7132. {
  7133. return $links[$key];
  7134. }
  7135. else
  7136. {
  7137. return null;
  7138. }
  7139. }
  7140. public function get_links($rel = 'alternate')
  7141. {
  7142. if (!isset($this->data['links']))
  7143. {
  7144. $this->data['links'] = array();
  7145. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  7146. {
  7147. if (isset($link['attribs']['']['href']))
  7148. {
  7149. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  7150. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  7151. }
  7152. }
  7153. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  7154. {
  7155. if (isset($link['attribs']['']['href']))
  7156. {
  7157. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  7158. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  7159. }
  7160. }
  7161. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  7162. {
  7163. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  7164. }
  7165. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  7166. {
  7167. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  7168. }
  7169. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  7170. {
  7171. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  7172. }
  7173. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  7174. {
  7175. if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
  7176. {
  7177. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  7178. }
  7179. }
  7180. $keys = array_keys($this->data['links']);
  7181. foreach ($keys as $key)
  7182. {
  7183. if (SimplePie_Misc::is_isegment_nz_nc($key))
  7184. {
  7185. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  7186. {
  7187. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  7188. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  7189. }
  7190. else
  7191. {
  7192. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  7193. }
  7194. }
  7195. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  7196. {
  7197. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  7198. }
  7199. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  7200. }
  7201. }
  7202. if (isset($this->data['links'][$rel]))
  7203. {
  7204. return $this->data['links'][$rel];
  7205. }
  7206. else
  7207. {
  7208. return null;
  7209. }
  7210. }
  7211. /**
  7212. * @todo Add ability to prefer one type of content over another (in a media group).
  7213. */
  7214. public function get_enclosure($key = 0, $prefer = null)
  7215. {
  7216. $enclosures = $this->get_enclosures();
  7217. if (isset($enclosures[$key]))
  7218. {
  7219. return $enclosures[$key];
  7220. }
  7221. else
  7222. {
  7223. return null;
  7224. }
  7225. }
  7226. /**
  7227. * Grabs all available enclosures (podcasts, etc.)
  7228. *
  7229. * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
  7230. *
  7231. * At this point, we're pretty much assuming that all enclosures for an item are the same content. Anything else is too complicated to properly support.
  7232. *
  7233. * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
  7234. * @todo If an element exists at a level, but it's value is empty, we should fall back to the value from the parent (if it exists).
  7235. */
  7236. public function get_enclosures()
  7237. {
  7238. if (!isset($this->data['enclosures']))
  7239. {
  7240. $this->data['enclosures'] = array();
  7241. // Elements
  7242. $captions_parent = null;
  7243. $categories_parent = null;
  7244. $copyrights_parent = null;
  7245. $credits_parent = null;
  7246. $description_parent = null;
  7247. $duration_parent = null;
  7248. $hashes_parent = null;
  7249. $keywords_parent = null;
  7250. $player_parent = null;
  7251. $ratings_parent = null;
  7252. $restrictions_parent = null;
  7253. $thumbnails_parent = null;
  7254. $title_parent = null;
  7255. // Let's do the channel and item-level ones first, and just re-use them if we need to.
  7256. $parent = $this->get_feed();
  7257. // CAPTIONS
  7258. if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  7259. {
  7260. foreach ($captions as $caption)
  7261. {
  7262. $caption_type = null;
  7263. $caption_lang = null;
  7264. $caption_startTime = null;
  7265. $caption_endTime = null;
  7266. $caption_text = null;
  7267. if (isset($caption['attribs']['']['type']))
  7268. {
  7269. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7270. }
  7271. if (isset($caption['attribs']['']['lang']))
  7272. {
  7273. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  7274. }
  7275. if (isset($caption['attribs']['']['start']))
  7276. {
  7277. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  7278. }
  7279. if (isset($caption['attribs']['']['end']))
  7280. {
  7281. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  7282. }
  7283. if (isset($caption['data']))
  7284. {
  7285. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7286. }
  7287. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  7288. }
  7289. }
  7290. elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  7291. {
  7292. foreach ($captions as $caption)
  7293. {
  7294. $caption_type = null;
  7295. $caption_lang = null;
  7296. $caption_startTime = null;
  7297. $caption_endTime = null;
  7298. $caption_text = null;
  7299. if (isset($caption['attribs']['']['type']))
  7300. {
  7301. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7302. }
  7303. if (isset($caption['attribs']['']['lang']))
  7304. {
  7305. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  7306. }
  7307. if (isset($caption['attribs']['']['start']))
  7308. {
  7309. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  7310. }
  7311. if (isset($caption['attribs']['']['end']))
  7312. {
  7313. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  7314. }
  7315. if (isset($caption['data']))
  7316. {
  7317. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7318. }
  7319. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  7320. }
  7321. }
  7322. if (is_array($captions_parent))
  7323. {
  7324. $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
  7325. }
  7326. // CATEGORIES
  7327. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  7328. {
  7329. $term = null;
  7330. $scheme = null;
  7331. $label = null;
  7332. if (isset($category['data']))
  7333. {
  7334. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7335. }
  7336. if (isset($category['attribs']['']['scheme']))
  7337. {
  7338. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7339. }
  7340. else
  7341. {
  7342. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  7343. }
  7344. if (isset($category['attribs']['']['label']))
  7345. {
  7346. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  7347. }
  7348. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  7349. }
  7350. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  7351. {
  7352. $term = null;
  7353. $scheme = null;
  7354. $label = null;
  7355. if (isset($category['data']))
  7356. {
  7357. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7358. }
  7359. if (isset($category['attribs']['']['scheme']))
  7360. {
  7361. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7362. }
  7363. else
  7364. {
  7365. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  7366. }
  7367. if (isset($category['attribs']['']['label']))
  7368. {
  7369. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  7370. }
  7371. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  7372. }
  7373. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
  7374. {
  7375. $term = null;
  7376. $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
  7377. $label = null;
  7378. if (isset($category['attribs']['']['text']))
  7379. {
  7380. $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  7381. }
  7382. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  7383. if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
  7384. {
  7385. foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
  7386. {
  7387. if (isset($subcategory['attribs']['']['text']))
  7388. {
  7389. $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  7390. }
  7391. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  7392. }
  7393. }
  7394. }
  7395. if (is_array($categories_parent))
  7396. {
  7397. $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
  7398. }
  7399. // COPYRIGHT
  7400. if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  7401. {
  7402. $copyright_url = null;
  7403. $copyright_label = null;
  7404. if (isset($copyright[0]['attribs']['']['url']))
  7405. {
  7406. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  7407. }
  7408. if (isset($copyright[0]['data']))
  7409. {
  7410. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7411. }
  7412. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  7413. }
  7414. elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  7415. {
  7416. $copyright_url = null;
  7417. $copyright_label = null;
  7418. if (isset($copyright[0]['attribs']['']['url']))
  7419. {
  7420. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  7421. }
  7422. if (isset($copyright[0]['data']))
  7423. {
  7424. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7425. }
  7426. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  7427. }
  7428. // CREDITS
  7429. if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  7430. {
  7431. foreach ($credits as $credit)
  7432. {
  7433. $credit_role = null;
  7434. $credit_scheme = null;
  7435. $credit_name = null;
  7436. if (isset($credit['attribs']['']['role']))
  7437. {
  7438. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  7439. }
  7440. if (isset($credit['attribs']['']['scheme']))
  7441. {
  7442. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7443. }
  7444. else
  7445. {
  7446. $credit_scheme = 'urn:ebu';
  7447. }
  7448. if (isset($credit['data']))
  7449. {
  7450. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7451. }
  7452. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  7453. }
  7454. }
  7455. elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  7456. {
  7457. foreach ($credits as $credit)
  7458. {
  7459. $credit_role = null;
  7460. $credit_scheme = null;
  7461. $credit_name = null;
  7462. if (isset($credit['attribs']['']['role']))
  7463. {
  7464. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  7465. }
  7466. if (isset($credit['attribs']['']['scheme']))
  7467. {
  7468. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7469. }
  7470. else
  7471. {
  7472. $credit_scheme = 'urn:ebu';
  7473. }
  7474. if (isset($credit['data']))
  7475. {
  7476. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7477. }
  7478. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  7479. }
  7480. }
  7481. if (is_array($credits_parent))
  7482. {
  7483. $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
  7484. }
  7485. // DESCRIPTION
  7486. if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  7487. {
  7488. if (isset($description_parent[0]['data']))
  7489. {
  7490. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7491. }
  7492. }
  7493. elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  7494. {
  7495. if (isset($description_parent[0]['data']))
  7496. {
  7497. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7498. }
  7499. }
  7500. // DURATION
  7501. if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
  7502. {
  7503. $seconds = null;
  7504. $minutes = null;
  7505. $hours = null;
  7506. if (isset($duration_parent[0]['data']))
  7507. {
  7508. $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  7509. if (sizeof($temp) > 0)
  7510. {
  7511. $seconds = (int) array_pop($temp);
  7512. }
  7513. if (sizeof($temp) > 0)
  7514. {
  7515. $minutes = (int) array_pop($temp);
  7516. $seconds += $minutes * 60;
  7517. }
  7518. if (sizeof($temp) > 0)
  7519. {
  7520. $hours = (int) array_pop($temp);
  7521. $seconds += $hours * 3600;
  7522. }
  7523. unset($temp);
  7524. $duration_parent = $seconds;
  7525. }
  7526. }
  7527. // HASHES
  7528. if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  7529. {
  7530. foreach ($hashes_iterator as $hash)
  7531. {
  7532. $value = null;
  7533. $algo = null;
  7534. if (isset($hash['data']))
  7535. {
  7536. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7537. }
  7538. if (isset($hash['attribs']['']['algo']))
  7539. {
  7540. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  7541. }
  7542. else
  7543. {
  7544. $algo = 'md5';
  7545. }
  7546. $hashes_parent[] = $algo.':'.$value;
  7547. }
  7548. }
  7549. elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  7550. {
  7551. foreach ($hashes_iterator as $hash)
  7552. {
  7553. $value = null;
  7554. $algo = null;
  7555. if (isset($hash['data']))
  7556. {
  7557. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7558. }
  7559. if (isset($hash['attribs']['']['algo']))
  7560. {
  7561. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  7562. }
  7563. else
  7564. {
  7565. $algo = 'md5';
  7566. }
  7567. $hashes_parent[] = $algo.':'.$value;
  7568. }
  7569. }
  7570. if (is_array($hashes_parent))
  7571. {
  7572. $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
  7573. }
  7574. // KEYWORDS
  7575. if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  7576. {
  7577. if (isset($keywords[0]['data']))
  7578. {
  7579. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  7580. foreach ($temp as $word)
  7581. {
  7582. $keywords_parent[] = trim($word);
  7583. }
  7584. }
  7585. unset($temp);
  7586. }
  7587. elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  7588. {
  7589. if (isset($keywords[0]['data']))
  7590. {
  7591. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  7592. foreach ($temp as $word)
  7593. {
  7594. $keywords_parent[] = trim($word);
  7595. }
  7596. }
  7597. unset($temp);
  7598. }
  7599. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  7600. {
  7601. if (isset($keywords[0]['data']))
  7602. {
  7603. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  7604. foreach ($temp as $word)
  7605. {
  7606. $keywords_parent[] = trim($word);
  7607. }
  7608. }
  7609. unset($temp);
  7610. }
  7611. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  7612. {
  7613. if (isset($keywords[0]['data']))
  7614. {
  7615. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  7616. foreach ($temp as $word)
  7617. {
  7618. $keywords_parent[] = trim($word);
  7619. }
  7620. }
  7621. unset($temp);
  7622. }
  7623. if (is_array($keywords_parent))
  7624. {
  7625. $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
  7626. }
  7627. // PLAYER
  7628. if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  7629. {
  7630. if (isset($player_parent[0]['attribs']['']['url']))
  7631. {
  7632. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  7633. }
  7634. }
  7635. elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  7636. {
  7637. if (isset($player_parent[0]['attribs']['']['url']))
  7638. {
  7639. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  7640. }
  7641. }
  7642. // RATINGS
  7643. if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  7644. {
  7645. foreach ($ratings as $rating)
  7646. {
  7647. $rating_scheme = null;
  7648. $rating_value = null;
  7649. if (isset($rating['attribs']['']['scheme']))
  7650. {
  7651. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7652. }
  7653. else
  7654. {
  7655. $rating_scheme = 'urn:simple';
  7656. }
  7657. if (isset($rating['data']))
  7658. {
  7659. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7660. }
  7661. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  7662. }
  7663. }
  7664. elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  7665. {
  7666. foreach ($ratings as $rating)
  7667. {
  7668. $rating_scheme = 'urn:itunes';
  7669. $rating_value = null;
  7670. if (isset($rating['data']))
  7671. {
  7672. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7673. }
  7674. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  7675. }
  7676. }
  7677. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  7678. {
  7679. foreach ($ratings as $rating)
  7680. {
  7681. $rating_scheme = null;
  7682. $rating_value = null;
  7683. if (isset($rating['attribs']['']['scheme']))
  7684. {
  7685. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  7686. }
  7687. else
  7688. {
  7689. $rating_scheme = 'urn:simple';
  7690. }
  7691. if (isset($rating['data']))
  7692. {
  7693. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7694. }
  7695. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  7696. }
  7697. }
  7698. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  7699. {
  7700. foreach ($ratings as $rating)
  7701. {
  7702. $rating_scheme = 'urn:itunes';
  7703. $rating_value = null;
  7704. if (isset($rating['data']))
  7705. {
  7706. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7707. }
  7708. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  7709. }
  7710. }
  7711. if (is_array($ratings_parent))
  7712. {
  7713. $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
  7714. }
  7715. // RESTRICTIONS
  7716. if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  7717. {
  7718. foreach ($restrictions as $restriction)
  7719. {
  7720. $restriction_relationship = null;
  7721. $restriction_type = null;
  7722. $restriction_value = null;
  7723. if (isset($restriction['attribs']['']['relationship']))
  7724. {
  7725. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  7726. }
  7727. if (isset($restriction['attribs']['']['type']))
  7728. {
  7729. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7730. }
  7731. if (isset($restriction['data']))
  7732. {
  7733. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7734. }
  7735. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  7736. }
  7737. }
  7738. elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  7739. {
  7740. foreach ($restrictions as $restriction)
  7741. {
  7742. $restriction_relationship = 'allow';
  7743. $restriction_type = null;
  7744. $restriction_value = 'itunes';
  7745. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  7746. {
  7747. $restriction_relationship = 'deny';
  7748. }
  7749. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  7750. }
  7751. }
  7752. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  7753. {
  7754. foreach ($restrictions as $restriction)
  7755. {
  7756. $restriction_relationship = null;
  7757. $restriction_type = null;
  7758. $restriction_value = null;
  7759. if (isset($restriction['attribs']['']['relationship']))
  7760. {
  7761. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  7762. }
  7763. if (isset($restriction['attribs']['']['type']))
  7764. {
  7765. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7766. }
  7767. if (isset($restriction['data']))
  7768. {
  7769. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7770. }
  7771. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  7772. }
  7773. }
  7774. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  7775. {
  7776. foreach ($restrictions as $restriction)
  7777. {
  7778. $restriction_relationship = 'allow';
  7779. $restriction_type = null;
  7780. $restriction_value = 'itunes';
  7781. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  7782. {
  7783. $restriction_relationship = 'deny';
  7784. }
  7785. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  7786. }
  7787. }
  7788. if (is_array($restrictions_parent))
  7789. {
  7790. $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
  7791. }
  7792. // THUMBNAILS
  7793. if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  7794. {
  7795. foreach ($thumbnails as $thumbnail)
  7796. {
  7797. if (isset($thumbnail['attribs']['']['url']))
  7798. {
  7799. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  7800. }
  7801. }
  7802. }
  7803. elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  7804. {
  7805. foreach ($thumbnails as $thumbnail)
  7806. {
  7807. if (isset($thumbnail['attribs']['']['url']))
  7808. {
  7809. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  7810. }
  7811. }
  7812. }
  7813. // TITLES
  7814. if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  7815. {
  7816. if (isset($title_parent[0]['data']))
  7817. {
  7818. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7819. }
  7820. }
  7821. elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  7822. {
  7823. if (isset($title_parent[0]['data']))
  7824. {
  7825. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7826. }
  7827. }
  7828. // Clear the memory
  7829. unset($parent);
  7830. // Attributes
  7831. $bitrate = null;
  7832. $channels = null;
  7833. $duration = null;
  7834. $expression = null;
  7835. $framerate = null;
  7836. $height = null;
  7837. $javascript = null;
  7838. $lang = null;
  7839. $length = null;
  7840. $medium = null;
  7841. $samplingrate = null;
  7842. $type = null;
  7843. $url = null;
  7844. $width = null;
  7845. // Elements
  7846. $captions = null;
  7847. $categories = null;
  7848. $copyrights = null;
  7849. $credits = null;
  7850. $description = null;
  7851. $hashes = null;
  7852. $keywords = null;
  7853. $player = null;
  7854. $ratings = null;
  7855. $restrictions = null;
  7856. $thumbnails = null;
  7857. $title = null;
  7858. // If we have media:group tags, loop through them.
  7859. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
  7860. {
  7861. if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  7862. {
  7863. // If we have media:content tags, loop through them.
  7864. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  7865. {
  7866. if (isset($content['attribs']['']['url']))
  7867. {
  7868. // Attributes
  7869. $bitrate = null;
  7870. $channels = null;
  7871. $duration = null;
  7872. $expression = null;
  7873. $framerate = null;
  7874. $height = null;
  7875. $javascript = null;
  7876. $lang = null;
  7877. $length = null;
  7878. $medium = null;
  7879. $samplingrate = null;
  7880. $type = null;
  7881. $url = null;
  7882. $width = null;
  7883. // Elements
  7884. $captions = null;
  7885. $categories = null;
  7886. $copyrights = null;
  7887. $credits = null;
  7888. $description = null;
  7889. $hashes = null;
  7890. $keywords = null;
  7891. $player = null;
  7892. $ratings = null;
  7893. $restrictions = null;
  7894. $thumbnails = null;
  7895. $title = null;
  7896. // Start checking the attributes of media:content
  7897. if (isset($content['attribs']['']['bitrate']))
  7898. {
  7899. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  7900. }
  7901. if (isset($content['attribs']['']['channels']))
  7902. {
  7903. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  7904. }
  7905. if (isset($content['attribs']['']['duration']))
  7906. {
  7907. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  7908. }
  7909. else
  7910. {
  7911. $duration = $duration_parent;
  7912. }
  7913. if (isset($content['attribs']['']['expression']))
  7914. {
  7915. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  7916. }
  7917. if (isset($content['attribs']['']['framerate']))
  7918. {
  7919. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  7920. }
  7921. if (isset($content['attribs']['']['height']))
  7922. {
  7923. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  7924. }
  7925. if (isset($content['attribs']['']['lang']))
  7926. {
  7927. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  7928. }
  7929. if (isset($content['attribs']['']['fileSize']))
  7930. {
  7931. $length = ceil($content['attribs']['']['fileSize']);
  7932. }
  7933. if (isset($content['attribs']['']['medium']))
  7934. {
  7935. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  7936. }
  7937. if (isset($content['attribs']['']['samplingrate']))
  7938. {
  7939. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  7940. }
  7941. if (isset($content['attribs']['']['type']))
  7942. {
  7943. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7944. }
  7945. if (isset($content['attribs']['']['width']))
  7946. {
  7947. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  7948. }
  7949. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  7950. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  7951. // CAPTIONS
  7952. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  7953. {
  7954. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  7955. {
  7956. $caption_type = null;
  7957. $caption_lang = null;
  7958. $caption_startTime = null;
  7959. $caption_endTime = null;
  7960. $caption_text = null;
  7961. if (isset($caption['attribs']['']['type']))
  7962. {
  7963. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  7964. }
  7965. if (isset($caption['attribs']['']['lang']))
  7966. {
  7967. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  7968. }
  7969. if (isset($caption['attribs']['']['start']))
  7970. {
  7971. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  7972. }
  7973. if (isset($caption['attribs']['']['end']))
  7974. {
  7975. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  7976. }
  7977. if (isset($caption['data']))
  7978. {
  7979. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  7980. }
  7981. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  7982. }
  7983. if (is_array($captions))
  7984. {
  7985. $captions = array_values(SimplePie_Misc::array_unique($captions));
  7986. }
  7987. }
  7988. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  7989. {
  7990. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  7991. {
  7992. $caption_type = null;
  7993. $caption_lang = null;
  7994. $caption_startTime = null;
  7995. $caption_endTime = null;
  7996. $caption_text = null;
  7997. if (isset($caption['attribs']['']['type']))
  7998. {
  7999. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8000. }
  8001. if (isset($caption['attribs']['']['lang']))
  8002. {
  8003. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  8004. }
  8005. if (isset($caption['attribs']['']['start']))
  8006. {
  8007. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  8008. }
  8009. if (isset($caption['attribs']['']['end']))
  8010. {
  8011. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  8012. }
  8013. if (isset($caption['data']))
  8014. {
  8015. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8016. }
  8017. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  8018. }
  8019. if (is_array($captions))
  8020. {
  8021. $captions = array_values(SimplePie_Misc::array_unique($captions));
  8022. }
  8023. }
  8024. else
  8025. {
  8026. $captions = $captions_parent;
  8027. }
  8028. // CATEGORIES
  8029. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  8030. {
  8031. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  8032. {
  8033. $term = null;
  8034. $scheme = null;
  8035. $label = null;
  8036. if (isset($category['data']))
  8037. {
  8038. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8039. }
  8040. if (isset($category['attribs']['']['scheme']))
  8041. {
  8042. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8043. }
  8044. else
  8045. {
  8046. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  8047. }
  8048. if (isset($category['attribs']['']['label']))
  8049. {
  8050. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  8051. }
  8052. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  8053. }
  8054. }
  8055. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  8056. {
  8057. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  8058. {
  8059. $term = null;
  8060. $scheme = null;
  8061. $label = null;
  8062. if (isset($category['data']))
  8063. {
  8064. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8065. }
  8066. if (isset($category['attribs']['']['scheme']))
  8067. {
  8068. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8069. }
  8070. else
  8071. {
  8072. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  8073. }
  8074. if (isset($category['attribs']['']['label']))
  8075. {
  8076. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  8077. }
  8078. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  8079. }
  8080. }
  8081. if (is_array($categories) && is_array($categories_parent))
  8082. {
  8083. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  8084. }
  8085. elseif (is_array($categories))
  8086. {
  8087. $categories = array_values(SimplePie_Misc::array_unique($categories));
  8088. }
  8089. elseif (is_array($categories_parent))
  8090. {
  8091. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  8092. }
  8093. // COPYRIGHTS
  8094. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  8095. {
  8096. $copyright_url = null;
  8097. $copyright_label = null;
  8098. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  8099. {
  8100. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  8101. }
  8102. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  8103. {
  8104. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8105. }
  8106. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  8107. }
  8108. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  8109. {
  8110. $copyright_url = null;
  8111. $copyright_label = null;
  8112. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  8113. {
  8114. $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  8115. }
  8116. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  8117. {
  8118. $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8119. }
  8120. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  8121. }
  8122. else
  8123. {
  8124. $copyrights = $copyrights_parent;
  8125. }
  8126. // CREDITS
  8127. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  8128. {
  8129. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  8130. {
  8131. $credit_role = null;
  8132. $credit_scheme = null;
  8133. $credit_name = null;
  8134. if (isset($credit['attribs']['']['role']))
  8135. {
  8136. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  8137. }
  8138. if (isset($credit['attribs']['']['scheme']))
  8139. {
  8140. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8141. }
  8142. else
  8143. {
  8144. $credit_scheme = 'urn:ebu';
  8145. }
  8146. if (isset($credit['data']))
  8147. {
  8148. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8149. }
  8150. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  8151. }
  8152. if (is_array($credits))
  8153. {
  8154. $credits = array_values(SimplePie_Misc::array_unique($credits));
  8155. }
  8156. }
  8157. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  8158. {
  8159. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  8160. {
  8161. $credit_role = null;
  8162. $credit_scheme = null;
  8163. $credit_name = null;
  8164. if (isset($credit['attribs']['']['role']))
  8165. {
  8166. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  8167. }
  8168. if (isset($credit['attribs']['']['scheme']))
  8169. {
  8170. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8171. }
  8172. else
  8173. {
  8174. $credit_scheme = 'urn:ebu';
  8175. }
  8176. if (isset($credit['data']))
  8177. {
  8178. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8179. }
  8180. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  8181. }
  8182. if (is_array($credits))
  8183. {
  8184. $credits = array_values(SimplePie_Misc::array_unique($credits));
  8185. }
  8186. }
  8187. else
  8188. {
  8189. $credits = $credits_parent;
  8190. }
  8191. // DESCRIPTION
  8192. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  8193. {
  8194. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8195. }
  8196. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  8197. {
  8198. $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8199. }
  8200. else
  8201. {
  8202. $description = $description_parent;
  8203. }
  8204. // HASHES
  8205. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  8206. {
  8207. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  8208. {
  8209. $value = null;
  8210. $algo = null;
  8211. if (isset($hash['data']))
  8212. {
  8213. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8214. }
  8215. if (isset($hash['attribs']['']['algo']))
  8216. {
  8217. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  8218. }
  8219. else
  8220. {
  8221. $algo = 'md5';
  8222. }
  8223. $hashes[] = $algo.':'.$value;
  8224. }
  8225. if (is_array($hashes))
  8226. {
  8227. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  8228. }
  8229. }
  8230. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  8231. {
  8232. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  8233. {
  8234. $value = null;
  8235. $algo = null;
  8236. if (isset($hash['data']))
  8237. {
  8238. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8239. }
  8240. if (isset($hash['attribs']['']['algo']))
  8241. {
  8242. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  8243. }
  8244. else
  8245. {
  8246. $algo = 'md5';
  8247. }
  8248. $hashes[] = $algo.':'.$value;
  8249. }
  8250. if (is_array($hashes))
  8251. {
  8252. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  8253. }
  8254. }
  8255. else
  8256. {
  8257. $hashes = $hashes_parent;
  8258. }
  8259. // KEYWORDS
  8260. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  8261. {
  8262. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  8263. {
  8264. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  8265. foreach ($temp as $word)
  8266. {
  8267. $keywords[] = trim($word);
  8268. }
  8269. unset($temp);
  8270. }
  8271. if (is_array($keywords))
  8272. {
  8273. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  8274. }
  8275. }
  8276. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  8277. {
  8278. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  8279. {
  8280. $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  8281. foreach ($temp as $word)
  8282. {
  8283. $keywords[] = trim($word);
  8284. }
  8285. unset($temp);
  8286. }
  8287. if (is_array($keywords))
  8288. {
  8289. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  8290. }
  8291. }
  8292. else
  8293. {
  8294. $keywords = $keywords_parent;
  8295. }
  8296. // PLAYER
  8297. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  8298. {
  8299. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8300. }
  8301. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  8302. {
  8303. $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8304. }
  8305. else
  8306. {
  8307. $player = $player_parent;
  8308. }
  8309. // RATINGS
  8310. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  8311. {
  8312. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  8313. {
  8314. $rating_scheme = null;
  8315. $rating_value = null;
  8316. if (isset($rating['attribs']['']['scheme']))
  8317. {
  8318. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8319. }
  8320. else
  8321. {
  8322. $rating_scheme = 'urn:simple';
  8323. }
  8324. if (isset($rating['data']))
  8325. {
  8326. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8327. }
  8328. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  8329. }
  8330. if (is_array($ratings))
  8331. {
  8332. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  8333. }
  8334. }
  8335. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  8336. {
  8337. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  8338. {
  8339. $rating_scheme = null;
  8340. $rating_value = null;
  8341. if (isset($rating['attribs']['']['scheme']))
  8342. {
  8343. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8344. }
  8345. else
  8346. {
  8347. $rating_scheme = 'urn:simple';
  8348. }
  8349. if (isset($rating['data']))
  8350. {
  8351. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8352. }
  8353. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  8354. }
  8355. if (is_array($ratings))
  8356. {
  8357. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  8358. }
  8359. }
  8360. else
  8361. {
  8362. $ratings = $ratings_parent;
  8363. }
  8364. // RESTRICTIONS
  8365. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  8366. {
  8367. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  8368. {
  8369. $restriction_relationship = null;
  8370. $restriction_type = null;
  8371. $restriction_value = null;
  8372. if (isset($restriction['attribs']['']['relationship']))
  8373. {
  8374. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  8375. }
  8376. if (isset($restriction['attribs']['']['type']))
  8377. {
  8378. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8379. }
  8380. if (isset($restriction['data']))
  8381. {
  8382. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8383. }
  8384. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  8385. }
  8386. if (is_array($restrictions))
  8387. {
  8388. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  8389. }
  8390. }
  8391. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  8392. {
  8393. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  8394. {
  8395. $restriction_relationship = null;
  8396. $restriction_type = null;
  8397. $restriction_value = null;
  8398. if (isset($restriction['attribs']['']['relationship']))
  8399. {
  8400. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  8401. }
  8402. if (isset($restriction['attribs']['']['type']))
  8403. {
  8404. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8405. }
  8406. if (isset($restriction['data']))
  8407. {
  8408. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8409. }
  8410. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  8411. }
  8412. if (is_array($restrictions))
  8413. {
  8414. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  8415. }
  8416. }
  8417. else
  8418. {
  8419. $restrictions = $restrictions_parent;
  8420. }
  8421. // THUMBNAILS
  8422. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  8423. {
  8424. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  8425. {
  8426. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8427. }
  8428. if (is_array($thumbnails))
  8429. {
  8430. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  8431. }
  8432. }
  8433. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  8434. {
  8435. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  8436. {
  8437. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8438. }
  8439. if (is_array($thumbnails))
  8440. {
  8441. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  8442. }
  8443. }
  8444. else
  8445. {
  8446. $thumbnails = $thumbnails_parent;
  8447. }
  8448. // TITLES
  8449. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  8450. {
  8451. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8452. }
  8453. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  8454. {
  8455. $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8456. }
  8457. else
  8458. {
  8459. $title = $title_parent;
  8460. }
  8461. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
  8462. }
  8463. }
  8464. }
  8465. }
  8466. // If we have standalone media:content tags, loop through them.
  8467. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  8468. {
  8469. foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  8470. {
  8471. if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  8472. {
  8473. // Attributes
  8474. $bitrate = null;
  8475. $channels = null;
  8476. $duration = null;
  8477. $expression = null;
  8478. $framerate = null;
  8479. $height = null;
  8480. $javascript = null;
  8481. $lang = null;
  8482. $length = null;
  8483. $medium = null;
  8484. $samplingrate = null;
  8485. $type = null;
  8486. $url = null;
  8487. $width = null;
  8488. // Elements
  8489. $captions = null;
  8490. $categories = null;
  8491. $copyrights = null;
  8492. $credits = null;
  8493. $description = null;
  8494. $hashes = null;
  8495. $keywords = null;
  8496. $player = null;
  8497. $ratings = null;
  8498. $restrictions = null;
  8499. $thumbnails = null;
  8500. $title = null;
  8501. // Start checking the attributes of media:content
  8502. if (isset($content['attribs']['']['bitrate']))
  8503. {
  8504. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  8505. }
  8506. if (isset($content['attribs']['']['channels']))
  8507. {
  8508. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  8509. }
  8510. if (isset($content['attribs']['']['duration']))
  8511. {
  8512. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  8513. }
  8514. else
  8515. {
  8516. $duration = $duration_parent;
  8517. }
  8518. if (isset($content['attribs']['']['expression']))
  8519. {
  8520. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  8521. }
  8522. if (isset($content['attribs']['']['framerate']))
  8523. {
  8524. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  8525. }
  8526. if (isset($content['attribs']['']['height']))
  8527. {
  8528. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  8529. }
  8530. if (isset($content['attribs']['']['lang']))
  8531. {
  8532. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  8533. }
  8534. if (isset($content['attribs']['']['fileSize']))
  8535. {
  8536. $length = ceil($content['attribs']['']['fileSize']);
  8537. }
  8538. if (isset($content['attribs']['']['medium']))
  8539. {
  8540. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  8541. }
  8542. if (isset($content['attribs']['']['samplingrate']))
  8543. {
  8544. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  8545. }
  8546. if (isset($content['attribs']['']['type']))
  8547. {
  8548. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8549. }
  8550. if (isset($content['attribs']['']['width']))
  8551. {
  8552. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  8553. }
  8554. if (isset($content['attribs']['']['url']))
  8555. {
  8556. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8557. }
  8558. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  8559. // CAPTIONS
  8560. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  8561. {
  8562. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  8563. {
  8564. $caption_type = null;
  8565. $caption_lang = null;
  8566. $caption_startTime = null;
  8567. $caption_endTime = null;
  8568. $caption_text = null;
  8569. if (isset($caption['attribs']['']['type']))
  8570. {
  8571. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8572. }
  8573. if (isset($caption['attribs']['']['lang']))
  8574. {
  8575. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  8576. }
  8577. if (isset($caption['attribs']['']['start']))
  8578. {
  8579. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  8580. }
  8581. if (isset($caption['attribs']['']['end']))
  8582. {
  8583. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  8584. }
  8585. if (isset($caption['data']))
  8586. {
  8587. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8588. }
  8589. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  8590. }
  8591. if (is_array($captions))
  8592. {
  8593. $captions = array_values(SimplePie_Misc::array_unique($captions));
  8594. }
  8595. }
  8596. else
  8597. {
  8598. $captions = $captions_parent;
  8599. }
  8600. // CATEGORIES
  8601. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  8602. {
  8603. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  8604. {
  8605. $term = null;
  8606. $scheme = null;
  8607. $label = null;
  8608. if (isset($category['data']))
  8609. {
  8610. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8611. }
  8612. if (isset($category['attribs']['']['scheme']))
  8613. {
  8614. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8615. }
  8616. else
  8617. {
  8618. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  8619. }
  8620. if (isset($category['attribs']['']['label']))
  8621. {
  8622. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  8623. }
  8624. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  8625. }
  8626. }
  8627. if (is_array($categories) && is_array($categories_parent))
  8628. {
  8629. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  8630. }
  8631. elseif (is_array($categories))
  8632. {
  8633. $categories = array_values(SimplePie_Misc::array_unique($categories));
  8634. }
  8635. elseif (is_array($categories_parent))
  8636. {
  8637. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  8638. }
  8639. else
  8640. {
  8641. $categories = null;
  8642. }
  8643. // COPYRIGHTS
  8644. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  8645. {
  8646. $copyright_url = null;
  8647. $copyright_label = null;
  8648. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  8649. {
  8650. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  8651. }
  8652. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  8653. {
  8654. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8655. }
  8656. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  8657. }
  8658. else
  8659. {
  8660. $copyrights = $copyrights_parent;
  8661. }
  8662. // CREDITS
  8663. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  8664. {
  8665. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  8666. {
  8667. $credit_role = null;
  8668. $credit_scheme = null;
  8669. $credit_name = null;
  8670. if (isset($credit['attribs']['']['role']))
  8671. {
  8672. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  8673. }
  8674. if (isset($credit['attribs']['']['scheme']))
  8675. {
  8676. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8677. }
  8678. else
  8679. {
  8680. $credit_scheme = 'urn:ebu';
  8681. }
  8682. if (isset($credit['data']))
  8683. {
  8684. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8685. }
  8686. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  8687. }
  8688. if (is_array($credits))
  8689. {
  8690. $credits = array_values(SimplePie_Misc::array_unique($credits));
  8691. }
  8692. }
  8693. else
  8694. {
  8695. $credits = $credits_parent;
  8696. }
  8697. // DESCRIPTION
  8698. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  8699. {
  8700. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8701. }
  8702. else
  8703. {
  8704. $description = $description_parent;
  8705. }
  8706. // HASHES
  8707. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  8708. {
  8709. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  8710. {
  8711. $value = null;
  8712. $algo = null;
  8713. if (isset($hash['data']))
  8714. {
  8715. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8716. }
  8717. if (isset($hash['attribs']['']['algo']))
  8718. {
  8719. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  8720. }
  8721. else
  8722. {
  8723. $algo = 'md5';
  8724. }
  8725. $hashes[] = $algo.':'.$value;
  8726. }
  8727. if (is_array($hashes))
  8728. {
  8729. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  8730. }
  8731. }
  8732. else
  8733. {
  8734. $hashes = $hashes_parent;
  8735. }
  8736. // KEYWORDS
  8737. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  8738. {
  8739. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  8740. {
  8741. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  8742. foreach ($temp as $word)
  8743. {
  8744. $keywords[] = trim($word);
  8745. }
  8746. unset($temp);
  8747. }
  8748. if (is_array($keywords))
  8749. {
  8750. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  8751. }
  8752. }
  8753. else
  8754. {
  8755. $keywords = $keywords_parent;
  8756. }
  8757. // PLAYER
  8758. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  8759. {
  8760. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8761. }
  8762. else
  8763. {
  8764. $player = $player_parent;
  8765. }
  8766. // RATINGS
  8767. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  8768. {
  8769. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  8770. {
  8771. $rating_scheme = null;
  8772. $rating_value = null;
  8773. if (isset($rating['attribs']['']['scheme']))
  8774. {
  8775. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  8776. }
  8777. else
  8778. {
  8779. $rating_scheme = 'urn:simple';
  8780. }
  8781. if (isset($rating['data']))
  8782. {
  8783. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8784. }
  8785. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  8786. }
  8787. if (is_array($ratings))
  8788. {
  8789. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  8790. }
  8791. }
  8792. else
  8793. {
  8794. $ratings = $ratings_parent;
  8795. }
  8796. // RESTRICTIONS
  8797. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  8798. {
  8799. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  8800. {
  8801. $restriction_relationship = null;
  8802. $restriction_type = null;
  8803. $restriction_value = null;
  8804. if (isset($restriction['attribs']['']['relationship']))
  8805. {
  8806. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  8807. }
  8808. if (isset($restriction['attribs']['']['type']))
  8809. {
  8810. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8811. }
  8812. if (isset($restriction['data']))
  8813. {
  8814. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8815. }
  8816. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  8817. }
  8818. if (is_array($restrictions))
  8819. {
  8820. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  8821. }
  8822. }
  8823. else
  8824. {
  8825. $restrictions = $restrictions_parent;
  8826. }
  8827. // THUMBNAILS
  8828. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  8829. {
  8830. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  8831. {
  8832. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  8833. }
  8834. if (is_array($thumbnails))
  8835. {
  8836. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  8837. }
  8838. }
  8839. else
  8840. {
  8841. $thumbnails = $thumbnails_parent;
  8842. }
  8843. // TITLES
  8844. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  8845. {
  8846. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  8847. }
  8848. else
  8849. {
  8850. $title = $title_parent;
  8851. }
  8852. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
  8853. }
  8854. }
  8855. }
  8856. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  8857. {
  8858. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  8859. {
  8860. // Attributes
  8861. $bitrate = null;
  8862. $channels = null;
  8863. $duration = null;
  8864. $expression = null;
  8865. $framerate = null;
  8866. $height = null;
  8867. $javascript = null;
  8868. $lang = null;
  8869. $length = null;
  8870. $medium = null;
  8871. $samplingrate = null;
  8872. $type = null;
  8873. $url = null;
  8874. $width = null;
  8875. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  8876. if (isset($link['attribs']['']['type']))
  8877. {
  8878. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8879. }
  8880. if (isset($link['attribs']['']['length']))
  8881. {
  8882. $length = ceil($link['attribs']['']['length']);
  8883. }
  8884. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  8885. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
  8886. }
  8887. }
  8888. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  8889. {
  8890. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  8891. {
  8892. // Attributes
  8893. $bitrate = null;
  8894. $channels = null;
  8895. $duration = null;
  8896. $expression = null;
  8897. $framerate = null;
  8898. $height = null;
  8899. $javascript = null;
  8900. $lang = null;
  8901. $length = null;
  8902. $medium = null;
  8903. $samplingrate = null;
  8904. $type = null;
  8905. $url = null;
  8906. $width = null;
  8907. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  8908. if (isset($link['attribs']['']['type']))
  8909. {
  8910. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8911. }
  8912. if (isset($link['attribs']['']['length']))
  8913. {
  8914. $length = ceil($link['attribs']['']['length']);
  8915. }
  8916. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  8917. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
  8918. }
  8919. }
  8920. if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
  8921. {
  8922. if (isset($enclosure[0]['attribs']['']['url']))
  8923. {
  8924. // Attributes
  8925. $bitrate = null;
  8926. $channels = null;
  8927. $duration = null;
  8928. $expression = null;
  8929. $framerate = null;
  8930. $height = null;
  8931. $javascript = null;
  8932. $lang = null;
  8933. $length = null;
  8934. $medium = null;
  8935. $samplingrate = null;
  8936. $type = null;
  8937. $url = null;
  8938. $width = null;
  8939. $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
  8940. if (isset($enclosure[0]['attribs']['']['type']))
  8941. {
  8942. $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  8943. }
  8944. if (isset($enclosure[0]['attribs']['']['length']))
  8945. {
  8946. $length = ceil($enclosure[0]['attribs']['']['length']);
  8947. }
  8948. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  8949. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
  8950. }
  8951. }
  8952. if (sizeof($this->data['enclosures']) === 0 && ($url || $type || $length || $bitrate || $captions_parent || $categories_parent || $channels || $copyrights_parent || $credits_parent || $description_parent || $duration_parent || $expression || $framerate || $hashes_parent || $height || $keywords_parent || $lang || $medium || $player_parent || $ratings_parent || $restrictions_parent || $samplingrate || $thumbnails_parent || $title_parent || $width))
  8953. {
  8954. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  8955. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, null, $bitrate, $captions_parent, $categories_parent, $channels, $copyrights_parent, $credits_parent, $description_parent, $duration_parent, $expression, $framerate, $hashes_parent, $height, $keywords_parent, $lang, $medium, $player_parent, $ratings_parent, $restrictions_parent, $samplingrate, $thumbnails_parent, $title_parent, $width);
  8956. }
  8957. $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
  8958. }
  8959. if (!empty($this->data['enclosures']))
  8960. {
  8961. return $this->data['enclosures'];
  8962. }
  8963. else
  8964. {
  8965. return null;
  8966. }
  8967. }
  8968. public function get_latitude()
  8969. {
  8970. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  8971. {
  8972. return (float) $return[0]['data'];
  8973. }
  8974. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  8975. {
  8976. return (float) $match[1];
  8977. }
  8978. else
  8979. {
  8980. return null;
  8981. }
  8982. }
  8983. public function get_longitude()
  8984. {
  8985. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  8986. {
  8987. return (float) $return[0]['data'];
  8988. }
  8989. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  8990. {
  8991. return (float) $return[0]['data'];
  8992. }
  8993. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  8994. {
  8995. return (float) $match[2];
  8996. }
  8997. else
  8998. {
  8999. return null;
  9000. }
  9001. }
  9002. public function get_source()
  9003. {
  9004. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
  9005. {
  9006. return new $this->feed->source_class($this, $return[0]);
  9007. }
  9008. else
  9009. {
  9010. return null;
  9011. }
  9012. }
  9013. }
  9014. class SimplePie_Locator
  9015. {
  9016. var $useragent;
  9017. var $timeout;
  9018. var $file;
  9019. var $local = array();
  9020. var $elsewhere = array();
  9021. var $file_class = 'SimplePie_File';
  9022. var $cached_entities = array();
  9023. var $http_base;
  9024. var $base;
  9025. var $base_location = 0;
  9026. var $checked_feeds = 0;
  9027. var $max_checked_feeds = 10;
  9028. var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  9029. public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
  9030. {
  9031. $this->file =& $file;
  9032. $this->file_class = $file_class;
  9033. $this->useragent = $useragent;
  9034. $this->timeout = $timeout;
  9035. $this->max_checked_feeds = $max_checked_feeds;
  9036. $this->content_type_sniffer_class = $content_type_sniffer_class;
  9037. }
  9038. public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
  9039. {
  9040. if ($this->is_feed($this->file))
  9041. {
  9042. return $this->file;
  9043. }
  9044. if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  9045. {
  9046. $sniffer = new $this->content_type_sniffer_class($this->file);
  9047. if ($sniffer->get_type() !== 'text/html')
  9048. {
  9049. return null;
  9050. }
  9051. }
  9052. if ($type & ~SIMPLEPIE_LOCATOR_NONE)
  9053. {
  9054. $this->get_base();
  9055. }
  9056. if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
  9057. {
  9058. return $working[0];
  9059. }
  9060. if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
  9061. {
  9062. if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
  9063. {
  9064. return $working;
  9065. }
  9066. if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
  9067. {
  9068. return $working;
  9069. }
  9070. if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
  9071. {
  9072. return $working;
  9073. }
  9074. if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
  9075. {
  9076. return $working;
  9077. }
  9078. }
  9079. return null;
  9080. }
  9081. public function is_feed(&$file)
  9082. {
  9083. if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  9084. {
  9085. $sniffer = new $this->content_type_sniffer_class($file);
  9086. $sniffed = $sniffer->get_type();
  9087. if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
  9088. {
  9089. return true;
  9090. }
  9091. else
  9092. {
  9093. return false;
  9094. }
  9095. }
  9096. elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
  9097. {
  9098. return true;
  9099. }
  9100. else
  9101. {
  9102. return false;
  9103. }
  9104. }
  9105. public function get_base()
  9106. {
  9107. $this->http_base = $this->file->url;
  9108. $this->base = $this->http_base;
  9109. $elements = SimplePie_Misc::get_element('base', $this->file->body);
  9110. foreach ($elements as $element)
  9111. {
  9112. if ($element['attribs']['href']['data'] !== '')
  9113. {
  9114. $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
  9115. $this->base_location = $element['offset'];
  9116. break;
  9117. }
  9118. }
  9119. }
  9120. public function autodiscovery()
  9121. {
  9122. $links = array_merge(SimplePie_Misc::get_element('link', $this->file->body), SimplePie_Misc::get_element('a', $this->file->body), SimplePie_Misc::get_element('area', $this->file->body));
  9123. $done = array();
  9124. $feeds = array();
  9125. foreach ($links as $link)
  9126. {
  9127. if ($this->checked_feeds === $this->max_checked_feeds)
  9128. {
  9129. break;
  9130. }
  9131. if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
  9132. {
  9133. $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
  9134. if ($this->base_location < $link['offset'])
  9135. {
  9136. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  9137. }
  9138. else
  9139. {
  9140. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  9141. }
  9142. if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $rel) && !in_array('stylesheet', $rel) && !empty($link['attribs']['type']['data']) && in_array(strtolower(SimplePie_Misc::parse_mime($link['attribs']['type']['data'])), array('application/rss+xml', 'application/atom+xml'))) && !isset($feeds[$href]))
  9143. {
  9144. $this->checked_feeds++;
  9145. $headers = array(
  9146. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  9147. );
  9148. $feed = new $this->file_class($href, $this->timeout, 5, $headers, $this->useragent);
  9149. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  9150. {
  9151. $feeds[$href] = $feed;
  9152. }
  9153. }
  9154. $done[] = $href;
  9155. }
  9156. }
  9157. if (!empty($feeds))
  9158. {
  9159. return array_values($feeds);
  9160. }
  9161. else
  9162. {
  9163. return null;
  9164. }
  9165. }
  9166. public function get_links()
  9167. {
  9168. $links = SimplePie_Misc::get_element('a', $this->file->body);
  9169. foreach ($links as $link)
  9170. {
  9171. if (isset($link['attribs']['href']['data']))
  9172. {
  9173. $href = trim($link['attribs']['href']['data']);
  9174. $parsed = SimplePie_Misc::parse_url($href);
  9175. if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
  9176. {
  9177. if ($this->base_location < $link['offset'])
  9178. {
  9179. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  9180. }
  9181. else
  9182. {
  9183. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  9184. }
  9185. $current = SimplePie_Misc::parse_url($this->file->url);
  9186. if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
  9187. {
  9188. $this->local[] = $href;
  9189. }
  9190. else
  9191. {
  9192. $this->elsewhere[] = $href;
  9193. }
  9194. }
  9195. }
  9196. }
  9197. $this->local = array_unique($this->local);
  9198. $this->elsewhere = array_unique($this->elsewhere);
  9199. if (!empty($this->local) || !empty($this->elsewhere))
  9200. {
  9201. return true;
  9202. }
  9203. return null;
  9204. }
  9205. public function extension(&$array)
  9206. {
  9207. foreach ($array as $key => $value)
  9208. {
  9209. if ($this->checked_feeds === $this->max_checked_feeds)
  9210. {
  9211. break;
  9212. }
  9213. if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
  9214. {
  9215. $this->checked_feeds++;
  9216. $headers = array(
  9217. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  9218. );
  9219. $feed = new $this->file_class($value, $this->timeout, 5, $headers, $this->useragent);
  9220. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  9221. {
  9222. return $feed;
  9223. }
  9224. else
  9225. {
  9226. unset($array[$key]);
  9227. }
  9228. }
  9229. }
  9230. return null;
  9231. }
  9232. public function body(&$array)
  9233. {
  9234. foreach ($array as $key => $value)
  9235. {
  9236. if ($this->checked_feeds === $this->max_checked_feeds)
  9237. {
  9238. break;
  9239. }
  9240. if (preg_match('/(rss|rdf|atom|xml)/i', $value))
  9241. {
  9242. $this->checked_feeds++;
  9243. $headers = array(
  9244. 'Accept' => 'application/atom+xml, application/rss+xml, application/rdf+xml;q=0.9, application/xml;q=0.8, text/xml;q=0.8, text/html;q=0.7, unknown/unknown;q=0.1, application/unknown;q=0.1, */*;q=0.1',
  9245. );
  9246. $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
  9247. if ($feed->success && ($feed->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($feed->status_code === 200 || $feed->status_code > 206 && $feed->status_code < 300)) && $this->is_feed($feed))
  9248. {
  9249. return $feed;
  9250. }
  9251. else
  9252. {
  9253. unset($array[$key]);
  9254. }
  9255. }
  9256. }
  9257. return null;
  9258. }
  9259. }
  9260. class SimplePie_Misc
  9261. {
  9262. public static function time_hms($seconds)
  9263. {
  9264. $time = '';
  9265. $hours = floor($seconds / 3600);
  9266. $remainder = $seconds % 3600;
  9267. if ($hours > 0)
  9268. {
  9269. $time .= $hours.':';
  9270. }
  9271. $minutes = floor($remainder / 60);
  9272. $seconds = $remainder % 60;
  9273. if ($minutes < 10 && $hours > 0)
  9274. {
  9275. $minutes = '0' . $minutes;
  9276. }
  9277. if ($seconds < 10)
  9278. {
  9279. $seconds = '0' . $seconds;
  9280. }
  9281. $time .= $minutes.':';
  9282. $time .= $seconds;
  9283. return $time;
  9284. }
  9285. public static function absolutize_url($relative, $base)
  9286. {
  9287. $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
  9288. return $iri->get_iri();
  9289. }
  9290. public static function remove_dot_segments($input)
  9291. {
  9292. $output = '';
  9293. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  9294. {
  9295. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  9296. if (strpos($input, '../') === 0)
  9297. {
  9298. $input = substr($input, 3);
  9299. }
  9300. elseif (strpos($input, './') === 0)
  9301. {
  9302. $input = substr($input, 2);
  9303. }
  9304. // B: if the input buffer begins with a prefix of "/./" or "/.", where "." is a complete path segment, then replace that prefix with "/" in the input buffer; otherwise,
  9305. elseif (strpos($input, '/./') === 0)
  9306. {
  9307. $input = substr_replace($input, '/', 0, 3);
  9308. }
  9309. elseif ($input === '/.')
  9310. {
  9311. $input = '/';
  9312. }
  9313. // C: if the input buffer begins with a prefix of "/../" or "/..", where ".." is a complete path segment, then replace that prefix with "/" in the input buffer and remove the last segment and its preceding "/" (if any) from the output buffer; otherwise,
  9314. elseif (strpos($input, '/../') === 0)
  9315. {
  9316. $input = substr_replace($input, '/', 0, 4);
  9317. $output = substr_replace($output, '', strrpos($output, '/'));
  9318. }
  9319. elseif ($input === '/..')
  9320. {
  9321. $input = '/';
  9322. $output = substr_replace($output, '', strrpos($output, '/'));
  9323. }
  9324. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  9325. elseif ($input === '.' || $input === '..')
  9326. {
  9327. $input = '';
  9328. }
  9329. // E: move the first path segment in the input buffer to the end of the output buffer, including the initial "/" character (if any) and any subsequent characters up to, but not including, the next "/" character or the end of the input buffer
  9330. elseif (($pos = strpos($input, '/', 1)) !== false)
  9331. {
  9332. $output .= substr($input, 0, $pos);
  9333. $input = substr_replace($input, '', 0, $pos);
  9334. }
  9335. else
  9336. {
  9337. $output .= $input;
  9338. $input = '';
  9339. }
  9340. }
  9341. return $output . $input;
  9342. }
  9343. public static function get_element($realname, $string)
  9344. {
  9345. $return = array();
  9346. $name = preg_quote($realname, '/');
  9347. if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
  9348. {
  9349. for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
  9350. {
  9351. $return[$i]['tag'] = $realname;
  9352. $return[$i]['full'] = $matches[$i][0][0];
  9353. $return[$i]['offset'] = $matches[$i][0][1];
  9354. if (strlen($matches[$i][3][0]) <= 2)
  9355. {
  9356. $return[$i]['self_closing'] = true;
  9357. }
  9358. else
  9359. {
  9360. $return[$i]['self_closing'] = false;
  9361. $return[$i]['content'] = $matches[$i][4][0];
  9362. }
  9363. $return[$i]['attribs'] = array();
  9364. if (isset($matches[$i][2][0]) && preg_match_all('/[\x09\x0A\x0B\x0C\x0D\x20]+([^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3D\x3E]*)(?:[\x09\x0A\x0B\x0C\x0D\x20]*=[\x09\x0A\x0B\x0C\x0D\x20]*(?:"([^"]*)"|\'([^\']*)\'|([^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?/', ' ' . $matches[$i][2][0] . ' ', $attribs, PREG_SET_ORDER))
  9365. {
  9366. for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
  9367. {
  9368. if (count($attribs[$j]) === 2)
  9369. {
  9370. $attribs[$j][2] = $attribs[$j][1];
  9371. }
  9372. $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
  9373. }
  9374. }
  9375. }
  9376. }
  9377. return $return;
  9378. }
  9379. public static function element_implode($element)
  9380. {
  9381. $full = "<$element[tag]";
  9382. foreach ($element['attribs'] as $key => $value)
  9383. {
  9384. $key = strtolower($key);
  9385. $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
  9386. }
  9387. if ($element['self_closing'])
  9388. {
  9389. $full .= ' />';
  9390. }
  9391. else
  9392. {
  9393. $full .= ">$element[content]</$element[tag]>";
  9394. }
  9395. return $full;
  9396. }
  9397. public static function error($message, $level, $file, $line)
  9398. {
  9399. if ((ini_get('error_reporting') & $level) > 0)
  9400. {
  9401. switch ($level)
  9402. {
  9403. case E_USER_ERROR:
  9404. $note = 'PHP Error';
  9405. break;
  9406. case E_USER_WARNING:
  9407. $note = 'PHP Warning';
  9408. break;
  9409. case E_USER_NOTICE:
  9410. $note = 'PHP Notice';
  9411. break;
  9412. default:
  9413. $note = 'Unknown Error';
  9414. break;
  9415. }
  9416. $log_error = true;
  9417. if (!function_exists('error_log'))
  9418. {
  9419. $log_error = false;
  9420. }
  9421. $log_file = @ini_get('error_log');
  9422. if (!empty($log_file) && ('syslog' !== $log_file) && !@is_writable($log_file))
  9423. {
  9424. $log_error = false;
  9425. }
  9426. if ($log_error)
  9427. {
  9428. @error_log("$note: $message in $file on line $line", 0);
  9429. }
  9430. }
  9431. return $message;
  9432. }
  9433. public static function fix_protocol($url, $http = 1)
  9434. {
  9435. $url = SimplePie_Misc::normalize_url($url);
  9436. $parsed = SimplePie_Misc::parse_url($url);
  9437. if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
  9438. {
  9439. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
  9440. }
  9441. if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
  9442. {
  9443. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
  9444. }
  9445. if ($http === 2 && $parsed['scheme'] !== '')
  9446. {
  9447. return "feed:$url";
  9448. }
  9449. elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
  9450. {
  9451. return substr_replace($url, 'podcast', 0, 4);
  9452. }
  9453. elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
  9454. {
  9455. return substr_replace($url, 'itpc', 0, 4);
  9456. }
  9457. else
  9458. {
  9459. return $url;
  9460. }
  9461. }
  9462. public static function parse_url($url)
  9463. {
  9464. $iri = new SimplePie_IRI($url);
  9465. return array(
  9466. 'scheme' => (string) $iri->get_scheme(),
  9467. 'authority' => (string) $iri->get_authority(),
  9468. 'path' => (string) $iri->get_path(),
  9469. 'query' => (string) $iri->get_query(),
  9470. 'fragment' => (string) $iri->get_fragment()
  9471. );
  9472. }
  9473. public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
  9474. {
  9475. $iri = new SimplePie_IRI('');
  9476. $iri->set_scheme($scheme);
  9477. $iri->set_authority($authority);
  9478. $iri->set_path($path);
  9479. $iri->set_query($query);
  9480. $iri->set_fragment($fragment);
  9481. return $iri->get_iri();
  9482. }
  9483. public static function normalize_url($url)
  9484. {
  9485. $iri = new SimplePie_IRI($url);
  9486. return $iri->get_iri();
  9487. }
  9488. public static function percent_encoding_normalization($match)
  9489. {
  9490. $integer = hexdec($match[1]);
  9491. if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
  9492. {
  9493. return chr($integer);
  9494. }
  9495. else
  9496. {
  9497. return strtoupper($match[0]);
  9498. }
  9499. }
  9500. /**
  9501. * Converts a Windows-1252 encoded string to a UTF-8 encoded string
  9502. *
  9503. * @static
  9504. * @param string $string Windows-1252 encoded string
  9505. * @return string UTF-8 encoded string
  9506. */
  9507. public static function windows_1252_to_utf8($string)
  9508. {
  9509. static $convert_table = array("\x80" => "\xE2\x82\xAC", "\x81" => "\xEF\xBF\xBD", "\x82" => "\xE2\x80\x9A", "\x83" => "\xC6\x92", "\x84" => "\xE2\x80\x9E", "\x85" => "\xE2\x80\xA6", "\x86" => "\xE2\x80\xA0", "\x87" => "\xE2\x80\xA1", "\x88" => "\xCB\x86", "\x89" => "\xE2\x80\xB0", "\x8A" => "\xC5\xA0", "\x8B" => "\xE2\x80\xB9", "\x8C" => "\xC5\x92", "\x8D" => "\xEF\xBF\xBD", "\x8E" => "\xC5\xBD", "\x8F" => "\xEF\xBF\xBD", "\x90" => "\xEF\xBF\xBD", "\x91" => "\xE2\x80\x98", "\x92" => "\xE2\x80\x99", "\x93" => "\xE2\x80\x9C", "\x94" => "\xE2\x80\x9D", "\x95" => "\xE2\x80\xA2", "\x96" => "\xE2\x80\x93", "\x97" => "\xE2\x80\x94", "\x98" => "\xCB\x9C", "\x99" => "\xE2\x84\xA2", "\x9A" => "\xC5\xA1", "\x9B" => "\xE2\x80\xBA", "\x9C" => "\xC5\x93", "\x9D" => "\xEF\xBF\xBD", "\x9E" => "\xC5\xBE", "\x9F" => "\xC5\xB8", "\xA0" => "\xC2\xA0", "\xA1" => "\xC2\xA1", "\xA2" => "\xC2\xA2", "\xA3" => "\xC2\xA3", "\xA4" => "\xC2\xA4", "\xA5" => "\xC2\xA5", "\xA6" => "\xC2\xA6", "\xA7" => "\xC2\xA7", "\xA8" => "\xC2\xA8", "\xA9" => "\xC2\xA9", "\xAA" => "\xC2\xAA", "\xAB" => "\xC2\xAB", "\xAC" => "\xC2\xAC", "\xAD" => "\xC2\xAD", "\xAE" => "\xC2\xAE", "\xAF" => "\xC2\xAF", "\xB0" => "\xC2\xB0", "\xB1" => "\xC2\xB1", "\xB2" => "\xC2\xB2", "\xB3" => "\xC2\xB3", "\xB4" => "\xC2\xB4", "\xB5" => "\xC2\xB5", "\xB6" => "\xC2\xB6", "\xB7" => "\xC2\xB7", "\xB8" => "\xC2\xB8", "\xB9" => "\xC2\xB9", "\xBA" => "\xC2\xBA", "\xBB" => "\xC2\xBB", "\xBC" => "\xC2\xBC", "\xBD" => "\xC2\xBD", "\xBE" => "\xC2\xBE", "\xBF" => "\xC2\xBF", "\xC0" => "\xC3\x80", "\xC1" => "\xC3\x81", "\xC2" => "\xC3\x82", "\xC3" => "\xC3\x83", "\xC4" => "\xC3\x84", "\xC5" => "\xC3\x85", "\xC6" => "\xC3\x86", "\xC7" => "\xC3\x87", "\xC8" => "\xC3\x88", "\xC9" => "\xC3\x89", "\xCA" => "\xC3\x8A", "\xCB" => "\xC3\x8B", "\xCC" => "\xC3\x8C", "\xCD" => "\xC3\x8D", "\xCE" => "\xC3\x8E", "\xCF" => "\xC3\x8F", "\xD0" => "\xC3\x90", "\xD1" => "\xC3\x91", "\xD2" => "\xC3\x92", "\xD3" => "\xC3\x93", "\xD4" => "\xC3\x94", "\xD5" => "\xC3\x95", "\xD6" => "\xC3\x96", "\xD7" => "\xC3\x97", "\xD8" => "\xC3\x98", "\xD9" => "\xC3\x99", "\xDA" => "\xC3\x9A", "\xDB" => "\xC3\x9B", "\xDC" => "\xC3\x9C", "\xDD" => "\xC3\x9D", "\xDE" => "\xC3\x9E", "\xDF" => "\xC3\x9F", "\xE0" => "\xC3\xA0", "\xE1" => "\xC3\xA1", "\xE2" => "\xC3\xA2", "\xE3" => "\xC3\xA3", "\xE4" => "\xC3\xA4", "\xE5" => "\xC3\xA5", "\xE6" => "\xC3\xA6", "\xE7" => "\xC3\xA7", "\xE8" => "\xC3\xA8", "\xE9" => "\xC3\xA9", "\xEA" => "\xC3\xAA", "\xEB" => "\xC3\xAB", "\xEC" => "\xC3\xAC", "\xED" => "\xC3\xAD", "\xEE" => "\xC3\xAE", "\xEF" => "\xC3\xAF", "\xF0" => "\xC3\xB0", "\xF1" => "\xC3\xB1", "\xF2" => "\xC3\xB2", "\xF3" => "\xC3\xB3", "\xF4" => "\xC3\xB4", "\xF5" => "\xC3\xB5", "\xF6" => "\xC3\xB6", "\xF7" => "\xC3\xB7", "\xF8" => "\xC3\xB8", "\xF9" => "\xC3\xB9", "\xFA" => "\xC3\xBA", "\xFB" => "\xC3\xBB", "\xFC" => "\xC3\xBC", "\xFD" => "\xC3\xBD", "\xFE" => "\xC3\xBE", "\xFF" => "\xC3\xBF");
  9510. return strtr($string, $convert_table);
  9511. }
  9512. /**
  9513. * Change a string from one encoding to another
  9514. *
  9515. * @param string $data Raw data in $input encoding
  9516. * @param string $input Encoding of $data
  9517. * @param string $output Encoding you want
  9518. * @return string|boolean False if we can't convert it
  9519. */
  9520. public static function change_encoding($data, $input, $output)
  9521. {
  9522. $input = SimplePie_Misc::encoding($input);
  9523. $output = SimplePie_Misc::encoding($output);
  9524. // We fail to fail on non US-ASCII bytes
  9525. if ($input === 'US-ASCII')
  9526. {
  9527. static $non_ascii_octects = '';
  9528. if (!$non_ascii_octects)
  9529. {
  9530. for ($i = 0x80; $i <= 0xFF; $i++)
  9531. {
  9532. $non_ascii_octects .= chr($i);
  9533. }
  9534. }
  9535. $data = substr($data, 0, strcspn($data, $non_ascii_octects));
  9536. }
  9537. // This is first, as behaviour of this is completely predictable
  9538. if ($input === 'windows-1252' && $output === 'UTF-8')
  9539. {
  9540. return SimplePie_Misc::windows_1252_to_utf8($data);
  9541. }
  9542. // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
  9543. elseif (function_exists('mb_convert_encoding') && ($return = SimplePie_Misc::change_encoding_mbstring($data, $input, $output)))
  9544. {
  9545. return $return;
  9546. }
  9547. // This is last, as behaviour of this varies with OS userland and PHP version
  9548. elseif (function_exists('iconv') && ($return = SimplePie_Misc::change_encoding_iconv($data, $input, $output)))
  9549. {
  9550. return $return;
  9551. }
  9552. // If we can't do anything, just fail
  9553. else
  9554. {
  9555. return false;
  9556. }
  9557. }
  9558. protected static function change_encoding_mbstring($data, $input, $output)
  9559. {
  9560. if ($input === 'windows-949')
  9561. {
  9562. $input = 'EUC-KR';
  9563. }
  9564. if ($output === 'windows-949')
  9565. {
  9566. $output = 'EUC-KR';
  9567. }
  9568. // Check that the encoding is supported
  9569. if (@mb_convert_encoding("\x80", 'UTF-16BE', $input) === "\x00\x80")
  9570. {
  9571. return false;
  9572. }
  9573. if (!in_array($input, mb_list_encodings()))
  9574. {
  9575. return false;
  9576. }
  9577. // Let's do some conversion
  9578. if ($return = @mb_convert_encoding($data, $output, $input))
  9579. {
  9580. return $return;
  9581. }
  9582. return false;
  9583. }
  9584. protected static function change_encoding_iconv($data, $input, $output)
  9585. {
  9586. return @iconv($input, $output, $data);
  9587. }
  9588. /**
  9589. * Normalize an encoding name
  9590. *
  9591. * This is automatically generated by create.php
  9592. *
  9593. * To generate it, run `php create.php` on the command line, and copy the
  9594. * output to replace this function.
  9595. *
  9596. * @param string $charset Character set to standardise
  9597. * @return string Standardised name
  9598. */
  9599. public static function encoding($charset)
  9600. {
  9601. // Normalization from UTS #22
  9602. switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
  9603. {
  9604. case 'adobestandardencoding':
  9605. case 'csadobestandardencoding':
  9606. return 'Adobe-Standard-Encoding';
  9607. case 'adobesymbolencoding':
  9608. case 'cshppsmath':
  9609. return 'Adobe-Symbol-Encoding';
  9610. case 'ami1251':
  9611. case 'amiga1251':
  9612. return 'Amiga-1251';
  9613. case 'ansix31101983':
  9614. case 'csat5001983':
  9615. case 'csiso99naplps':
  9616. case 'isoir99':
  9617. case 'naplps':
  9618. return 'ANSI_X3.110-1983';
  9619. case 'arabic7':
  9620. case 'asmo449':
  9621. case 'csiso89asmo449':
  9622. case 'iso9036':
  9623. case 'isoir89':
  9624. return 'ASMO_449';
  9625. case 'big5':
  9626. case 'csbig5':
  9627. return 'Big5';
  9628. case 'big5hkscs':
  9629. return 'Big5-HKSCS';
  9630. case 'bocu1':
  9631. case 'csbocu1':
  9632. return 'BOCU-1';
  9633. case 'brf':
  9634. case 'csbrf':
  9635. return 'BRF';
  9636. case 'bs4730':
  9637. case 'csiso4unitedkingdom':
  9638. case 'gb':
  9639. case 'iso646gb':
  9640. case 'isoir4':
  9641. case 'uk':
  9642. return 'BS_4730';
  9643. case 'bsviewdata':
  9644. case 'csiso47bsviewdata':
  9645. case 'isoir47':
  9646. return 'BS_viewdata';
  9647. case 'cesu8':
  9648. case 'cscesu8':
  9649. return 'CESU-8';
  9650. case 'ca':
  9651. case 'csa71':
  9652. case 'csaz243419851':
  9653. case 'csiso121canadian1':
  9654. case 'iso646ca':
  9655. case 'isoir121':
  9656. return 'CSA_Z243.4-1985-1';
  9657. case 'csa72':
  9658. case 'csaz243419852':
  9659. case 'csiso122canadian2':
  9660. case 'iso646ca2':
  9661. case 'isoir122':
  9662. return 'CSA_Z243.4-1985-2';
  9663. case 'csaz24341985gr':
  9664. case 'csiso123csaz24341985gr':
  9665. case 'isoir123':
  9666. return 'CSA_Z243.4-1985-gr';
  9667. case 'csiso139csn369103':
  9668. case 'csn369103':
  9669. case 'isoir139':
  9670. return 'CSN_369103';
  9671. case 'csdecmcs':
  9672. case 'dec':
  9673. case 'decmcs':
  9674. return 'DEC-MCS';
  9675. case 'csiso21german':
  9676. case 'de':
  9677. case 'din66003':
  9678. case 'iso646de':
  9679. case 'isoir21':
  9680. return 'DIN_66003';
  9681. case 'csdkus':
  9682. case 'dkus':
  9683. return 'dk-us';
  9684. case 'csiso646danish':
  9685. case 'dk':
  9686. case 'ds2089':
  9687. case 'iso646dk':
  9688. return 'DS_2089';
  9689. case 'csibmebcdicatde':
  9690. case 'ebcdicatde':
  9691. return 'EBCDIC-AT-DE';
  9692. case 'csebcdicatdea':
  9693. case 'ebcdicatdea':
  9694. return 'EBCDIC-AT-DE-A';
  9695. case 'csebcdiccafr':
  9696. case 'ebcdiccafr':
  9697. return 'EBCDIC-CA-FR';
  9698. case 'csebcdicdkno':
  9699. case 'ebcdicdkno':
  9700. return 'EBCDIC-DK-NO';
  9701. case 'csebcdicdknoa':
  9702. case 'ebcdicdknoa':
  9703. return 'EBCDIC-DK-NO-A';
  9704. case 'csebcdices':
  9705. case 'ebcdices':
  9706. return 'EBCDIC-ES';
  9707. case 'csebcdicesa':
  9708. case 'ebcdicesa':
  9709. return 'EBCDIC-ES-A';
  9710. case 'csebcdicess':
  9711. case 'ebcdicess':
  9712. return 'EBCDIC-ES-S';
  9713. case 'csebcdicfise':
  9714. case 'ebcdicfise':
  9715. return 'EBCDIC-FI-SE';
  9716. case 'csebcdicfisea':
  9717. case 'ebcdicfisea':
  9718. return 'EBCDIC-FI-SE-A';
  9719. case 'csebcdicfr':
  9720. case 'ebcdicfr':
  9721. return 'EBCDIC-FR';
  9722. case 'csebcdicit':
  9723. case 'ebcdicit':
  9724. return 'EBCDIC-IT';
  9725. case 'csebcdicpt':
  9726. case 'ebcdicpt':
  9727. return 'EBCDIC-PT';
  9728. case 'csebcdicuk':
  9729. case 'ebcdicuk':
  9730. return 'EBCDIC-UK';
  9731. case 'csebcdicus':
  9732. case 'ebcdicus':
  9733. return 'EBCDIC-US';
  9734. case 'csiso111ecmacyrillic':
  9735. case 'ecmacyrillic':
  9736. case 'isoir111':
  9737. case 'koi8e':
  9738. return 'ECMA-cyrillic';
  9739. case 'csiso17spanish':
  9740. case 'es':
  9741. case 'iso646es':
  9742. case 'isoir17':
  9743. return 'ES';
  9744. case 'csiso85spanish2':
  9745. case 'es2':
  9746. case 'iso646es2':
  9747. case 'isoir85':
  9748. return 'ES2';
  9749. case 'cseucpkdfmtjapanese':
  9750. case 'eucjp':
  9751. case 'extendedunixcodepackedformatforjapanese':
  9752. return 'EUC-JP';
  9753. case 'cseucfixwidjapanese':
  9754. case 'extendedunixcodefixedwidthforjapanese':
  9755. return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
  9756. case 'gb18030':
  9757. return 'GB18030';
  9758. case 'chinese':
  9759. case 'cp936':
  9760. case 'csgb2312':
  9761. case 'csiso58gb231280':
  9762. case 'gb2312':
  9763. case 'gb231280':
  9764. case 'gbk':
  9765. case 'isoir58':
  9766. case 'ms936':
  9767. case 'windows936':
  9768. return 'GBK';
  9769. case 'cn':
  9770. case 'csiso57gb1988':
  9771. case 'gb198880':
  9772. case 'iso646cn':
  9773. case 'isoir57':
  9774. return 'GB_1988-80';
  9775. case 'csiso153gost1976874':
  9776. case 'gost1976874':
  9777. case 'isoir153':
  9778. case 'stsev35888':
  9779. return 'GOST_19768-74';
  9780. case 'csiso150':
  9781. case 'csiso150greekccitt':
  9782. case 'greekccitt':
  9783. case 'isoir150':
  9784. return 'greek-ccitt';
  9785. case 'csiso88greek7':
  9786. case 'greek7':
  9787. case 'isoir88':
  9788. return 'greek7';
  9789. case 'csiso18greek7old':
  9790. case 'greek7old':
  9791. case 'isoir18':
  9792. return 'greek7-old';
  9793. case 'cshpdesktop':
  9794. case 'hpdesktop':
  9795. return 'HP-DeskTop';
  9796. case 'cshplegal':
  9797. case 'hplegal':
  9798. return 'HP-Legal';
  9799. case 'cshpmath8':
  9800. case 'hpmath8':
  9801. return 'HP-Math8';
  9802. case 'cshppifont':
  9803. case 'hppifont':
  9804. return 'HP-Pi-font';
  9805. case 'cshproman8':
  9806. case 'hproman8':
  9807. case 'r8':
  9808. case 'roman8':
  9809. return 'hp-roman8';
  9810. case 'hzgb2312':
  9811. return 'HZ-GB-2312';
  9812. case 'csibmsymbols':
  9813. case 'ibmsymbols':
  9814. return 'IBM-Symbols';
  9815. case 'csibmthai':
  9816. case 'ibmthai':
  9817. return 'IBM-Thai';
  9818. case 'cp37':
  9819. case 'csibm37':
  9820. case 'ebcdiccpca':
  9821. case 'ebcdiccpnl':
  9822. case 'ebcdiccpus':
  9823. case 'ebcdiccpwt':
  9824. case 'ibm37':
  9825. return 'IBM037';
  9826. case 'cp38':
  9827. case 'csibm38':
  9828. case 'ebcdicint':
  9829. case 'ibm38':
  9830. return 'IBM038';
  9831. case 'cp273':
  9832. case 'csibm273':
  9833. case 'ibm273':
  9834. return 'IBM273';
  9835. case 'cp274':
  9836. case 'csibm274':
  9837. case 'ebcdicbe':
  9838. case 'ibm274':
  9839. return 'IBM274';
  9840. case 'cp275':
  9841. case 'csibm275':
  9842. case 'ebcdicbr':
  9843. case 'ibm275':
  9844. return 'IBM275';
  9845. case 'csibm277':
  9846. case 'ebcdiccpdk':
  9847. case 'ebcdiccpno':
  9848. case 'ibm277':
  9849. return 'IBM277';
  9850. case 'cp278':
  9851. case 'csibm278':
  9852. case 'ebcdiccpfi':
  9853. case 'ebcdiccpse':
  9854. case 'ibm278':
  9855. return 'IBM278';
  9856. case 'cp280':
  9857. case 'csibm280':
  9858. case 'ebcdiccpit':
  9859. case 'ibm280':
  9860. return 'IBM280';
  9861. case 'cp281':
  9862. case 'csibm281':
  9863. case 'ebcdicjpe':
  9864. case 'ibm281':
  9865. return 'IBM281';
  9866. case 'cp284':
  9867. case 'csibm284':
  9868. case 'ebcdiccpes':
  9869. case 'ibm284':
  9870. return 'IBM284';
  9871. case 'cp285':
  9872. case 'csibm285':
  9873. case 'ebcdiccpgb':
  9874. case 'ibm285':
  9875. return 'IBM285';
  9876. case 'cp290':
  9877. case 'csibm290':
  9878. case 'ebcdicjpkana':
  9879. case 'ibm290':
  9880. return 'IBM290';
  9881. case 'cp297':
  9882. case 'csibm297':
  9883. case 'ebcdiccpfr':
  9884. case 'ibm297':
  9885. return 'IBM297';
  9886. case 'cp420':
  9887. case 'csibm420':
  9888. case 'ebcdiccpar1':
  9889. case 'ibm420':
  9890. return 'IBM420';
  9891. case 'cp423':
  9892. case 'csibm423':
  9893. case 'ebcdiccpgr':
  9894. case 'ibm423':
  9895. return 'IBM423';
  9896. case 'cp424':
  9897. case 'csibm424':
  9898. case 'ebcdiccphe':
  9899. case 'ibm424':
  9900. return 'IBM424';
  9901. case '437':
  9902. case 'cp437':
  9903. case 'cspc8codepage437':
  9904. case 'ibm437':
  9905. return 'IBM437';
  9906. case 'cp500':
  9907. case 'csibm500':
  9908. case 'ebcdiccpbe':
  9909. case 'ebcdiccpch':
  9910. case 'ibm500':
  9911. return 'IBM500';
  9912. case 'cp775':
  9913. case 'cspc775baltic':
  9914. case 'ibm775':
  9915. return 'IBM775';
  9916. case '850':
  9917. case 'cp850':
  9918. case 'cspc850multilingual':
  9919. case 'ibm850':
  9920. return 'IBM850';
  9921. case '851':
  9922. case 'cp851':
  9923. case 'csibm851':
  9924. case 'ibm851':
  9925. return 'IBM851';
  9926. case '852':
  9927. case 'cp852':
  9928. case 'cspcp852':
  9929. case 'ibm852':
  9930. return 'IBM852';
  9931. case '855':
  9932. case 'cp855':
  9933. case 'csibm855':
  9934. case 'ibm855':
  9935. return 'IBM855';
  9936. case '857':
  9937. case 'cp857':
  9938. case 'csibm857':
  9939. case 'ibm857':
  9940. return 'IBM857';
  9941. case 'ccsid858':
  9942. case 'cp858':
  9943. case 'ibm858':
  9944. case 'pcmultilingual850euro':
  9945. return 'IBM00858';
  9946. case '860':
  9947. case 'cp860':
  9948. case 'csibm860':
  9949. case 'ibm860':
  9950. return 'IBM860';
  9951. case '861':
  9952. case 'cp861':
  9953. case 'cpis':
  9954. case 'csibm861':
  9955. case 'ibm861':
  9956. return 'IBM861';
  9957. case '862':
  9958. case 'cp862':
  9959. case 'cspc862latinhebrew':
  9960. case 'ibm862':
  9961. return 'IBM862';
  9962. case '863':
  9963. case 'cp863':
  9964. case 'csibm863':
  9965. case 'ibm863':
  9966. return 'IBM863';
  9967. case 'cp864':
  9968. case 'csibm864':
  9969. case 'ibm864':
  9970. return 'IBM864';
  9971. case '865':
  9972. case 'cp865':
  9973. case 'csibm865':
  9974. case 'ibm865':
  9975. return 'IBM865';
  9976. case '866':
  9977. case 'cp866':
  9978. case 'csibm866':
  9979. case 'ibm866':
  9980. return 'IBM866';
  9981. case 'cp868':
  9982. case 'cpar':
  9983. case 'csibm868':
  9984. case 'ibm868':
  9985. return 'IBM868';
  9986. case '869':
  9987. case 'cp869':
  9988. case 'cpgr':
  9989. case 'csibm869':
  9990. case 'ibm869':
  9991. return 'IBM869';
  9992. case 'cp870':
  9993. case 'csibm870':
  9994. case 'ebcdiccproece':
  9995. case 'ebcdiccpyu':
  9996. case 'ibm870':
  9997. return 'IBM870';
  9998. case 'cp871':
  9999. case 'csibm871':
  10000. case 'ebcdiccpis':
  10001. case 'ibm871':
  10002. return 'IBM871';
  10003. case 'cp880':
  10004. case 'csibm880':
  10005. case 'ebcdiccyrillic':
  10006. case 'ibm880':
  10007. return 'IBM880';
  10008. case 'cp891':
  10009. case 'csibm891':
  10010. case 'ibm891':
  10011. return 'IBM891';
  10012. case 'cp903':
  10013. case 'csibm903':
  10014. case 'ibm903':
  10015. return 'IBM903';
  10016. case '904':
  10017. case 'cp904':
  10018. case 'csibbm904':
  10019. case 'ibm904':
  10020. return 'IBM904';
  10021. case 'cp905':
  10022. case 'csibm905':
  10023. case 'ebcdiccptr':
  10024. case 'ibm905':
  10025. return 'IBM905';
  10026. case 'cp918':
  10027. case 'csibm918':
  10028. case 'ebcdiccpar2':
  10029. case 'ibm918':
  10030. return 'IBM918';
  10031. case 'ccsid924':
  10032. case 'cp924':
  10033. case 'ebcdiclatin9euro':
  10034. case 'ibm924':
  10035. return 'IBM00924';
  10036. case 'cp1026':
  10037. case 'csibm1026':
  10038. case 'ibm1026':
  10039. return 'IBM1026';
  10040. case 'ibm1047':
  10041. return 'IBM1047';
  10042. case 'ccsid1140':
  10043. case 'cp1140':
  10044. case 'ebcdicus37euro':
  10045. case 'ibm1140':
  10046. return 'IBM01140';
  10047. case 'ccsid1141':
  10048. case 'cp1141':
  10049. case 'ebcdicde273euro':
  10050. case 'ibm1141':
  10051. return 'IBM01141';
  10052. case 'ccsid1142':
  10053. case 'cp1142':
  10054. case 'ebcdicdk277euro':
  10055. case 'ebcdicno277euro':
  10056. case 'ibm1142':
  10057. return 'IBM01142';
  10058. case 'ccsid1143':
  10059. case 'cp1143':
  10060. case 'ebcdicfi278euro':
  10061. case 'ebcdicse278euro':
  10062. case 'ibm1143':
  10063. return 'IBM01143';
  10064. case 'ccsid1144':
  10065. case 'cp1144':
  10066. case 'ebcdicit280euro':
  10067. case 'ibm1144':
  10068. return 'IBM01144';
  10069. case 'ccsid1145':
  10070. case 'cp1145':
  10071. case 'ebcdices284euro':
  10072. case 'ibm1145':
  10073. return 'IBM01145';
  10074. case 'ccsid1146':
  10075. case 'cp1146':
  10076. case 'ebcdicgb285euro':
  10077. case 'ibm1146':
  10078. return 'IBM01146';
  10079. case 'ccsid1147':
  10080. case 'cp1147':
  10081. case 'ebcdicfr297euro':
  10082. case 'ibm1147':
  10083. return 'IBM01147';
  10084. case 'ccsid1148':
  10085. case 'cp1148':
  10086. case 'ebcdicinternational500euro':
  10087. case 'ibm1148':
  10088. return 'IBM01148';
  10089. case 'ccsid1149':
  10090. case 'cp1149':
  10091. case 'ebcdicis871euro':
  10092. case 'ibm1149':
  10093. return 'IBM01149';
  10094. case 'csiso143iecp271':
  10095. case 'iecp271':
  10096. case 'isoir143':
  10097. return 'IEC_P27-1';
  10098. case 'csiso49inis':
  10099. case 'inis':
  10100. case 'isoir49':
  10101. return 'INIS';
  10102. case 'csiso50inis8':
  10103. case 'inis8':
  10104. case 'isoir50':
  10105. return 'INIS-8';
  10106. case 'csiso51iniscyrillic':
  10107. case 'iniscyrillic':
  10108. case 'isoir51':
  10109. return 'INIS-cyrillic';
  10110. case 'csinvariant':
  10111. case 'invariant':
  10112. return 'INVARIANT';
  10113. case 'iso2022cn':
  10114. return 'ISO-2022-CN';
  10115. case 'iso2022cnext':
  10116. return 'ISO-2022-CN-EXT';
  10117. case 'csiso2022jp':
  10118. case 'iso2022jp':
  10119. return 'ISO-2022-JP';
  10120. case 'csiso2022jp2':
  10121. case 'iso2022jp2':
  10122. return 'ISO-2022-JP-2';
  10123. case 'csiso2022kr':
  10124. case 'iso2022kr':
  10125. return 'ISO-2022-KR';
  10126. case 'cswindows30latin1':
  10127. case 'iso88591windows30latin1':
  10128. return 'ISO-8859-1-Windows-3.0-Latin-1';
  10129. case 'cswindows31latin1':
  10130. case 'iso88591windows31latin1':
  10131. return 'ISO-8859-1-Windows-3.1-Latin-1';
  10132. case 'csisolatin2':
  10133. case 'iso88592':
  10134. case 'iso885921987':
  10135. case 'isoir101':
  10136. case 'l2':
  10137. case 'latin2':
  10138. return 'ISO-8859-2';
  10139. case 'cswindows31latin2':
  10140. case 'iso88592windowslatin2':
  10141. return 'ISO-8859-2-Windows-Latin-2';
  10142. case 'csisolatin3':
  10143. case 'iso88593':
  10144. case 'iso885931988':
  10145. case 'isoir109':
  10146. case 'l3':
  10147. case 'latin3':
  10148. return 'ISO-8859-3';
  10149. case 'csisolatin4':
  10150. case 'iso88594':
  10151. case 'iso885941988':
  10152. case 'isoir110':
  10153. case 'l4':
  10154. case 'latin4':
  10155. return 'ISO-8859-4';
  10156. case 'csisolatincyrillic':
  10157. case 'cyrillic':
  10158. case 'iso88595':
  10159. case 'iso885951988':
  10160. case 'isoir144':
  10161. return 'ISO-8859-5';
  10162. case 'arabic':
  10163. case 'asmo708':
  10164. case 'csisolatinarabic':
  10165. case 'ecma114':
  10166. case 'iso88596':
  10167. case 'iso885961987':
  10168. case 'isoir127':
  10169. return 'ISO-8859-6';
  10170. case 'csiso88596e':
  10171. case 'iso88596e':
  10172. return 'ISO-8859-6-E';
  10173. case 'csiso88596i':
  10174. case 'iso88596i':
  10175. return 'ISO-8859-6-I';
  10176. case 'csisolatingreek':
  10177. case 'ecma118':
  10178. case 'elot928':
  10179. case 'greek':
  10180. case 'greek8':
  10181. case 'iso88597':
  10182. case 'iso885971987':
  10183. case 'isoir126':
  10184. return 'ISO-8859-7';
  10185. case 'csisolatinhebrew':
  10186. case 'hebrew':
  10187. case 'iso88598':
  10188. case 'iso885981988':
  10189. case 'isoir138':
  10190. return 'ISO-8859-8';
  10191. case 'csiso88598e':
  10192. case 'iso88598e':
  10193. return 'ISO-8859-8-E';
  10194. case 'csiso88598i':
  10195. case 'iso88598i':
  10196. return 'ISO-8859-8-I';
  10197. case 'cswindows31latin5':
  10198. case 'iso88599windowslatin5':
  10199. return 'ISO-8859-9-Windows-Latin-5';
  10200. case 'csisolatin6':
  10201. case 'iso885910':
  10202. case 'iso8859101992':
  10203. case 'isoir157':
  10204. case 'l6':
  10205. case 'latin6':
  10206. return 'ISO-8859-10';
  10207. case 'iso885913':
  10208. return 'ISO-8859-13';
  10209. case 'iso885914':
  10210. case 'iso8859141998':
  10211. case 'isoceltic':
  10212. case 'isoir199':
  10213. case 'l8':
  10214. case 'latin8':
  10215. return 'ISO-8859-14';
  10216. case 'iso885915':
  10217. case 'latin9':
  10218. return 'ISO-8859-15';
  10219. case 'iso885916':
  10220. case 'iso8859162001':
  10221. case 'isoir226':
  10222. case 'l10':
  10223. case 'latin10':
  10224. return 'ISO-8859-16';
  10225. case 'iso10646j1':
  10226. return 'ISO-10646-J-1';
  10227. case 'csunicode':
  10228. case 'iso10646ucs2':
  10229. return 'ISO-10646-UCS-2';
  10230. case 'csucs4':
  10231. case 'iso10646ucs4':
  10232. return 'ISO-10646-UCS-4';
  10233. case 'csunicodeascii':
  10234. case 'iso10646ucsbasic':
  10235. return 'ISO-10646-UCS-Basic';
  10236. case 'csunicodelatin1':
  10237. case 'iso10646':
  10238. case 'iso10646unicodelatin1':
  10239. return 'ISO-10646-Unicode-Latin1';
  10240. case 'csiso10646utf1':
  10241. case 'iso10646utf1':
  10242. return 'ISO-10646-UTF-1';
  10243. case 'csiso115481':
  10244. case 'iso115481':
  10245. case 'isotr115481':
  10246. return 'ISO-11548-1';
  10247. case 'csiso90':
  10248. case 'isoir90':
  10249. return 'iso-ir-90';
  10250. case 'csunicodeibm1261':
  10251. case 'isounicodeibm1261':
  10252. return 'ISO-Unicode-IBM-1261';
  10253. case 'csunicodeibm1264':
  10254. case 'isounicodeibm1264':
  10255. return 'ISO-Unicode-IBM-1264';
  10256. case 'csunicodeibm1265':
  10257. case 'isounicodeibm1265':
  10258. return 'ISO-Unicode-IBM-1265';
  10259. case 'csunicodeibm1268':
  10260. case 'isounicodeibm1268':
  10261. return 'ISO-Unicode-IBM-1268';
  10262. case 'csunicodeibm1276':
  10263. case 'isounicodeibm1276':
  10264. return 'ISO-Unicode-IBM-1276';
  10265. case 'csiso646basic1983':
  10266. case 'iso646basic1983':
  10267. case 'ref':
  10268. return 'ISO_646.basic:1983';
  10269. case 'csiso2intlrefversion':
  10270. case 'irv':
  10271. case 'iso646irv1983':
  10272. case 'isoir2':
  10273. return 'ISO_646.irv:1983';
  10274. case 'csiso2033':
  10275. case 'e13b':
  10276. case 'iso20331983':
  10277. case 'isoir98':
  10278. return 'ISO_2033-1983';
  10279. case 'csiso5427cyrillic':
  10280. case 'iso5427':
  10281. case 'isoir37':
  10282. return 'ISO_5427';
  10283. case 'iso5427cyrillic1981':
  10284. case 'iso54271981':
  10285. case 'isoir54':
  10286. return 'ISO_5427:1981';
  10287. case 'csiso5428greek':
  10288. case 'iso54281980':
  10289. case 'isoir55':
  10290. return 'ISO_5428:1980';
  10291. case 'csiso6937add':
  10292. case 'iso6937225':
  10293. case 'isoir152':
  10294. return 'ISO_6937-2-25';
  10295. case 'csisotextcomm':
  10296. case 'iso69372add':
  10297. case 'isoir142':
  10298. return 'ISO_6937-2-add';
  10299. case 'csiso8859supp':
  10300. case 'iso8859supp':
  10301. case 'isoir154':
  10302. case 'latin125':
  10303. return 'ISO_8859-supp';
  10304. case 'csiso10367box':
  10305. case 'iso10367box':
  10306. case 'isoir155':
  10307. return 'ISO_10367-box';
  10308. case 'csiso15italian':
  10309. case 'iso646it':
  10310. case 'isoir15':
  10311. case 'it':
  10312. return 'IT';
  10313. case 'csiso13jisc6220jp':
  10314. case 'isoir13':
  10315. case 'jisc62201969':
  10316. case 'jisc62201969jp':
  10317. case 'katakana':
  10318. case 'x2017':
  10319. return 'JIS_C6220-1969-jp';
  10320. case 'csiso14jisc6220ro':
  10321. case 'iso646jp':
  10322. case 'isoir14':
  10323. case 'jisc62201969ro':
  10324. case 'jp':
  10325. return 'JIS_C6220-1969-ro';
  10326. case 'csiso42jisc62261978':
  10327. case 'isoir42':
  10328. case 'jisc62261978':
  10329. return 'JIS_C6226-1978';
  10330. case 'csiso87jisx208':
  10331. case 'isoir87':
  10332. case 'jisc62261983':
  10333. case 'jisx2081983':
  10334. case 'x208':
  10335. return 'JIS_C6226-1983';
  10336. case 'csiso91jisc62291984a':
  10337. case 'isoir91':
  10338. case 'jisc62291984a':
  10339. case 'jpocra':
  10340. return 'JIS_C6229-1984-a';
  10341. case 'csiso92jisc62991984b':
  10342. case 'iso646jpocrb':
  10343. case 'isoir92':
  10344. case 'jisc62291984b':
  10345. case 'jpocrb':
  10346. return 'JIS_C6229-1984-b';
  10347. case 'csiso93jis62291984badd':
  10348. case 'isoir93':
  10349. case 'jisc62291984badd':
  10350. case 'jpocrbadd':
  10351. return 'JIS_C6229-1984-b-add';
  10352. case 'csiso94jis62291984hand':
  10353. case 'isoir94':
  10354. case 'jisc62291984hand':
  10355. case 'jpocrhand':
  10356. return 'JIS_C6229-1984-hand';
  10357. case 'csiso95jis62291984handadd':
  10358. case 'isoir95':
  10359. case 'jisc62291984handadd':
  10360. case 'jpocrhandadd':
  10361. return 'JIS_C6229-1984-hand-add';
  10362. case 'csiso96jisc62291984kana':
  10363. case 'isoir96':
  10364. case 'jisc62291984kana':
  10365. return 'JIS_C6229-1984-kana';
  10366. case 'csjisencoding':
  10367. case 'jisencoding':
  10368. return 'JIS_Encoding';
  10369. case 'cshalfwidthkatakana':
  10370. case 'jisx201':
  10371. case 'x201':
  10372. return 'JIS_X0201';
  10373. case 'csiso159jisx2121990':
  10374. case 'isoir159':
  10375. case 'jisx2121990':
  10376. case 'x212':
  10377. return 'JIS_X0212-1990';
  10378. case 'csiso141jusib1002':
  10379. case 'iso646yu':
  10380. case 'isoir141':
  10381. case 'js':
  10382. case 'jusib1002':
  10383. case 'yu':
  10384. return 'JUS_I.B1.002';
  10385. case 'csiso147macedonian':
  10386. case 'isoir147':
  10387. case 'jusib1003mac':
  10388. case 'macedonian':
  10389. return 'JUS_I.B1.003-mac';
  10390. case 'csiso146serbian':
  10391. case 'isoir146':
  10392. case 'jusib1003serb':
  10393. case 'serbian':
  10394. return 'JUS_I.B1.003-serb';
  10395. case 'koi7switched':
  10396. return 'KOI7-switched';
  10397. case 'cskoi8r':
  10398. case 'koi8r':
  10399. return 'KOI8-R';
  10400. case 'koi8u':
  10401. return 'KOI8-U';
  10402. case 'csksc5636':
  10403. case 'iso646kr':
  10404. case 'ksc5636':
  10405. return 'KSC5636';
  10406. case 'cskz1048':
  10407. case 'kz1048':
  10408. case 'rk1048':
  10409. case 'strk10482002':
  10410. return 'KZ-1048';
  10411. case 'csiso19latingreek':
  10412. case 'isoir19':
  10413. case 'latingreek':
  10414. return 'latin-greek';
  10415. case 'csiso27latingreek1':
  10416. case 'isoir27':
  10417. case 'latingreek1':
  10418. return 'Latin-greek-1';
  10419. case 'csiso158lap':
  10420. case 'isoir158':
  10421. case 'lap':
  10422. case 'latinlap':
  10423. return 'latin-lap';
  10424. case 'csmacintosh':
  10425. case 'mac':
  10426. case 'macintosh':
  10427. return 'macintosh';
  10428. case 'csmicrosoftpublishing':
  10429. case 'microsoftpublishing':
  10430. return 'Microsoft-Publishing';
  10431. case 'csmnem':
  10432. case 'mnem':
  10433. return 'MNEM';
  10434. case 'csmnemonic':
  10435. case 'mnemonic':
  10436. return 'MNEMONIC';
  10437. case 'csiso86hungarian':
  10438. case 'hu':
  10439. case 'iso646hu':
  10440. case 'isoir86':
  10441. case 'msz77953':
  10442. return 'MSZ_7795.3';
  10443. case 'csnatsdano':
  10444. case 'isoir91':
  10445. case 'natsdano':
  10446. return 'NATS-DANO';
  10447. case 'csnatsdanoadd':
  10448. case 'isoir92':
  10449. case 'natsdanoadd':
  10450. return 'NATS-DANO-ADD';
  10451. case 'csnatssefi':
  10452. case 'isoir81':
  10453. case 'natssefi':
  10454. return 'NATS-SEFI';
  10455. case 'csnatssefiadd':
  10456. case 'isoir82':
  10457. case 'natssefiadd':
  10458. return 'NATS-SEFI-ADD';
  10459. case 'csiso151cuba':
  10460. case 'cuba':
  10461. case 'iso646cu':
  10462. case 'isoir151':
  10463. case 'ncnc1081':
  10464. return 'NC_NC00-10:81';
  10465. case 'csiso69french':
  10466. case 'fr':
  10467. case 'iso646fr':
  10468. case 'isoir69':
  10469. case 'nfz62010':
  10470. return 'NF_Z_62-010';
  10471. case 'csiso25french':
  10472. case 'iso646fr1':
  10473. case 'isoir25':
  10474. case 'nfz620101973':
  10475. return 'NF_Z_62-010_(1973)';
  10476. case 'csiso60danishnorwegian':
  10477. case 'csiso60norwegian1':
  10478. case 'iso646no':
  10479. case 'isoir60':
  10480. case 'no':
  10481. case 'ns45511':
  10482. return 'NS_4551-1';
  10483. case 'csiso61norwegian2':
  10484. case 'iso646no2':
  10485. case 'isoir61':
  10486. case 'no2':
  10487. case 'ns45512':
  10488. return 'NS_4551-2';
  10489. case 'osdebcdicdf3irv':
  10490. return 'OSD_EBCDIC_DF03_IRV';
  10491. case 'osdebcdicdf41':
  10492. return 'OSD_EBCDIC_DF04_1';
  10493. case 'osdebcdicdf415':
  10494. return 'OSD_EBCDIC_DF04_15';
  10495. case 'cspc8danishnorwegian':
  10496. case 'pc8danishnorwegian':
  10497. return 'PC8-Danish-Norwegian';
  10498. case 'cspc8turkish':
  10499. case 'pc8turkish':
  10500. return 'PC8-Turkish';
  10501. case 'csiso16portuguese':
  10502. case 'iso646pt':
  10503. case 'isoir16':
  10504. case 'pt':
  10505. return 'PT';
  10506. case 'csiso84portuguese2':
  10507. case 'iso646pt2':
  10508. case 'isoir84':
  10509. case 'pt2':
  10510. return 'PT2';
  10511. case 'cp154':
  10512. case 'csptcp154':
  10513. case 'cyrillicasian':
  10514. case 'pt154':
  10515. case 'ptcp154':
  10516. return 'PTCP154';
  10517. case 'scsu':
  10518. return 'SCSU';
  10519. case 'csiso10swedish':
  10520. case 'fi':
  10521. case 'iso646fi':
  10522. case 'iso646se':
  10523. case 'isoir10':
  10524. case 'se':
  10525. case 'sen850200b':
  10526. return 'SEN_850200_B';
  10527. case 'csiso11swedishfornames':
  10528. case 'iso646se2':
  10529. case 'isoir11':
  10530. case 'se2':
  10531. case 'sen850200c':
  10532. return 'SEN_850200_C';
  10533. case 'csiso102t617bit':
  10534. case 'isoir102':
  10535. case 't617bit':
  10536. return 'T.61-7bit';
  10537. case 'csiso103t618bit':
  10538. case 'isoir103':
  10539. case 't61':
  10540. case 't618bit':
  10541. return 'T.61-8bit';
  10542. case 'csiso128t101g2':
  10543. case 'isoir128':
  10544. case 't101g2':
  10545. return 'T.101-G2';
  10546. case 'cstscii':
  10547. case 'tscii':
  10548. return 'TSCII';
  10549. case 'csunicode11':
  10550. case 'unicode11':
  10551. return 'UNICODE-1-1';
  10552. case 'csunicode11utf7':
  10553. case 'unicode11utf7':
  10554. return 'UNICODE-1-1-UTF-7';
  10555. case 'csunknown8bit':
  10556. case 'unknown8bit':
  10557. return 'UNKNOWN-8BIT';
  10558. case 'ansix341968':
  10559. case 'ansix341986':
  10560. case 'ascii':
  10561. case 'cp367':
  10562. case 'csascii':
  10563. case 'ibm367':
  10564. case 'iso646irv1991':
  10565. case 'iso646us':
  10566. case 'isoir6':
  10567. case 'us':
  10568. case 'usascii':
  10569. return 'US-ASCII';
  10570. case 'csusdk':
  10571. case 'usdk':
  10572. return 'us-dk';
  10573. case 'utf7':
  10574. return 'UTF-7';
  10575. case 'utf8':
  10576. return 'UTF-8';
  10577. case 'utf16':
  10578. return 'UTF-16';
  10579. case 'utf16be':
  10580. return 'UTF-16BE';
  10581. case 'utf16le':
  10582. return 'UTF-16LE';
  10583. case 'utf32':
  10584. return 'UTF-32';
  10585. case 'utf32be':
  10586. return 'UTF-32BE';
  10587. case 'utf32le':
  10588. return 'UTF-32LE';
  10589. case 'csventurainternational':
  10590. case 'venturainternational':
  10591. return 'Ventura-International';
  10592. case 'csventuramath':
  10593. case 'venturamath':
  10594. return 'Ventura-Math';
  10595. case 'csventuraus':
  10596. case 'venturaus':
  10597. return 'Ventura-US';
  10598. case 'csiso70videotexsupp1':
  10599. case 'isoir70':
  10600. case 'videotexsuppl':
  10601. return 'videotex-suppl';
  10602. case 'csviqr':
  10603. case 'viqr':
  10604. return 'VIQR';
  10605. case 'csviscii':
  10606. case 'viscii':
  10607. return 'VISCII';
  10608. case 'csshiftjis':
  10609. case 'cswindows31j':
  10610. case 'mskanji':
  10611. case 'shiftjis':
  10612. case 'windows31j':
  10613. return 'Windows-31J';
  10614. case 'iso885911':
  10615. case 'tis620':
  10616. return 'windows-874';
  10617. case 'cseuckr':
  10618. case 'csksc56011987':
  10619. case 'euckr':
  10620. case 'isoir149':
  10621. case 'korean':
  10622. case 'ksc5601':
  10623. case 'ksc56011987':
  10624. case 'ksc56011989':
  10625. case 'windows949':
  10626. return 'windows-949';
  10627. case 'windows1250':
  10628. return 'windows-1250';
  10629. case 'windows1251':
  10630. return 'windows-1251';
  10631. case 'cp819':
  10632. case 'csisolatin1':
  10633. case 'ibm819':
  10634. case 'iso88591':
  10635. case 'iso885911987':
  10636. case 'isoir100':
  10637. case 'l1':
  10638. case 'latin1':
  10639. case 'windows1252':
  10640. return 'windows-1252';
  10641. case 'windows1253':
  10642. return 'windows-1253';
  10643. case 'csisolatin5':
  10644. case 'iso88599':
  10645. case 'iso885991989':
  10646. case 'isoir148':
  10647. case 'l5':
  10648. case 'latin5':
  10649. case 'windows1254':
  10650. return 'windows-1254';
  10651. case 'windows1255':
  10652. return 'windows-1255';
  10653. case 'windows1256':
  10654. return 'windows-1256';
  10655. case 'windows1257':
  10656. return 'windows-1257';
  10657. case 'windows1258':
  10658. return 'windows-1258';
  10659. default:
  10660. return $charset;
  10661. }
  10662. }
  10663. public static function get_curl_version()
  10664. {
  10665. if (is_array($curl = curl_version()))
  10666. {
  10667. $curl = $curl['version'];
  10668. }
  10669. elseif (substr($curl, 0, 5) === 'curl/')
  10670. {
  10671. $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
  10672. }
  10673. elseif (substr($curl, 0, 8) === 'libcurl/')
  10674. {
  10675. $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
  10676. }
  10677. else
  10678. {
  10679. $curl = 0;
  10680. }
  10681. return $curl;
  10682. }
  10683. public static function is_subclass_of($class1, $class2)
  10684. {
  10685. if (func_num_args() !== 2)
  10686. {
  10687. trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
  10688. }
  10689. elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
  10690. {
  10691. return is_subclass_of($class1, $class2);
  10692. }
  10693. elseif (is_string($class1) && is_string($class2))
  10694. {
  10695. if (class_exists($class1))
  10696. {
  10697. if (class_exists($class2))
  10698. {
  10699. $class2 = strtolower($class2);
  10700. while ($class1 = strtolower(get_parent_class($class1)))
  10701. {
  10702. if ($class1 === $class2)
  10703. {
  10704. return true;
  10705. }
  10706. }
  10707. }
  10708. }
  10709. else
  10710. {
  10711. trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
  10712. }
  10713. }
  10714. return false;
  10715. }
  10716. /**
  10717. * Strip HTML comments
  10718. *
  10719. * @param string $data Data to strip comments from
  10720. * @return string Comment stripped string
  10721. */
  10722. public static function strip_comments($data)
  10723. {
  10724. $output = '';
  10725. while (($start = strpos($data, '<!--')) !== false)
  10726. {
  10727. $output .= substr($data, 0, $start);
  10728. if (($end = strpos($data, '-->', $start)) !== false)
  10729. {
  10730. $data = substr_replace($data, '', 0, $end + 3);
  10731. }
  10732. else
  10733. {
  10734. $data = '';
  10735. }
  10736. }
  10737. return $output . $data;
  10738. }
  10739. public static function parse_date($dt)
  10740. {
  10741. $parser = SimplePie_Parse_Date::get();
  10742. return $parser->parse($dt);
  10743. }
  10744. /**
  10745. * Decode HTML entities
  10746. *
  10747. * @static
  10748. * @param string $data Input data
  10749. * @return string Output data
  10750. */
  10751. public static function entities_decode($data)
  10752. {
  10753. $decoder = new SimplePie_Decode_HTML_Entities($data);
  10754. return $decoder->parse();
  10755. }
  10756. /**
  10757. * Remove RFC822 comments
  10758. *
  10759. * @param string $data Data to strip comments from
  10760. * @return string Comment stripped string
  10761. */
  10762. public static function uncomment_rfc822($string)
  10763. {
  10764. $string = (string) $string;
  10765. $position = 0;
  10766. $length = strlen($string);
  10767. $depth = 0;
  10768. $output = '';
  10769. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  10770. {
  10771. $output .= substr($string, $position, $pos - $position);
  10772. $position = $pos + 1;
  10773. if ($string[$pos - 1] !== '\\')
  10774. {
  10775. $depth++;
  10776. while ($depth && $position < $length)
  10777. {
  10778. $position += strcspn($string, '()', $position);
  10779. if ($string[$position - 1] === '\\')
  10780. {
  10781. $position++;
  10782. continue;
  10783. }
  10784. elseif (isset($string[$position]))
  10785. {
  10786. switch ($string[$position])
  10787. {
  10788. case '(':
  10789. $depth++;
  10790. break;
  10791. case ')':
  10792. $depth--;
  10793. break;
  10794. }
  10795. $position++;
  10796. }
  10797. else
  10798. {
  10799. break;
  10800. }
  10801. }
  10802. }
  10803. else
  10804. {
  10805. $output .= '(';
  10806. }
  10807. }
  10808. $output .= substr($string, $position);
  10809. return $output;
  10810. }
  10811. public static function parse_mime($mime)
  10812. {
  10813. if (($pos = strpos($mime, ';')) === false)
  10814. {
  10815. return trim($mime);
  10816. }
  10817. else
  10818. {
  10819. return trim(substr($mime, 0, $pos));
  10820. }
  10821. }
  10822. public static function htmlspecialchars_decode($string, $quote_style)
  10823. {
  10824. if (function_exists('htmlspecialchars_decode'))
  10825. {
  10826. return htmlspecialchars_decode($string, $quote_style);
  10827. }
  10828. else
  10829. {
  10830. return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
  10831. }
  10832. }
  10833. public static function atom_03_construct_type($attribs)
  10834. {
  10835. if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
  10836. {
  10837. $mode = SIMPLEPIE_CONSTRUCT_BASE64;
  10838. }
  10839. else
  10840. {
  10841. $mode = SIMPLEPIE_CONSTRUCT_NONE;
  10842. }
  10843. if (isset($attribs['']['type']))
  10844. {
  10845. switch (strtolower(trim($attribs['']['type'])))
  10846. {
  10847. case 'text':
  10848. case 'text/plain':
  10849. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  10850. case 'html':
  10851. case 'text/html':
  10852. return SIMPLEPIE_CONSTRUCT_HTML | $mode;
  10853. case 'xhtml':
  10854. case 'application/xhtml+xml':
  10855. return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
  10856. default:
  10857. return SIMPLEPIE_CONSTRUCT_NONE | $mode;
  10858. }
  10859. }
  10860. else
  10861. {
  10862. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  10863. }
  10864. }
  10865. public static function atom_10_construct_type($attribs)
  10866. {
  10867. if (isset($attribs['']['type']))
  10868. {
  10869. switch (strtolower(trim($attribs['']['type'])))
  10870. {
  10871. case 'text':
  10872. return SIMPLEPIE_CONSTRUCT_TEXT;
  10873. case 'html':
  10874. return SIMPLEPIE_CONSTRUCT_HTML;
  10875. case 'xhtml':
  10876. return SIMPLEPIE_CONSTRUCT_XHTML;
  10877. default:
  10878. return SIMPLEPIE_CONSTRUCT_NONE;
  10879. }
  10880. }
  10881. return SIMPLEPIE_CONSTRUCT_TEXT;
  10882. }
  10883. public static function atom_10_content_construct_type($attribs)
  10884. {
  10885. if (isset($attribs['']['type']))
  10886. {
  10887. $type = strtolower(trim($attribs['']['type']));
  10888. switch ($type)
  10889. {
  10890. case 'text':
  10891. return SIMPLEPIE_CONSTRUCT_TEXT;
  10892. case 'html':
  10893. return SIMPLEPIE_CONSTRUCT_HTML;
  10894. case 'xhtml':
  10895. return SIMPLEPIE_CONSTRUCT_XHTML;
  10896. }
  10897. if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
  10898. {
  10899. return SIMPLEPIE_CONSTRUCT_NONE;
  10900. }
  10901. else
  10902. {
  10903. return SIMPLEPIE_CONSTRUCT_BASE64;
  10904. }
  10905. }
  10906. else
  10907. {
  10908. return SIMPLEPIE_CONSTRUCT_TEXT;
  10909. }
  10910. }
  10911. public static function is_isegment_nz_nc($string)
  10912. {
  10913. return (bool) preg_match('/^([A-Za-z0-9\-._~\x{A0}-\x{D7FF}\x{F900}-\x{FDCF}\x{FDF0}-\x{FFEF}\x{10000}-\x{1FFFD}\x{20000}-\x{2FFFD}\x{30000}-\x{3FFFD}\x{40000}-\x{4FFFD}\x{50000}-\x{5FFFD}\x{60000}-\x{6FFFD}\x{70000}-\x{7FFFD}\x{80000}-\x{8FFFD}\x{90000}-\x{9FFFD}\x{A0000}-\x{AFFFD}\x{B0000}-\x{BFFFD}\x{C0000}-\x{CFFFD}\x{D0000}-\x{DFFFD}\x{E1000}-\x{EFFFD}!$&\'()*+,;=@]|(%[0-9ABCDEF]{2}))+$/u', $string);
  10914. }
  10915. public static function space_seperated_tokens($string)
  10916. {
  10917. $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
  10918. $string_length = strlen($string);
  10919. $position = strspn($string, $space_characters);
  10920. $tokens = array();
  10921. while ($position < $string_length)
  10922. {
  10923. $len = strcspn($string, $space_characters, $position);
  10924. $tokens[] = substr($string, $position, $len);
  10925. $position += $len;
  10926. $position += strspn($string, $space_characters, $position);
  10927. }
  10928. return $tokens;
  10929. }
  10930. public static function array_unique($array)
  10931. {
  10932. if (version_compare(PHP_VERSION, '5.2', '>='))
  10933. {
  10934. return array_unique($array);
  10935. }
  10936. else
  10937. {
  10938. $array = (array) $array;
  10939. $new_array = array();
  10940. $new_array_strings = array();
  10941. foreach ($array as $key => $value)
  10942. {
  10943. if (is_object($value))
  10944. {
  10945. if (method_exists($value, '__toString'))
  10946. {
  10947. $cmp = $value->__toString();
  10948. }
  10949. else
  10950. {
  10951. trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
  10952. }
  10953. }
  10954. elseif (is_array($value))
  10955. {
  10956. $cmp = (string) reset($value);
  10957. }
  10958. else
  10959. {
  10960. $cmp = (string) $value;
  10961. }
  10962. if (!in_array($cmp, $new_array_strings))
  10963. {
  10964. $new_array[$key] = $value;
  10965. $new_array_strings[] = $cmp;
  10966. }
  10967. }
  10968. return $new_array;
  10969. }
  10970. }
  10971. /**
  10972. * Converts a unicode codepoint to a UTF-8 character
  10973. *
  10974. * @static
  10975. * @param int $codepoint Unicode codepoint
  10976. * @return string UTF-8 character
  10977. */
  10978. public static function codepoint_to_utf8($codepoint)
  10979. {
  10980. $codepoint = (int) $codepoint;
  10981. if ($codepoint < 0)
  10982. {
  10983. return false;
  10984. }
  10985. else if ($codepoint <= 0x7f)
  10986. {
  10987. return chr($codepoint);
  10988. }
  10989. else if ($codepoint <= 0x7ff)
  10990. {
  10991. return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
  10992. }
  10993. else if ($codepoint <= 0xffff)
  10994. {
  10995. return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  10996. }
  10997. else if ($codepoint <= 0x10ffff)
  10998. {
  10999. return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  11000. }
  11001. else
  11002. {
  11003. // U+FFFD REPLACEMENT CHARACTER
  11004. return "\xEF\xBF\xBD";
  11005. }
  11006. }
  11007. /**
  11008. * Similar to parse_str()
  11009. *
  11010. * Returns an associative array of name/value pairs, where the value is an
  11011. * array of values that have used the same name
  11012. *
  11013. * @static
  11014. * @param string $str The input string.
  11015. * @return array
  11016. */
  11017. public static function parse_str($str)
  11018. {
  11019. $return = array();
  11020. $str = explode('&', $str);
  11021. foreach ($str as $section)
  11022. {
  11023. if (strpos($section, '=') !== false)
  11024. {
  11025. list($name, $value) = explode('=', $section, 2);
  11026. $return[urldecode($name)][] = urldecode($value);
  11027. }
  11028. else
  11029. {
  11030. $return[urldecode($section)][] = null;
  11031. }
  11032. }
  11033. return $return;
  11034. }
  11035. /**
  11036. * Detect XML encoding, as per XML 1.0 Appendix F.1
  11037. *
  11038. * @todo Add support for EBCDIC
  11039. * @param string $data XML data
  11040. * @return array Possible encodings
  11041. */
  11042. public static function xml_encoding($data)
  11043. {
  11044. // UTF-32 Big Endian BOM
  11045. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  11046. {
  11047. $encoding[] = 'UTF-32BE';
  11048. }
  11049. // UTF-32 Little Endian BOM
  11050. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  11051. {
  11052. $encoding[] = 'UTF-32LE';
  11053. }
  11054. // UTF-16 Big Endian BOM
  11055. elseif (substr($data, 0, 2) === "\xFE\xFF")
  11056. {
  11057. $encoding[] = 'UTF-16BE';
  11058. }
  11059. // UTF-16 Little Endian BOM
  11060. elseif (substr($data, 0, 2) === "\xFF\xFE")
  11061. {
  11062. $encoding[] = 'UTF-16LE';
  11063. }
  11064. // UTF-8 BOM
  11065. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  11066. {
  11067. $encoding[] = 'UTF-8';
  11068. }
  11069. // UTF-32 Big Endian Without BOM
  11070. elseif (substr($data, 0, 20) === "\x00\x00\x00\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C")
  11071. {
  11072. if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
  11073. {
  11074. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
  11075. if ($parser->parse())
  11076. {
  11077. $encoding[] = $parser->encoding;
  11078. }
  11079. }
  11080. $encoding[] = 'UTF-32BE';
  11081. }
  11082. // UTF-32 Little Endian Without BOM
  11083. elseif (substr($data, 0, 20) === "\x3C\x00\x00\x00\x3F\x00\x00\x00\x78\x00\x00\x00\x6D\x00\x00\x00\x6C\x00\x00\x00")
  11084. {
  11085. if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
  11086. {
  11087. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
  11088. if ($parser->parse())
  11089. {
  11090. $encoding[] = $parser->encoding;
  11091. }
  11092. }
  11093. $encoding[] = 'UTF-32LE';
  11094. }
  11095. // UTF-16 Big Endian Without BOM
  11096. elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
  11097. {
  11098. if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
  11099. {
  11100. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
  11101. if ($parser->parse())
  11102. {
  11103. $encoding[] = $parser->encoding;
  11104. }
  11105. }
  11106. $encoding[] = 'UTF-16BE';
  11107. }
  11108. // UTF-16 Little Endian Without BOM
  11109. elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
  11110. {
  11111. if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
  11112. {
  11113. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
  11114. if ($parser->parse())
  11115. {
  11116. $encoding[] = $parser->encoding;
  11117. }
  11118. }
  11119. $encoding[] = 'UTF-16LE';
  11120. }
  11121. // US-ASCII (or superset)
  11122. elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
  11123. {
  11124. if ($pos = strpos($data, "\x3F\x3E"))
  11125. {
  11126. $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  11127. if ($parser->parse())
  11128. {
  11129. $encoding[] = $parser->encoding;
  11130. }
  11131. }
  11132. $encoding[] = 'UTF-8';
  11133. }
  11134. // Fallback to UTF-8
  11135. else
  11136. {
  11137. $encoding[] = 'UTF-8';
  11138. }
  11139. return $encoding;
  11140. }
  11141. public static function output_javascript()
  11142. {
  11143. if (function_exists('ob_gzhandler'))
  11144. {
  11145. ob_start('ob_gzhandler');
  11146. }
  11147. header('Content-type: text/javascript; charset: UTF-8');
  11148. header('Cache-Control: must-revalidate');
  11149. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
  11150. ?>
  11151. function embed_odeo(link) {
  11152. document.writeln('<embed src="http://odeo.com/flash/audio_player_fullsize.swf" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="440" height="80" wmode="transparent" allowScriptAccess="any" flashvars="valid_sample_rate=true&external_url='+link+'"></embed>');
  11153. }
  11154. function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
  11155. if (placeholder != '') {
  11156. document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" href="'+link+'" src="'+placeholder+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="false" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
  11157. }
  11158. else {
  11159. document.writeln('<embed type="'+type+'" style="cursor:hand; cursor:pointer;" src="'+link+'" width="'+width+'" height="'+height+'" autoplay="false" target="myself" controller="true" loop="'+loop+'" scale="aspect" bgcolor="'+bgcolor+'" pluginspage="http://www.apple.com/quicktime/download/"></embed>');
  11160. }
  11161. }
  11162. function embed_flash(bgcolor, width, height, link, loop, type) {
  11163. document.writeln('<embed src="'+link+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="'+type+'" quality="high" width="'+width+'" height="'+height+'" bgcolor="'+bgcolor+'" loop="'+loop+'"></embed>');
  11164. }
  11165. function embed_flv(width, height, link, placeholder, loop, player) {
  11166. document.writeln('<embed src="'+player+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" quality="high" width="'+width+'" height="'+height+'" wmode="transparent" flashvars="file='+link+'&autostart=false&repeat='+loop+'&showdigits=true&showfsbutton=false"></embed>');
  11167. }
  11168. function embed_wmedia(width, height, link) {
  11169. document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
  11170. }
  11171. <?php
  11172. }
  11173. /**
  11174. * Get the SimplePie build timestamp
  11175. *
  11176. * Uses the git index if it exists, otherwise uses the modification time
  11177. * of the newest file.
  11178. */
  11179. public static function get_build()
  11180. {
  11181. $root = dirname(dirname(__FILE__));
  11182. if (file_exists($root . '/.git/index'))
  11183. {
  11184. return filemtime($root . '/.git/index');
  11185. }
  11186. elseif (file_exists($root . '/SimplePie'))
  11187. {
  11188. $time = 0;
  11189. foreach (glob($root . '/SimplePie/*.php') as $file)
  11190. {
  11191. if (($mtime = filemtime($file)) > $time)
  11192. {
  11193. $time = $mtime;
  11194. }
  11195. }
  11196. return $time;
  11197. }
  11198. elseif (file_exists(dirname(__FILE__) . '/Core.php'))
  11199. {
  11200. return filemtime(dirname(__FILE__) . '/Core.php');
  11201. }
  11202. else
  11203. {
  11204. return filemtime(__FILE__);
  11205. }
  11206. }
  11207. /**
  11208. * Format debugging information
  11209. */
  11210. public static function debug(&$sp)
  11211. {
  11212. $info = 'SimplePie ' . SIMPLEPIE_VERSION . ' Build ' . SIMPLEPIE_BUILD . "\n";
  11213. $info .= 'PHP ' . PHP_VERSION . "\n";
  11214. if ($sp->error() !== null)
  11215. {
  11216. $info .= 'Error occurred: ' . $sp->error() . "\n";
  11217. }
  11218. else
  11219. {
  11220. $info .= "No error found.\n";
  11221. }
  11222. $info .= "Extensions:\n";
  11223. $extensions = array('pcre', 'curl', 'zlib', 'mbstring', 'iconv', 'xmlreader', 'xml');
  11224. foreach ($extensions as $ext)
  11225. {
  11226. if (extension_loaded($ext))
  11227. {
  11228. $info .= " $ext loaded\n";
  11229. switch ($ext)
  11230. {
  11231. case 'pcre':
  11232. $info .= ' Version ' . PCRE_VERSION . "\n";
  11233. break;
  11234. case 'curl':
  11235. $version = curl_version();
  11236. $info .= ' Version ' . $version['version'] . "\n";
  11237. break;
  11238. case 'mbstring':
  11239. $info .= ' Overloading: ' . mb_get_info('func_overload') . "\n";
  11240. break;
  11241. case 'iconv':
  11242. $info .= ' Version ' . ICONV_VERSION . "\n";
  11243. break;
  11244. case 'xml':
  11245. $info .= ' Version ' . LIBXML_DOTTED_VERSION . "\n";
  11246. break;
  11247. }
  11248. }
  11249. else
  11250. {
  11251. $info .= " $ext not loaded\n";
  11252. }
  11253. }
  11254. return $info;
  11255. }
  11256. }
  11257. /**
  11258. * Class to validate and to work with IPv6 addresses.
  11259. *
  11260. * @package SimplePie
  11261. * @copyright 2003-2005 The PHP Group
  11262. * @license http://www.opensource.org/licenses/bsd-license.php
  11263. * @link http://pear.php.net/package/Net_IPv6
  11264. * @author Alexander Merz <alexander.merz@web.de>
  11265. * @author elfrink at introweb dot nl
  11266. * @author Josh Peck <jmp at joshpeck dot org>
  11267. * @author Geoffrey Sneddon <geoffers@gmail.com>
  11268. */
  11269. class SimplePie_Net_IPv6
  11270. {
  11271. /**
  11272. * Removes a possible existing netmask specification of an IP address.
  11273. *
  11274. * @param string $ip the (compressed) IP as Hex representation
  11275. * @return string the IP the without netmask
  11276. * @since 1.1.0
  11277. * @access public
  11278. * @static
  11279. */
  11280. public static function removeNetmaskSpec($ip)
  11281. {
  11282. if (strpos($ip, '/') !== false)
  11283. {
  11284. list($addr, $nm) = explode('/', $ip);
  11285. }
  11286. else
  11287. {
  11288. $addr = $ip;
  11289. }
  11290. return $addr;
  11291. }
  11292. /**
  11293. * Uncompresses an IPv6 address
  11294. *
  11295. * RFC 2373 allows you to compress zeros in an address to '::'. This
  11296. * function expects an valid IPv6 address and expands the '::' to
  11297. * the required zeros.
  11298. *
  11299. * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
  11300. * ::1 -> 0:0:0:0:0:0:0:1
  11301. *
  11302. * @access public
  11303. * @static
  11304. * @param string $ip a valid IPv6-address (hex format)
  11305. * @return string the uncompressed IPv6-address (hex format)
  11306. */
  11307. public static function Uncompress($ip)
  11308. {
  11309. $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
  11310. $c1 = -1;
  11311. $c2 = -1;
  11312. if (strpos($ip, '::') !== false)
  11313. {
  11314. list($ip1, $ip2) = explode('::', $ip);
  11315. if ($ip1 === '')
  11316. {
  11317. $c1 = -1;
  11318. }
  11319. else
  11320. {
  11321. $pos = 0;
  11322. if (($pos = substr_count($ip1, ':')) > 0)
  11323. {
  11324. $c1 = $pos;
  11325. }
  11326. else
  11327. {
  11328. $c1 = 0;
  11329. }
  11330. }
  11331. if ($ip2 === '')
  11332. {
  11333. $c2 = -1;
  11334. }
  11335. else
  11336. {
  11337. $pos = 0;
  11338. if (($pos = substr_count($ip2, ':')) > 0)
  11339. {
  11340. $c2 = $pos;
  11341. }
  11342. else
  11343. {
  11344. $c2 = 0;
  11345. }
  11346. }
  11347. if (strstr($ip2, '.'))
  11348. {
  11349. $c2++;
  11350. }
  11351. // ::
  11352. if ($c1 === -1 && $c2 === -1)
  11353. {
  11354. $uip = '0:0:0:0:0:0:0:0';
  11355. }
  11356. // ::xxx
  11357. else if ($c1 === -1)
  11358. {
  11359. $fill = str_repeat('0:', 7 - $c2);
  11360. $uip = str_replace('::', $fill, $uip);
  11361. }
  11362. // xxx::
  11363. else if ($c2 === -1)
  11364. {
  11365. $fill = str_repeat(':0', 7 - $c1);
  11366. $uip = str_replace('::', $fill, $uip);
  11367. }
  11368. // xxx::xxx
  11369. else
  11370. {
  11371. $fill = str_repeat(':0:', 6 - $c2 - $c1);
  11372. $uip = str_replace('::', $fill, $uip);
  11373. $uip = str_replace('::', ':', $uip);
  11374. }
  11375. }
  11376. return $uip;
  11377. }
  11378. /**
  11379. * Splits an IPv6 address into the IPv6 and a possible IPv4 part
  11380. *
  11381. * RFC 2373 allows you to note the last two parts of an IPv6 address as
  11382. * an IPv4 compatible address
  11383. *
  11384. * Example: 0:0:0:0:0:0:13.1.68.3
  11385. * 0:0:0:0:0:FFFF:129.144.52.38
  11386. *
  11387. * @access public
  11388. * @static
  11389. * @param string $ip a valid IPv6-address (hex format)
  11390. * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
  11391. */
  11392. public static function SplitV64($ip)
  11393. {
  11394. $ip = SimplePie_Net_IPv6::Uncompress($ip);
  11395. if (strstr($ip, '.'))
  11396. {
  11397. $pos = strrpos($ip, ':');
  11398. $ip[$pos] = '_';
  11399. $ipPart = explode('_', $ip);
  11400. return $ipPart;
  11401. }
  11402. else
  11403. {
  11404. return array($ip, '');
  11405. }
  11406. }
  11407. /**
  11408. * Checks an IPv6 address
  11409. *
  11410. * Checks if the given IP is IPv6-compatible
  11411. *
  11412. * @access public
  11413. * @static
  11414. * @param string $ip a valid IPv6-address
  11415. * @return bool true if $ip is an IPv6 address
  11416. */
  11417. public static function checkIPv6($ip)
  11418. {
  11419. $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
  11420. $count = 0;
  11421. if (!empty($ipPart[0]))
  11422. {
  11423. $ipv6 = explode(':', $ipPart[0]);
  11424. for ($i = 0; $i < count($ipv6); $i++)
  11425. {
  11426. $dec = hexdec($ipv6[$i]);
  11427. $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
  11428. if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
  11429. {
  11430. $count++;
  11431. }
  11432. }
  11433. if ($count === 8)
  11434. {
  11435. return true;
  11436. }
  11437. elseif ($count === 6 && !empty($ipPart[1]))
  11438. {
  11439. $ipv4 = explode('.', $ipPart[1]);
  11440. $count = 0;
  11441. foreach ($ipv4 as $ipv4_part)
  11442. {
  11443. if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
  11444. {
  11445. $count++;
  11446. }
  11447. }
  11448. if ($count === 4)
  11449. {
  11450. return true;
  11451. }
  11452. }
  11453. else
  11454. {
  11455. return false;
  11456. }
  11457. }
  11458. else
  11459. {
  11460. return false;
  11461. }
  11462. }
  11463. }
  11464. /**
  11465. * Date Parser
  11466. *
  11467. * @package SimplePie
  11468. */
  11469. class SimplePie_Parse_Date
  11470. {
  11471. /**
  11472. * Input data
  11473. *
  11474. * @access protected
  11475. * @var string
  11476. */
  11477. var $date;
  11478. /**
  11479. * List of days, calendar day name => ordinal day number in the week
  11480. *
  11481. * @access protected
  11482. * @var array
  11483. */
  11484. var $day = array(
  11485. // English
  11486. 'mon' => 1,
  11487. 'monday' => 1,
  11488. 'tue' => 2,
  11489. 'tuesday' => 2,
  11490. 'wed' => 3,
  11491. 'wednesday' => 3,
  11492. 'thu' => 4,
  11493. 'thursday' => 4,
  11494. 'fri' => 5,
  11495. 'friday' => 5,
  11496. 'sat' => 6,
  11497. 'saturday' => 6,
  11498. 'sun' => 7,
  11499. 'sunday' => 7,
  11500. // Dutch
  11501. 'maandag' => 1,
  11502. 'dinsdag' => 2,
  11503. 'woensdag' => 3,
  11504. 'donderdag' => 4,
  11505. 'vrijdag' => 5,
  11506. 'zaterdag' => 6,
  11507. 'zondag' => 7,
  11508. // French
  11509. 'lundi' => 1,
  11510. 'mardi' => 2,
  11511. 'mercredi' => 3,
  11512. 'jeudi' => 4,
  11513. 'vendredi' => 5,
  11514. 'samedi' => 6,
  11515. 'dimanche' => 7,
  11516. // German
  11517. 'montag' => 1,
  11518. 'dienstag' => 2,
  11519. 'mittwoch' => 3,
  11520. 'donnerstag' => 4,
  11521. 'freitag' => 5,
  11522. 'samstag' => 6,
  11523. 'sonnabend' => 6,
  11524. 'sonntag' => 7,
  11525. // Italian
  11526. 'lunedì' => 1,
  11527. 'martedì' => 2,
  11528. 'mercoledì' => 3,
  11529. 'giovedì' => 4,
  11530. 'venerdì' => 5,
  11531. 'sabato' => 6,
  11532. 'domenica' => 7,
  11533. // Spanish
  11534. 'lunes' => 1,
  11535. 'martes' => 2,
  11536. 'miércoles' => 3,
  11537. 'jueves' => 4,
  11538. 'viernes' => 5,
  11539. 'sábado' => 6,
  11540. 'domingo' => 7,
  11541. // Finnish
  11542. 'maanantai' => 1,
  11543. 'tiistai' => 2,
  11544. 'keskiviikko' => 3,
  11545. 'torstai' => 4,
  11546. 'perjantai' => 5,
  11547. 'lauantai' => 6,
  11548. 'sunnuntai' => 7,
  11549. // Hungarian
  11550. 'hétfő' => 1,
  11551. 'kedd' => 2,
  11552. 'szerda' => 3,
  11553. 'csütörtok' => 4,
  11554. 'péntek' => 5,
  11555. 'szombat' => 6,
  11556. 'vasárnap' => 7,
  11557. // Greek
  11558. 'Δευ' => 1,
  11559. 'Τρι' => 2,
  11560. 'Τετ' => 3,
  11561. 'Πεμ' => 4,
  11562. 'Παρ' => 5,
  11563. 'Σαβ' => 6,
  11564. 'Κυρ' => 7,
  11565. );
  11566. /**
  11567. * List of months, calendar month name => calendar month number
  11568. *
  11569. * @access protected
  11570. * @var array
  11571. */
  11572. var $month = array(
  11573. // English
  11574. 'jan' => 1,
  11575. 'january' => 1,
  11576. 'feb' => 2,
  11577. 'february' => 2,
  11578. 'mar' => 3,
  11579. 'march' => 3,
  11580. 'apr' => 4,
  11581. 'april' => 4,
  11582. 'may' => 5,
  11583. // No long form of May
  11584. 'jun' => 6,
  11585. 'june' => 6,
  11586. 'jul' => 7,
  11587. 'july' => 7,
  11588. 'aug' => 8,
  11589. 'august' => 8,
  11590. 'sep' => 9,
  11591. 'september' => 8,
  11592. 'oct' => 10,
  11593. 'october' => 10,
  11594. 'nov' => 11,
  11595. 'november' => 11,
  11596. 'dec' => 12,
  11597. 'december' => 12,
  11598. // Dutch
  11599. 'januari' => 1,
  11600. 'februari' => 2,
  11601. 'maart' => 3,
  11602. 'april' => 4,
  11603. 'mei' => 5,
  11604. 'juni' => 6,
  11605. 'juli' => 7,
  11606. 'augustus' => 8,
  11607. 'september' => 9,
  11608. 'oktober' => 10,
  11609. 'november' => 11,
  11610. 'december' => 12,
  11611. // French
  11612. 'janvier' => 1,
  11613. 'février' => 2,
  11614. 'mars' => 3,
  11615. 'avril' => 4,
  11616. 'mai' => 5,
  11617. 'juin' => 6,
  11618. 'juillet' => 7,
  11619. 'août' => 8,
  11620. 'septembre' => 9,
  11621. 'octobre' => 10,
  11622. 'novembre' => 11,
  11623. 'décembre' => 12,
  11624. // German
  11625. 'januar' => 1,
  11626. 'februar' => 2,
  11627. 'märz' => 3,
  11628. 'april' => 4,
  11629. 'mai' => 5,
  11630. 'juni' => 6,
  11631. 'juli' => 7,
  11632. 'august' => 8,
  11633. 'september' => 9,
  11634. 'oktober' => 10,
  11635. 'november' => 11,
  11636. 'dezember' => 12,
  11637. // Italian
  11638. 'gennaio' => 1,
  11639. 'febbraio' => 2,
  11640. 'marzo' => 3,
  11641. 'aprile' => 4,
  11642. 'maggio' => 5,
  11643. 'giugno' => 6,
  11644. 'luglio' => 7,
  11645. 'agosto' => 8,
  11646. 'settembre' => 9,
  11647. 'ottobre' => 10,
  11648. 'novembre' => 11,
  11649. 'dicembre' => 12,
  11650. // Spanish
  11651. 'enero' => 1,
  11652. 'febrero' => 2,
  11653. 'marzo' => 3,
  11654. 'abril' => 4,
  11655. 'mayo' => 5,
  11656. 'junio' => 6,
  11657. 'julio' => 7,
  11658. 'agosto' => 8,
  11659. 'septiembre' => 9,
  11660. 'setiembre' => 9,
  11661. 'octubre' => 10,
  11662. 'noviembre' => 11,
  11663. 'diciembre' => 12,
  11664. // Finnish
  11665. 'tammikuu' => 1,
  11666. 'helmikuu' => 2,
  11667. 'maaliskuu' => 3,
  11668. 'huhtikuu' => 4,
  11669. 'toukokuu' => 5,
  11670. 'kesäkuu' => 6,
  11671. 'heinäkuu' => 7,
  11672. 'elokuu' => 8,
  11673. 'suuskuu' => 9,
  11674. 'lokakuu' => 10,
  11675. 'marras' => 11,
  11676. 'joulukuu' => 12,
  11677. // Hungarian
  11678. 'január' => 1,
  11679. 'február' => 2,
  11680. 'március' => 3,
  11681. 'április' => 4,
  11682. 'május' => 5,
  11683. 'június' => 6,
  11684. 'július' => 7,
  11685. 'augusztus' => 8,
  11686. 'szeptember' => 9,
  11687. 'október' => 10,
  11688. 'november' => 11,
  11689. 'december' => 12,
  11690. // Greek
  11691. 'Ιαν' => 1,
  11692. 'Φεβ' => 2,
  11693. 'Μάώ' => 3,
  11694. 'Μαώ' => 3,
  11695. 'Απρ' => 4,
  11696. 'Μάι' => 5,
  11697. 'Μαϊ' => 5,
  11698. 'Μαι' => 5,
  11699. 'Ιούν' => 6,
  11700. 'Ιον' => 6,
  11701. 'Ιούλ' => 7,
  11702. 'Ιολ' => 7,
  11703. 'Αύγ' => 8,
  11704. 'Αυγ' => 8,
  11705. 'Σεπ' => 9,
  11706. 'Οκτ' => 10,
  11707. 'Νοέ' => 11,
  11708. 'Δεκ' => 12,
  11709. );
  11710. /**
  11711. * List of timezones, abbreviation => offset from UTC
  11712. *
  11713. * @access protected
  11714. * @var array
  11715. */
  11716. var $timezone = array(
  11717. 'ACDT' => 37800,
  11718. 'ACIT' => 28800,
  11719. 'ACST' => 34200,
  11720. 'ACT' => -18000,
  11721. 'ACWDT' => 35100,
  11722. 'ACWST' => 31500,
  11723. 'AEDT' => 39600,
  11724. 'AEST' => 36000,
  11725. 'AFT' => 16200,
  11726. 'AKDT' => -28800,
  11727. 'AKST' => -32400,
  11728. 'AMDT' => 18000,
  11729. 'AMT' => -14400,
  11730. 'ANAST' => 46800,
  11731. 'ANAT' => 43200,
  11732. 'ART' => -10800,
  11733. 'AZOST' => -3600,
  11734. 'AZST' => 18000,
  11735. 'AZT' => 14400,
  11736. 'BIOT' => 21600,
  11737. 'BIT' => -43200,
  11738. 'BOT' => -14400,
  11739. 'BRST' => -7200,
  11740. 'BRT' => -10800,
  11741. 'BST' => 3600,
  11742. 'BTT' => 21600,
  11743. 'CAST' => 18000,
  11744. 'CAT' => 7200,
  11745. 'CCT' => 23400,
  11746. 'CDT' => -18000,
  11747. 'CEDT' => 7200,
  11748. 'CET' => 3600,
  11749. 'CGST' => -7200,
  11750. 'CGT' => -10800,
  11751. 'CHADT' => 49500,
  11752. 'CHAST' => 45900,
  11753. 'CIST' => -28800,
  11754. 'CKT' => -36000,
  11755. 'CLDT' => -10800,
  11756. 'CLST' => -14400,
  11757. 'COT' => -18000,
  11758. 'CST' => -21600,
  11759. 'CVT' => -3600,
  11760. 'CXT' => 25200,
  11761. 'DAVT' => 25200,
  11762. 'DTAT' => 36000,
  11763. 'EADT' => -18000,
  11764. 'EAST' => -21600,
  11765. 'EAT' => 10800,
  11766. 'ECT' => -18000,
  11767. 'EDT' => -14400,
  11768. 'EEST' => 10800,
  11769. 'EET' => 7200,
  11770. 'EGT' => -3600,
  11771. 'EKST' => 21600,
  11772. 'EST' => -18000,
  11773. 'FJT' => 43200,
  11774. 'FKDT' => -10800,
  11775. 'FKST' => -14400,
  11776. 'FNT' => -7200,
  11777. 'GALT' => -21600,
  11778. 'GEDT' => 14400,
  11779. 'GEST' => 10800,
  11780. 'GFT' => -10800,
  11781. 'GILT' => 43200,
  11782. 'GIT' => -32400,
  11783. 'GST' => 14400,
  11784. 'GST' => -7200,
  11785. 'GYT' => -14400,
  11786. 'HAA' => -10800,
  11787. 'HAC' => -18000,
  11788. 'HADT' => -32400,
  11789. 'HAE' => -14400,
  11790. 'HAP' => -25200,
  11791. 'HAR' => -21600,
  11792. 'HAST' => -36000,
  11793. 'HAT' => -9000,
  11794. 'HAY' => -28800,
  11795. 'HKST' => 28800,
  11796. 'HMT' => 18000,
  11797. 'HNA' => -14400,
  11798. 'HNC' => -21600,
  11799. 'HNE' => -18000,
  11800. 'HNP' => -28800,
  11801. 'HNR' => -25200,
  11802. 'HNT' => -12600,
  11803. 'HNY' => -32400,
  11804. 'IRDT' => 16200,
  11805. 'IRKST' => 32400,
  11806. 'IRKT' => 28800,
  11807. 'IRST' => 12600,
  11808. 'JFDT' => -10800,
  11809. 'JFST' => -14400,
  11810. 'JST' => 32400,
  11811. 'KGST' => 21600,
  11812. 'KGT' => 18000,
  11813. 'KOST' => 39600,
  11814. 'KOVST' => 28800,
  11815. 'KOVT' => 25200,
  11816. 'KRAST' => 28800,
  11817. 'KRAT' => 25200,
  11818. 'KST' => 32400,
  11819. 'LHDT' => 39600,
  11820. 'LHST' => 37800,
  11821. 'LINT' => 50400,
  11822. 'LKT' => 21600,
  11823. 'MAGST' => 43200,
  11824. 'MAGT' => 39600,
  11825. 'MAWT' => 21600,
  11826. 'MDT' => -21600,
  11827. 'MESZ' => 7200,
  11828. 'MEZ' => 3600,
  11829. 'MHT' => 43200,
  11830. 'MIT' => -34200,
  11831. 'MNST' => 32400,
  11832. 'MSDT' => 14400,
  11833. 'MSST' => 10800,
  11834. 'MST' => -25200,
  11835. 'MUT' => 14400,
  11836. 'MVT' => 18000,
  11837. 'MYT' => 28800,
  11838. 'NCT' => 39600,
  11839. 'NDT' => -9000,
  11840. 'NFT' => 41400,
  11841. 'NMIT' => 36000,
  11842. 'NOVST' => 25200,
  11843. 'NOVT' => 21600,
  11844. 'NPT' => 20700,
  11845. 'NRT' => 43200,
  11846. 'NST' => -12600,
  11847. 'NUT' => -39600,
  11848. 'NZDT' => 46800,
  11849. 'NZST' => 43200,
  11850. 'OMSST' => 25200,
  11851. 'OMST' => 21600,
  11852. 'PDT' => -25200,
  11853. 'PET' => -18000,
  11854. 'PETST' => 46800,
  11855. 'PETT' => 43200,
  11856. 'PGT' => 36000,
  11857. 'PHOT' => 46800,
  11858. 'PHT' => 28800,
  11859. 'PKT' => 18000,
  11860. 'PMDT' => -7200,
  11861. 'PMST' => -10800,
  11862. 'PONT' => 39600,
  11863. 'PST' => -28800,
  11864. 'PWT' => 32400,
  11865. 'PYST' => -10800,
  11866. 'PYT' => -14400,
  11867. 'RET' => 14400,
  11868. 'ROTT' => -10800,
  11869. 'SAMST' => 18000,
  11870. 'SAMT' => 14400,
  11871. 'SAST' => 7200,
  11872. 'SBT' => 39600,
  11873. 'SCDT' => 46800,
  11874. 'SCST' => 43200,
  11875. 'SCT' => 14400,
  11876. 'SEST' => 3600,
  11877. 'SGT' => 28800,
  11878. 'SIT' => 28800,
  11879. 'SRT' => -10800,
  11880. 'SST' => -39600,
  11881. 'SYST' => 10800,
  11882. 'SYT' => 7200,
  11883. 'TFT' => 18000,
  11884. 'THAT' => -36000,
  11885. 'TJT' => 18000,
  11886. 'TKT' => -36000,
  11887. 'TMT' => 18000,
  11888. 'TOT' => 46800,
  11889. 'TPT' => 32400,
  11890. 'TRUT' => 36000,
  11891. 'TVT' => 43200,
  11892. 'TWT' => 28800,
  11893. 'UYST' => -7200,
  11894. 'UYT' => -10800,
  11895. 'UZT' => 18000,
  11896. 'VET' => -14400,
  11897. 'VLAST' => 39600,
  11898. 'VLAT' => 36000,
  11899. 'VOST' => 21600,
  11900. 'VUT' => 39600,
  11901. 'WAST' => 7200,
  11902. 'WAT' => 3600,
  11903. 'WDT' => 32400,
  11904. 'WEST' => 3600,
  11905. 'WFT' => 43200,
  11906. 'WIB' => 25200,
  11907. 'WIT' => 32400,
  11908. 'WITA' => 28800,
  11909. 'WKST' => 18000,
  11910. 'WST' => 28800,
  11911. 'YAKST' => 36000,
  11912. 'YAKT' => 32400,
  11913. 'YAPT' => 36000,
  11914. 'YEKST' => 21600,
  11915. 'YEKT' => 18000,
  11916. );
  11917. /**
  11918. * Cached PCRE for SimplePie_Parse_Date::$day
  11919. *
  11920. * @access protected
  11921. * @var string
  11922. */
  11923. var $day_pcre;
  11924. /**
  11925. * Cached PCRE for SimplePie_Parse_Date::$month
  11926. *
  11927. * @access protected
  11928. * @var string
  11929. */
  11930. var $month_pcre;
  11931. /**
  11932. * Array of user-added callback methods
  11933. *
  11934. * @access private
  11935. * @var array
  11936. */
  11937. var $built_in = array();
  11938. /**
  11939. * Array of user-added callback methods
  11940. *
  11941. * @access private
  11942. * @var array
  11943. */
  11944. var $user = array();
  11945. /**
  11946. * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  11947. * self::month_pcre, and self::built_in
  11948. *
  11949. * @access private
  11950. */
  11951. public function __construct()
  11952. {
  11953. $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  11954. $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  11955. static $cache;
  11956. if (!isset($cache[get_class($this)]))
  11957. {
  11958. $all_methods = get_class_methods($this);
  11959. foreach ($all_methods as $method)
  11960. {
  11961. if (strtolower(substr($method, 0, 5)) === 'date_')
  11962. {
  11963. $cache[get_class($this)][] = $method;
  11964. }
  11965. }
  11966. }
  11967. foreach ($cache[get_class($this)] as $method)
  11968. {
  11969. $this->built_in[] = $method;
  11970. }
  11971. }
  11972. /**
  11973. * Get the object
  11974. *
  11975. * @access public
  11976. */
  11977. public static function get()
  11978. {
  11979. static $object;
  11980. if (!$object)
  11981. {
  11982. $object = new SimplePie_Parse_Date;
  11983. }
  11984. return $object;
  11985. }
  11986. /**
  11987. * Parse a date
  11988. *
  11989. * @final
  11990. * @access public
  11991. * @param string $date Date to parse
  11992. * @return int Timestamp corresponding to date string, or false on failure
  11993. */
  11994. public function parse($date)
  11995. {
  11996. foreach ($this->user as $method)
  11997. {
  11998. if (($returned = call_user_func($method, $date)) !== false)
  11999. {
  12000. return $returned;
  12001. }
  12002. }
  12003. foreach ($this->built_in as $method)
  12004. {
  12005. if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
  12006. {
  12007. return $returned;
  12008. }
  12009. }
  12010. return false;
  12011. }
  12012. /**
  12013. * Add a callback method to parse a date
  12014. *
  12015. * @final
  12016. * @access public
  12017. * @param callback $callback
  12018. */
  12019. public function add_callback($callback)
  12020. {
  12021. if (is_callable($callback))
  12022. {
  12023. $this->user[] = $callback;
  12024. }
  12025. else
  12026. {
  12027. trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  12028. }
  12029. }
  12030. /**
  12031. * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  12032. * well as allowing any of upper or lower case "T", horizontal tabs, or
  12033. * spaces to be used as the time seperator (including more than one))
  12034. *
  12035. * @access protected
  12036. * @return int Timestamp
  12037. */
  12038. public function date_w3cdtf($date)
  12039. {
  12040. static $pcre;
  12041. if (!$pcre)
  12042. {
  12043. $year = '([0-9]{4})';
  12044. $month = $day = $hour = $minute = $second = '([0-9]{2})';
  12045. $decimal = '([0-9]*)';
  12046. $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  12047. $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  12048. }
  12049. if (preg_match($pcre, $date, $match))
  12050. {
  12051. /*
  12052. Capturing subpatterns:
  12053. 1: Year
  12054. 2: Month
  12055. 3: Day
  12056. 4: Hour
  12057. 5: Minute
  12058. 6: Second
  12059. 7: Decimal fraction of a second
  12060. 8: Zulu
  12061. 9: Timezone ±
  12062. 10: Timezone hours
  12063. 11: Timezone minutes
  12064. */
  12065. // Fill in empty matches
  12066. for ($i = count($match); $i <= 3; $i++)
  12067. {
  12068. $match[$i] = '1';
  12069. }
  12070. for ($i = count($match); $i <= 7; $i++)
  12071. {
  12072. $match[$i] = '0';
  12073. }
  12074. // Numeric timezone
  12075. if (isset($match[9]) && $match[9] !== '')
  12076. {
  12077. $timezone = $match[10] * 3600;
  12078. $timezone += $match[11] * 60;
  12079. if ($match[9] === '-')
  12080. {
  12081. $timezone = 0 - $timezone;
  12082. }
  12083. }
  12084. else
  12085. {
  12086. $timezone = 0;
  12087. }
  12088. // Convert the number of seconds to an integer, taking decimals into account
  12089. $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  12090. return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  12091. }
  12092. else
  12093. {
  12094. return false;
  12095. }
  12096. }
  12097. /**
  12098. * Remove RFC822 comments
  12099. *
  12100. * @access protected
  12101. * @param string $data Data to strip comments from
  12102. * @return string Comment stripped string
  12103. */
  12104. public function remove_rfc2822_comments($string)
  12105. {
  12106. $string = (string) $string;
  12107. $position = 0;
  12108. $length = strlen($string);
  12109. $depth = 0;
  12110. $output = '';
  12111. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  12112. {
  12113. $output .= substr($string, $position, $pos - $position);
  12114. $position = $pos + 1;
  12115. if ($string[$pos - 1] !== '\\')
  12116. {
  12117. $depth++;
  12118. while ($depth && $position < $length)
  12119. {
  12120. $position += strcspn($string, '()', $position);
  12121. if ($string[$position - 1] === '\\')
  12122. {
  12123. $position++;
  12124. continue;
  12125. }
  12126. elseif (isset($string[$position]))
  12127. {
  12128. switch ($string[$position])
  12129. {
  12130. case '(':
  12131. $depth++;
  12132. break;
  12133. case ')':
  12134. $depth--;
  12135. break;
  12136. }
  12137. $position++;
  12138. }
  12139. else
  12140. {
  12141. break;
  12142. }
  12143. }
  12144. }
  12145. else
  12146. {
  12147. $output .= '(';
  12148. }
  12149. }
  12150. $output .= substr($string, $position);
  12151. return $output;
  12152. }
  12153. /**
  12154. * Parse RFC2822's date format
  12155. *
  12156. * @access protected
  12157. * @return int Timestamp
  12158. */
  12159. public function date_rfc2822($date)
  12160. {
  12161. static $pcre;
  12162. if (!$pcre)
  12163. {
  12164. $wsp = '[\x09\x20]';
  12165. $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  12166. $optional_fws = $fws . '?';
  12167. $day_name = $this->day_pcre;
  12168. $month = $this->month_pcre;
  12169. $day = '([0-9]{1,2})';
  12170. $hour = $minute = $second = '([0-9]{2})';
  12171. $year = '([0-9]{2,4})';
  12172. $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  12173. $character_zone = '([A-Z]{1,5})';
  12174. $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  12175. $pcre = '/(?:' . $optional_fws . $day_name . $optional_fws . ',)?' . $optional_fws . $day . $fws . $month . $fws . $year . $fws . $hour . $optional_fws . ':' . $optional_fws . $minute . '(?:' . $optional_fws . ':' . $optional_fws . $second . ')?' . $fws . $zone . '/i';
  12176. }
  12177. if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  12178. {
  12179. /*
  12180. Capturing subpatterns:
  12181. 1: Day name
  12182. 2: Day
  12183. 3: Month
  12184. 4: Year
  12185. 5: Hour
  12186. 6: Minute
  12187. 7: Second
  12188. 8: Timezone ±
  12189. 9: Timezone hours
  12190. 10: Timezone minutes
  12191. 11: Alphabetic timezone
  12192. */
  12193. // Find the month number
  12194. $month = $this->month[strtolower($match[3])];
  12195. // Numeric timezone
  12196. if ($match[8] !== '')
  12197. {
  12198. $timezone = $match[9] * 3600;
  12199. $timezone += $match[10] * 60;
  12200. if ($match[8] === '-')
  12201. {
  12202. $timezone = 0 - $timezone;
  12203. }
  12204. }
  12205. // Character timezone
  12206. elseif (isset($this->timezone[strtoupper($match[11])]))
  12207. {
  12208. $timezone = $this->timezone[strtoupper($match[11])];
  12209. }
  12210. // Assume everything else to be -0000
  12211. else
  12212. {
  12213. $timezone = 0;
  12214. }
  12215. // Deal with 2/3 digit years
  12216. if ($match[4] < 50)
  12217. {
  12218. $match[4] += 2000;
  12219. }
  12220. elseif ($match[4] < 1000)
  12221. {
  12222. $match[4] += 1900;
  12223. }
  12224. // Second is optional, if it is empty set it to zero
  12225. if ($match[7] !== '')
  12226. {
  12227. $second = $match[7];
  12228. }
  12229. else
  12230. {
  12231. $second = 0;
  12232. }
  12233. return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  12234. }
  12235. else
  12236. {
  12237. return false;
  12238. }
  12239. }
  12240. /**
  12241. * Parse RFC850's date format
  12242. *
  12243. * @access protected
  12244. * @return int Timestamp
  12245. */
  12246. public function date_rfc850($date)
  12247. {
  12248. static $pcre;
  12249. if (!$pcre)
  12250. {
  12251. $space = '[\x09\x20]+';
  12252. $day_name = $this->day_pcre;
  12253. $month = $this->month_pcre;
  12254. $day = '([0-9]{1,2})';
  12255. $year = $hour = $minute = $second = '([0-9]{2})';
  12256. $zone = '([A-Z]{1,5})';
  12257. $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  12258. }
  12259. if (preg_match($pcre, $date, $match))
  12260. {
  12261. /*
  12262. Capturing subpatterns:
  12263. 1: Day name
  12264. 2: Day
  12265. 3: Month
  12266. 4: Year
  12267. 5: Hour
  12268. 6: Minute
  12269. 7: Second
  12270. 8: Timezone
  12271. */
  12272. // Month
  12273. $month = $this->month[strtolower($match[3])];
  12274. // Character timezone
  12275. if (isset($this->timezone[strtoupper($match[8])]))
  12276. {
  12277. $timezone = $this->timezone[strtoupper($match[8])];
  12278. }
  12279. // Assume everything else to be -0000
  12280. else
  12281. {
  12282. $timezone = 0;
  12283. }
  12284. // Deal with 2 digit year
  12285. if ($match[4] < 50)
  12286. {
  12287. $match[4] += 2000;
  12288. }
  12289. else
  12290. {
  12291. $match[4] += 1900;
  12292. }
  12293. return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  12294. }
  12295. else
  12296. {
  12297. return false;
  12298. }
  12299. }
  12300. /**
  12301. * Parse C99's asctime()'s date format
  12302. *
  12303. * @access protected
  12304. * @return int Timestamp
  12305. */
  12306. public function date_asctime($date)
  12307. {
  12308. static $pcre;
  12309. if (!$pcre)
  12310. {
  12311. $space = '[\x09\x20]+';
  12312. $wday_name = $this->day_pcre;
  12313. $mon_name = $this->month_pcre;
  12314. $day = '([0-9]{1,2})';
  12315. $hour = $sec = $min = '([0-9]{2})';
  12316. $year = '([0-9]{4})';
  12317. $terminator = '\x0A?\x00?';
  12318. $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  12319. }
  12320. if (preg_match($pcre, $date, $match))
  12321. {
  12322. /*
  12323. Capturing subpatterns:
  12324. 1: Day name
  12325. 2: Month
  12326. 3: Day
  12327. 4: Hour
  12328. 5: Minute
  12329. 6: Second
  12330. 7: Year
  12331. */
  12332. $month = $this->month[strtolower($match[2])];
  12333. return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  12334. }
  12335. else
  12336. {
  12337. return false;
  12338. }
  12339. }
  12340. /**
  12341. * Parse dates using strtotime()
  12342. *
  12343. * @access protected
  12344. * @return int Timestamp
  12345. */
  12346. public function date_strtotime($date)
  12347. {
  12348. $strtotime = strtotime($date);
  12349. if ($strtotime === -1 || $strtotime === false)
  12350. {
  12351. return false;
  12352. }
  12353. else
  12354. {
  12355. return $strtotime;
  12356. }
  12357. }
  12358. }
  12359. class SimplePie_Parser
  12360. {
  12361. var $error_code;
  12362. var $error_string;
  12363. var $current_line;
  12364. var $current_column;
  12365. var $current_byte;
  12366. var $separator = ' ';
  12367. var $namespace = array('');
  12368. var $element = array('');
  12369. var $xml_base = array('');
  12370. var $xml_base_explicit = array(false);
  12371. var $xml_lang = array('');
  12372. var $data = array();
  12373. var $datas = array(array());
  12374. var $current_xhtml_construct = -1;
  12375. var $encoding;
  12376. public function parse(&$data, $encoding)
  12377. {
  12378. // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
  12379. if (strtoupper($encoding) === 'US-ASCII')
  12380. {
  12381. $this->encoding = 'UTF-8';
  12382. }
  12383. else
  12384. {
  12385. $this->encoding = $encoding;
  12386. }
  12387. // Strip BOM:
  12388. // UTF-32 Big Endian BOM
  12389. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  12390. {
  12391. $data = substr($data, 4);
  12392. }
  12393. // UTF-32 Little Endian BOM
  12394. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  12395. {
  12396. $data = substr($data, 4);
  12397. }
  12398. // UTF-16 Big Endian BOM
  12399. elseif (substr($data, 0, 2) === "\xFE\xFF")
  12400. {
  12401. $data = substr($data, 2);
  12402. }
  12403. // UTF-16 Little Endian BOM
  12404. elseif (substr($data, 0, 2) === "\xFF\xFE")
  12405. {
  12406. $data = substr($data, 2);
  12407. }
  12408. // UTF-8 BOM
  12409. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  12410. {
  12411. $data = substr($data, 3);
  12412. }
  12413. if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
  12414. {
  12415. $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  12416. if ($declaration->parse())
  12417. {
  12418. $data = substr($data, $pos + 2);
  12419. $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
  12420. }
  12421. else
  12422. {
  12423. $this->error_string = 'SimplePie bug! Please report this!';
  12424. return false;
  12425. }
  12426. }
  12427. $return = true;
  12428. static $xml_is_sane = null;
  12429. if ($xml_is_sane === null)
  12430. {
  12431. $parser_check = xml_parser_create();
  12432. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  12433. xml_parser_free($parser_check);
  12434. $xml_is_sane = isset($values[0]['value']);
  12435. }
  12436. // Create the parser
  12437. if ($xml_is_sane)
  12438. {
  12439. $xml = xml_parser_create_ns($this->encoding, $this->separator);
  12440. xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
  12441. xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
  12442. xml_set_object($xml, $this);
  12443. xml_set_character_data_handler($xml, 'cdata');
  12444. xml_set_element_handler($xml, 'tag_open', 'tag_close');
  12445. // Parse!
  12446. if (!xml_parse($xml, $data, true))
  12447. {
  12448. $this->error_code = xml_get_error_code($xml);
  12449. $this->error_string = xml_error_string($this->error_code);
  12450. $return = false;
  12451. }
  12452. $this->current_line = xml_get_current_line_number($xml);
  12453. $this->current_column = xml_get_current_column_number($xml);
  12454. $this->current_byte = xml_get_current_byte_index($xml);
  12455. xml_parser_free($xml);
  12456. return $return;
  12457. }
  12458. else
  12459. {
  12460. libxml_clear_errors();
  12461. $xml = new XMLReader();
  12462. $xml->xml($data);
  12463. while (@$xml->read())
  12464. {
  12465. switch ($xml->nodeType)
  12466. {
  12467. case constant('XMLReader::END_ELEMENT'):
  12468. if ($xml->namespaceURI !== '')
  12469. {
  12470. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  12471. }
  12472. else
  12473. {
  12474. $tagName = $xml->localName;
  12475. }
  12476. $this->tag_close(null, $tagName);
  12477. break;
  12478. case constant('XMLReader::ELEMENT'):
  12479. $empty = $xml->isEmptyElement;
  12480. if ($xml->namespaceURI !== '')
  12481. {
  12482. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  12483. }
  12484. else
  12485. {
  12486. $tagName = $xml->localName;
  12487. }
  12488. $attributes = array();
  12489. while ($xml->moveToNextAttribute())
  12490. {
  12491. if ($xml->namespaceURI !== '')
  12492. {
  12493. $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
  12494. }
  12495. else
  12496. {
  12497. $attrName = $xml->localName;
  12498. }
  12499. $attributes[$attrName] = $xml->value;
  12500. }
  12501. $this->tag_open(null, $tagName, $attributes);
  12502. if ($empty)
  12503. {
  12504. $this->tag_close(null, $tagName);
  12505. }
  12506. break;
  12507. case constant('XMLReader::TEXT'):
  12508. case constant('XMLReader::CDATA'):
  12509. $this->cdata(null, $xml->value);
  12510. break;
  12511. }
  12512. }
  12513. if ($error = libxml_get_last_error())
  12514. {
  12515. $this->error_code = $error->code;
  12516. $this->error_string = $error->message;
  12517. $this->current_line = $error->line;
  12518. $this->current_column = $error->column;
  12519. return false;
  12520. }
  12521. else
  12522. {
  12523. return true;
  12524. }
  12525. }
  12526. }
  12527. public function get_error_code()
  12528. {
  12529. return $this->error_code;
  12530. }
  12531. public function get_error_string()
  12532. {
  12533. return $this->error_string;
  12534. }
  12535. public function get_current_line()
  12536. {
  12537. return $this->current_line;
  12538. }
  12539. public function get_current_column()
  12540. {
  12541. return $this->current_column;
  12542. }
  12543. public function get_current_byte()
  12544. {
  12545. return $this->current_byte;
  12546. }
  12547. public function get_data()
  12548. {
  12549. return $this->data;
  12550. }
  12551. public function tag_open($parser, $tag, $attributes)
  12552. {
  12553. list($this->namespace[], $this->element[]) = $this->split_ns($tag);
  12554. $attribs = array();
  12555. foreach ($attributes as $name => $value)
  12556. {
  12557. list($attrib_namespace, $attribute) = $this->split_ns($name);
  12558. $attribs[$attrib_namespace][$attribute] = $value;
  12559. }
  12560. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
  12561. {
  12562. $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
  12563. $this->xml_base_explicit[] = true;
  12564. }
  12565. else
  12566. {
  12567. $this->xml_base[] = end($this->xml_base);
  12568. $this->xml_base_explicit[] = end($this->xml_base_explicit);
  12569. }
  12570. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
  12571. {
  12572. $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
  12573. }
  12574. else
  12575. {
  12576. $this->xml_lang[] = end($this->xml_lang);
  12577. }
  12578. if ($this->current_xhtml_construct >= 0)
  12579. {
  12580. $this->current_xhtml_construct++;
  12581. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
  12582. {
  12583. $this->data['data'] .= '<' . end($this->element);
  12584. if (isset($attribs['']))
  12585. {
  12586. foreach ($attribs[''] as $name => $value)
  12587. {
  12588. $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
  12589. }
  12590. }
  12591. $this->data['data'] .= '>';
  12592. }
  12593. }
  12594. else
  12595. {
  12596. $this->datas[] =& $this->data;
  12597. $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
  12598. $this->data = array('data' => '', 'attribs' => $attribs, 'xml_base' => end($this->xml_base), 'xml_base_explicit' => end($this->xml_base_explicit), 'xml_lang' => end($this->xml_lang));
  12599. if ((end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_03 && in_array(end($this->element), array('title', 'tagline', 'copyright', 'info', 'summary', 'content')) && isset($attribs['']['mode']) && $attribs['']['mode'] === 'xml')
  12600. || (end($this->namespace) === SIMPLEPIE_NAMESPACE_ATOM_10 && in_array(end($this->element), array('rights', 'subtitle', 'summary', 'info', 'title', 'content')) && isset($attribs['']['type']) && $attribs['']['type'] === 'xhtml'))
  12601. {
  12602. $this->current_xhtml_construct = 0;
  12603. }
  12604. }
  12605. }
  12606. public function cdata($parser, $cdata)
  12607. {
  12608. if ($this->current_xhtml_construct >= 0)
  12609. {
  12610. $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
  12611. }
  12612. else
  12613. {
  12614. $this->data['data'] .= $cdata;
  12615. }
  12616. }
  12617. public function tag_close($parser, $tag)
  12618. {
  12619. if ($this->current_xhtml_construct >= 0)
  12620. {
  12621. $this->current_xhtml_construct--;
  12622. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML && !in_array(end($this->element), array('area', 'base', 'basefont', 'br', 'col', 'frame', 'hr', 'img', 'input', 'isindex', 'link', 'meta', 'param')))
  12623. {
  12624. $this->data['data'] .= '</' . end($this->element) . '>';
  12625. }
  12626. }
  12627. if ($this->current_xhtml_construct === -1)
  12628. {
  12629. $this->data =& $this->datas[count($this->datas) - 1];
  12630. array_pop($this->datas);
  12631. }
  12632. array_pop($this->element);
  12633. array_pop($this->namespace);
  12634. array_pop($this->xml_base);
  12635. array_pop($this->xml_base_explicit);
  12636. array_pop($this->xml_lang);
  12637. }
  12638. public function split_ns($string)
  12639. {
  12640. static $cache = array();
  12641. if (!isset($cache[$string]))
  12642. {
  12643. if ($pos = strpos($string, $this->separator))
  12644. {
  12645. static $separator_length;
  12646. if (!$separator_length)
  12647. {
  12648. $separator_length = strlen($this->separator);
  12649. }
  12650. $namespace = substr($string, 0, $pos);
  12651. $local_name = substr($string, $pos + $separator_length);
  12652. if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
  12653. {
  12654. $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
  12655. }
  12656. // Normalize the Media RSS namespaces
  12657. if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
  12658. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
  12659. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
  12660. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
  12661. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )
  12662. {
  12663. $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
  12664. }
  12665. $cache[$string] = array($namespace, $local_name);
  12666. }
  12667. else
  12668. {
  12669. $cache[$string] = array('', $string);
  12670. }
  12671. }
  12672. return $cache[$string];
  12673. }
  12674. }
  12675. class SimplePie_Rating
  12676. {
  12677. var $scheme;
  12678. var $value;
  12679. // Constructor, used to input the data
  12680. public function __construct($scheme = null, $value = null)
  12681. {
  12682. $this->scheme = $scheme;
  12683. $this->value = $value;
  12684. }
  12685. public function __toString()
  12686. {
  12687. // There is no $this->data here
  12688. return md5(serialize($this));
  12689. }
  12690. public function get_scheme()
  12691. {
  12692. if ($this->scheme !== null)
  12693. {
  12694. return $this->scheme;
  12695. }
  12696. else
  12697. {
  12698. return null;
  12699. }
  12700. }
  12701. public function get_value()
  12702. {
  12703. if ($this->value !== null)
  12704. {
  12705. return $this->value;
  12706. }
  12707. else
  12708. {
  12709. return null;
  12710. }
  12711. }
  12712. }
  12713. class SimplePie_Restriction
  12714. {
  12715. var $relationship;
  12716. var $type;
  12717. var $value;
  12718. // Constructor, used to input the data
  12719. public function __construct($relationship = null, $type = null, $value = null)
  12720. {
  12721. $this->relationship = $relationship;
  12722. $this->type = $type;
  12723. $this->value = $value;
  12724. }
  12725. public function __toString()
  12726. {
  12727. // There is no $this->data here
  12728. return md5(serialize($this));
  12729. }
  12730. public function get_relationship()
  12731. {
  12732. if ($this->relationship !== null)
  12733. {
  12734. return $this->relationship;
  12735. }
  12736. else
  12737. {
  12738. return null;
  12739. }
  12740. }
  12741. public function get_type()
  12742. {
  12743. if ($this->type !== null)
  12744. {
  12745. return $this->type;
  12746. }
  12747. else
  12748. {
  12749. return null;
  12750. }
  12751. }
  12752. public function get_value()
  12753. {
  12754. if ($this->value !== null)
  12755. {
  12756. return $this->value;
  12757. }
  12758. else
  12759. {
  12760. return null;
  12761. }
  12762. }
  12763. }
  12764. /**
  12765. * @todo Move to using an actual HTML parser (this will allow tags to be properly stripped, and to switch between HTML and XHTML), this will also make it easier to shorten a string while preserving HTML tags
  12766. */
  12767. class SimplePie_Sanitize
  12768. {
  12769. // Private vars
  12770. var $base;
  12771. // Options
  12772. var $remove_div = true;
  12773. var $image_handler = '';
  12774. var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  12775. var $encode_instead_of_strip = false;
  12776. var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  12777. var $strip_comments = false;
  12778. var $output_encoding = 'UTF-8';
  12779. var $enable_cache = true;
  12780. var $cache_location = './cache';
  12781. var $cache_name_function = 'md5';
  12782. var $cache_class = 'SimplePie_Cache';
  12783. var $file_class = 'SimplePie_File';
  12784. var $timeout = 10;
  12785. var $useragent = '';
  12786. var $force_fsockopen = false;
  12787. var $replace_url_attributes = array(
  12788. 'a' => 'href',
  12789. 'area' => 'href',
  12790. 'blockquote' => 'cite',
  12791. 'del' => 'cite',
  12792. 'form' => 'action',
  12793. 'img' => array('longdesc', 'src'),
  12794. 'input' => 'src',
  12795. 'ins' => 'cite',
  12796. 'q' => 'cite'
  12797. );
  12798. public function remove_div($enable = true)
  12799. {
  12800. $this->remove_div = (bool) $enable;
  12801. }
  12802. public function set_image_handler($page = false)
  12803. {
  12804. if ($page)
  12805. {
  12806. $this->image_handler = (string) $page;
  12807. }
  12808. else
  12809. {
  12810. $this->image_handler = false;
  12811. }
  12812. }
  12813. public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
  12814. {
  12815. if (isset($enable_cache))
  12816. {
  12817. $this->enable_cache = (bool) $enable_cache;
  12818. }
  12819. if ($cache_location)
  12820. {
  12821. $this->cache_location = (string) $cache_location;
  12822. }
  12823. if ($cache_name_function)
  12824. {
  12825. $this->cache_name_function = (string) $cache_name_function;
  12826. }
  12827. if ($cache_class)
  12828. {
  12829. $this->cache_class = (string) $cache_class;
  12830. }
  12831. }
  12832. public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
  12833. {
  12834. if ($file_class)
  12835. {
  12836. $this->file_class = (string) $file_class;
  12837. }
  12838. if ($timeout)
  12839. {
  12840. $this->timeout = (string) $timeout;
  12841. }
  12842. if ($useragent)
  12843. {
  12844. $this->useragent = (string) $useragent;
  12845. }
  12846. if ($force_fsockopen)
  12847. {
  12848. $this->force_fsockopen = (string) $force_fsockopen;
  12849. }
  12850. }
  12851. public function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
  12852. {
  12853. if ($tags)
  12854. {
  12855. if (is_array($tags))
  12856. {
  12857. $this->strip_htmltags = $tags;
  12858. }
  12859. else
  12860. {
  12861. $this->strip_htmltags = explode(',', $tags);
  12862. }
  12863. }
  12864. else
  12865. {
  12866. $this->strip_htmltags = false;
  12867. }
  12868. }
  12869. public function encode_instead_of_strip($encode = false)
  12870. {
  12871. $this->encode_instead_of_strip = (bool) $encode;
  12872. }
  12873. public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
  12874. {
  12875. if ($attribs)
  12876. {
  12877. if (is_array($attribs))
  12878. {
  12879. $this->strip_attributes = $attribs;
  12880. }
  12881. else
  12882. {
  12883. $this->strip_attributes = explode(',', $attribs);
  12884. }
  12885. }
  12886. else
  12887. {
  12888. $this->strip_attributes = false;
  12889. }
  12890. }
  12891. public function strip_comments($strip = false)
  12892. {
  12893. $this->strip_comments = (bool) $strip;
  12894. }
  12895. public function set_output_encoding($encoding = 'UTF-8')
  12896. {
  12897. $this->output_encoding = (string) $encoding;
  12898. }
  12899. /**
  12900. * Set element/attribute key/value pairs of HTML attributes
  12901. * containing URLs that need to be resolved relative to the feed
  12902. *
  12903. * @access public
  12904. * @since 1.0
  12905. * @param array $element_attribute Element/attribute key/value pairs
  12906. */
  12907. public function set_url_replacements($element_attribute = array('a' => 'href', 'area' => 'href', 'blockquote' => 'cite', 'del' => 'cite', 'form' => 'action', 'img' => array('longdesc', 'src'), 'input' => 'src', 'ins' => 'cite', 'q' => 'cite'))
  12908. {
  12909. $this->replace_url_attributes = (array) $element_attribute;
  12910. }
  12911. public function sanitize($data, $type, $base = '')
  12912. {
  12913. $data = trim($data);
  12914. if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
  12915. {
  12916. if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
  12917. {
  12918. if (preg_match('/(&(#(x[0-9a-fA-F]+|[0-9]+)|[a-zA-Z0-9]+)|<\/[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>)/', $data))
  12919. {
  12920. $type |= SIMPLEPIE_CONSTRUCT_HTML;
  12921. }
  12922. else
  12923. {
  12924. $type |= SIMPLEPIE_CONSTRUCT_TEXT;
  12925. }
  12926. }
  12927. if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
  12928. {
  12929. $data = base64_decode($data);
  12930. }
  12931. if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
  12932. {
  12933. if ($this->remove_div)
  12934. {
  12935. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
  12936. $data = preg_replace('/<\/div>$/', '', $data);
  12937. }
  12938. else
  12939. {
  12940. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
  12941. }
  12942. }
  12943. if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
  12944. {
  12945. // Strip comments
  12946. if ($this->strip_comments)
  12947. {
  12948. $data = SimplePie_Misc::strip_comments($data);
  12949. }
  12950. // Strip out HTML tags and attributes that might cause various security problems.
  12951. // Based on recommendations by Mark Pilgrim at:
  12952. // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
  12953. if ($this->strip_htmltags)
  12954. {
  12955. foreach ($this->strip_htmltags as $tag)
  12956. {
  12957. $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
  12958. while (preg_match($pcre, $data))
  12959. {
  12960. $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
  12961. }
  12962. }
  12963. }
  12964. if ($this->strip_attributes)
  12965. {
  12966. foreach ($this->strip_attributes as $attrib)
  12967. {
  12968. $data = preg_replace('/(<[A-Za-z][^\x09\x0A\x0B\x0C\x0D\x20\x2F\x3E]*)' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . trim($attrib) . '(?:\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'|(?:[^\x09\x0A\x0B\x0C\x0D\x20\x22\x27\x3E][^\x09\x0A\x0B\x0C\x0D\x20\x3E]*)?))?' . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>/', '\1\2\3>', $data);
  12969. }
  12970. }
  12971. // Replace relative URLs
  12972. $this->base = $base;
  12973. foreach ($this->replace_url_attributes as $element => $attributes)
  12974. {
  12975. $data = $this->replace_urls($data, $element, $attributes);
  12976. }
  12977. // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
  12978. if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
  12979. {
  12980. $images = SimplePie_Misc::get_element('img', $data);
  12981. foreach ($images as $img)
  12982. {
  12983. if (isset($img['attribs']['src']['data']))
  12984. {
  12985. $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
  12986. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
  12987. if ($cache->load())
  12988. {
  12989. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  12990. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  12991. }
  12992. else
  12993. {
  12994. $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
  12995. $headers = $file->headers;
  12996. if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  12997. {
  12998. if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
  12999. {
  13000. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  13001. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  13002. }
  13003. else
  13004. {
  13005. trigger_error("$this->cache_location is not writeable. Make sure you've set the correct relative or absolute path, and that the location is server-writable.", E_USER_WARNING);
  13006. }
  13007. }
  13008. }
  13009. }
  13010. }
  13011. }
  13012. // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
  13013. $data = trim($data);
  13014. }
  13015. if ($type & SIMPLEPIE_CONSTRUCT_IRI)
  13016. {
  13017. $data = SimplePie_Misc::absolutize_url($data, $base);
  13018. }
  13019. if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
  13020. {
  13021. $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
  13022. }
  13023. if ($this->output_encoding !== 'UTF-8')
  13024. {
  13025. $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
  13026. }
  13027. }
  13028. return $data;
  13029. }
  13030. public function replace_urls($data, $tag, $attributes)
  13031. {
  13032. if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
  13033. {
  13034. $elements = SimplePie_Misc::get_element($tag, $data);
  13035. foreach ($elements as $element)
  13036. {
  13037. if (is_array($attributes))
  13038. {
  13039. foreach ($attributes as $attribute)
  13040. {
  13041. if (isset($element['attribs'][$attribute]['data']))
  13042. {
  13043. $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
  13044. $new_element = SimplePie_Misc::element_implode($element);
  13045. $data = str_replace($element['full'], $new_element, $data);
  13046. $element['full'] = $new_element;
  13047. }
  13048. }
  13049. }
  13050. elseif (isset($element['attribs'][$attributes]['data']))
  13051. {
  13052. $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
  13053. $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
  13054. }
  13055. }
  13056. }
  13057. return $data;
  13058. }
  13059. public function do_strip_htmltags($match)
  13060. {
  13061. if ($this->encode_instead_of_strip)
  13062. {
  13063. if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13064. {
  13065. $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
  13066. $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
  13067. return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
  13068. }
  13069. else
  13070. {
  13071. return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
  13072. }
  13073. }
  13074. elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13075. {
  13076. return $match[4];
  13077. }
  13078. else
  13079. {
  13080. return '';
  13081. }
  13082. }
  13083. }
  13084. class SimplePie_Source
  13085. {
  13086. var $item;
  13087. var $data = array();
  13088. public function __construct($item, $data)
  13089. {
  13090. $this->item = $item;
  13091. $this->data = $data;
  13092. }
  13093. public function __toString()
  13094. {
  13095. return md5(serialize($this->data));
  13096. }
  13097. public function get_source_tags($namespace, $tag)
  13098. {
  13099. if (isset($this->data['child'][$namespace][$tag]))
  13100. {
  13101. return $this->data['child'][$namespace][$tag];
  13102. }
  13103. else
  13104. {
  13105. return null;
  13106. }
  13107. }
  13108. public function get_base($element = array())
  13109. {
  13110. return $this->item->get_base($element);
  13111. }
  13112. public function sanitize($data, $type, $base = '')
  13113. {
  13114. return $this->item->sanitize($data, $type, $base);
  13115. }
  13116. public function get_item()
  13117. {
  13118. return $this->item;
  13119. }
  13120. public function get_title()
  13121. {
  13122. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  13123. {
  13124. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13125. }
  13126. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  13127. {
  13128. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13129. }
  13130. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  13131. {
  13132. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13133. }
  13134. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  13135. {
  13136. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13137. }
  13138. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  13139. {
  13140. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13141. }
  13142. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  13143. {
  13144. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13145. }
  13146. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  13147. {
  13148. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13149. }
  13150. else
  13151. {
  13152. return null;
  13153. }
  13154. }
  13155. public function get_category($key = 0)
  13156. {
  13157. $categories = $this->get_categories();
  13158. if (isset($categories[$key]))
  13159. {
  13160. return $categories[$key];
  13161. }
  13162. else
  13163. {
  13164. return null;
  13165. }
  13166. }
  13167. public function get_categories()
  13168. {
  13169. $categories = array();
  13170. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  13171. {
  13172. $term = null;
  13173. $scheme = null;
  13174. $label = null;
  13175. if (isset($category['attribs']['']['term']))
  13176. {
  13177. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  13178. }
  13179. if (isset($category['attribs']['']['scheme']))
  13180. {
  13181. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  13182. }
  13183. if (isset($category['attribs']['']['label']))
  13184. {
  13185. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  13186. }
  13187. $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
  13188. }
  13189. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  13190. {
  13191. // This is really the label, but keep this as the term also for BC.
  13192. // Label will also work on retrieving because that falls back to term.
  13193. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13194. if (isset($category['attribs']['']['domain']))
  13195. {
  13196. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  13197. }
  13198. else
  13199. {
  13200. $scheme = null;
  13201. }
  13202. $categories[] = new $this->item->feed->category_class($term, $scheme, null);
  13203. }
  13204. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  13205. {
  13206. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  13207. }
  13208. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  13209. {
  13210. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  13211. }
  13212. if (!empty($categories))
  13213. {
  13214. return SimplePie_Misc::array_unique($categories);
  13215. }
  13216. else
  13217. {
  13218. return null;
  13219. }
  13220. }
  13221. public function get_author($key = 0)
  13222. {
  13223. $authors = $this->get_authors();
  13224. if (isset($authors[$key]))
  13225. {
  13226. return $authors[$key];
  13227. }
  13228. else
  13229. {
  13230. return null;
  13231. }
  13232. }
  13233. public function get_authors()
  13234. {
  13235. $authors = array();
  13236. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  13237. {
  13238. $name = null;
  13239. $uri = null;
  13240. $email = null;
  13241. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  13242. {
  13243. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13244. }
  13245. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  13246. {
  13247. $uri = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  13248. }
  13249. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  13250. {
  13251. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13252. }
  13253. if ($name !== null || $email !== null || $uri !== null)
  13254. {
  13255. $authors[] = new $this->item->feed->author_class($name, $uri, $email);
  13256. }
  13257. }
  13258. if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  13259. {
  13260. $name = null;
  13261. $url = null;
  13262. $email = null;
  13263. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  13264. {
  13265. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13266. }
  13267. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  13268. {
  13269. $url = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  13270. }
  13271. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  13272. {
  13273. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13274. }
  13275. if ($name !== null || $email !== null || $url !== null)
  13276. {
  13277. $authors[] = new $this->item->feed->author_class($name, $url, $email);
  13278. }
  13279. }
  13280. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  13281. {
  13282. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  13283. }
  13284. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  13285. {
  13286. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  13287. }
  13288. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  13289. {
  13290. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  13291. }
  13292. if (!empty($authors))
  13293. {
  13294. return SimplePie_Misc::array_unique($authors);
  13295. }
  13296. else
  13297. {
  13298. return null;
  13299. }
  13300. }
  13301. public function get_contributor($key = 0)
  13302. {
  13303. $contributors = $this->get_contributors();
  13304. if (isset($contributors[$key]))
  13305. {
  13306. return $contributors[$key];
  13307. }
  13308. else
  13309. {
  13310. return null;
  13311. }
  13312. }
  13313. public function get_contributors()
  13314. {
  13315. $contributors = array();
  13316. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  13317. {
  13318. $name = null;
  13319. $uri = null;
  13320. $email = null;
  13321. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  13322. {
  13323. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13324. }
  13325. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  13326. {
  13327. $uri = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]));
  13328. }
  13329. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  13330. {
  13331. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13332. }
  13333. if ($name !== null || $email !== null || $uri !== null)
  13334. {
  13335. $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
  13336. }
  13337. }
  13338. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  13339. {
  13340. $name = null;
  13341. $url = null;
  13342. $email = null;
  13343. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  13344. {
  13345. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13346. }
  13347. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  13348. {
  13349. $url = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]));
  13350. }
  13351. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  13352. {
  13353. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13354. }
  13355. if ($name !== null || $email !== null || $url !== null)
  13356. {
  13357. $contributors[] = new $this->item->feed->author_class($name, $url, $email);
  13358. }
  13359. }
  13360. if (!empty($contributors))
  13361. {
  13362. return SimplePie_Misc::array_unique($contributors);
  13363. }
  13364. else
  13365. {
  13366. return null;
  13367. }
  13368. }
  13369. public function get_link($key = 0, $rel = 'alternate')
  13370. {
  13371. $links = $this->get_links($rel);
  13372. if (isset($links[$key]))
  13373. {
  13374. return $links[$key];
  13375. }
  13376. else
  13377. {
  13378. return null;
  13379. }
  13380. }
  13381. /**
  13382. * Added for parity between the parent-level and the item/entry-level.
  13383. */
  13384. public function get_permalink()
  13385. {
  13386. return $this->get_link(0);
  13387. }
  13388. public function get_links($rel = 'alternate')
  13389. {
  13390. if (!isset($this->data['links']))
  13391. {
  13392. $this->data['links'] = array();
  13393. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  13394. {
  13395. foreach ($links as $link)
  13396. {
  13397. if (isset($link['attribs']['']['href']))
  13398. {
  13399. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  13400. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  13401. }
  13402. }
  13403. }
  13404. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  13405. {
  13406. foreach ($links as $link)
  13407. {
  13408. if (isset($link['attribs']['']['href']))
  13409. {
  13410. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  13411. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  13412. }
  13413. }
  13414. }
  13415. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  13416. {
  13417. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  13418. }
  13419. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  13420. {
  13421. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  13422. }
  13423. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  13424. {
  13425. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  13426. }
  13427. $keys = array_keys($this->data['links']);
  13428. foreach ($keys as $key)
  13429. {
  13430. if (SimplePie_Misc::is_isegment_nz_nc($key))
  13431. {
  13432. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  13433. {
  13434. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  13435. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  13436. }
  13437. else
  13438. {
  13439. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  13440. }
  13441. }
  13442. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  13443. {
  13444. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  13445. }
  13446. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  13447. }
  13448. }
  13449. if (isset($this->data['links'][$rel]))
  13450. {
  13451. return $this->data['links'][$rel];
  13452. }
  13453. else
  13454. {
  13455. return null;
  13456. }
  13457. }
  13458. public function get_description()
  13459. {
  13460. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  13461. {
  13462. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13463. }
  13464. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  13465. {
  13466. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13467. }
  13468. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  13469. {
  13470. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13471. }
  13472. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  13473. {
  13474. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13475. }
  13476. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  13477. {
  13478. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  13479. }
  13480. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  13481. {
  13482. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13483. }
  13484. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  13485. {
  13486. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13487. }
  13488. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  13489. {
  13490. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  13491. }
  13492. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  13493. {
  13494. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  13495. }
  13496. else
  13497. {
  13498. return null;
  13499. }
  13500. }
  13501. public function get_copyright()
  13502. {
  13503. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  13504. {
  13505. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13506. }
  13507. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  13508. {
  13509. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  13510. }
  13511. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  13512. {
  13513. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13514. }
  13515. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  13516. {
  13517. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13518. }
  13519. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  13520. {
  13521. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13522. }
  13523. else
  13524. {
  13525. return null;
  13526. }
  13527. }
  13528. public function get_language()
  13529. {
  13530. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  13531. {
  13532. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13533. }
  13534. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  13535. {
  13536. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13537. }
  13538. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  13539. {
  13540. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  13541. }
  13542. elseif (isset($this->data['xml_lang']))
  13543. {
  13544. return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  13545. }
  13546. else
  13547. {
  13548. return null;
  13549. }
  13550. }
  13551. public function get_latitude()
  13552. {
  13553. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  13554. {
  13555. return (float) $return[0]['data'];
  13556. }
  13557. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  13558. {
  13559. return (float) $match[1];
  13560. }
  13561. else
  13562. {
  13563. return null;
  13564. }
  13565. }
  13566. public function get_longitude()
  13567. {
  13568. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  13569. {
  13570. return (float) $return[0]['data'];
  13571. }
  13572. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  13573. {
  13574. return (float) $return[0]['data'];
  13575. }
  13576. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', trim($return[0]['data']), $match))
  13577. {
  13578. return (float) $match[2];
  13579. }
  13580. else
  13581. {
  13582. return null;
  13583. }
  13584. }
  13585. public function get_image_url()
  13586. {
  13587. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  13588. {
  13589. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  13590. }
  13591. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  13592. {
  13593. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  13594. }
  13595. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  13596. {
  13597. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  13598. }
  13599. else
  13600. {
  13601. return null;
  13602. }
  13603. }
  13604. }
  13605. /**
  13606. * Parses the XML Declaration
  13607. *
  13608. * @package SimplePie
  13609. */
  13610. class SimplePie_XML_Declaration_Parser
  13611. {
  13612. /**
  13613. * XML Version
  13614. *
  13615. * @access public
  13616. * @var string
  13617. */
  13618. var $version = '1.0';
  13619. /**
  13620. * Encoding
  13621. *
  13622. * @access public
  13623. * @var string
  13624. */
  13625. var $encoding = 'UTF-8';
  13626. /**
  13627. * Standalone
  13628. *
  13629. * @access public
  13630. * @var bool
  13631. */
  13632. var $standalone = false;
  13633. /**
  13634. * Current state of the state machine
  13635. *
  13636. * @access private
  13637. * @var string
  13638. */
  13639. var $state = 'before_version_name';
  13640. /**
  13641. * Input data
  13642. *
  13643. * @access private
  13644. * @var string
  13645. */
  13646. var $data = '';
  13647. /**
  13648. * Input data length (to avoid calling strlen() everytime this is needed)
  13649. *
  13650. * @access private
  13651. * @var int
  13652. */
  13653. var $data_length = 0;
  13654. /**
  13655. * Current position of the pointer
  13656. *
  13657. * @var int
  13658. * @access private
  13659. */
  13660. var $position = 0;
  13661. /**
  13662. * Create an instance of the class with the input data
  13663. *
  13664. * @access public
  13665. * @param string $data Input data
  13666. */
  13667. public function __construct($data)
  13668. {
  13669. $this->data = $data;
  13670. $this->data_length = strlen($this->data);
  13671. }
  13672. /**
  13673. * Parse the input data
  13674. *
  13675. * @access public
  13676. * @return bool true on success, false on failure
  13677. */
  13678. public function parse()
  13679. {
  13680. while ($this->state && $this->state !== 'emit' && $this->has_data())
  13681. {
  13682. $state = $this->state;
  13683. $this->$state();
  13684. }
  13685. $this->data = '';
  13686. if ($this->state === 'emit')
  13687. {
  13688. return true;
  13689. }
  13690. else
  13691. {
  13692. $this->version = '';
  13693. $this->encoding = '';
  13694. $this->standalone = '';
  13695. return false;
  13696. }
  13697. }
  13698. /**
  13699. * Check whether there is data beyond the pointer
  13700. *
  13701. * @access private
  13702. * @return bool true if there is further data, false if not
  13703. */
  13704. public function has_data()
  13705. {
  13706. return (bool) ($this->position < $this->data_length);
  13707. }
  13708. /**
  13709. * Advance past any whitespace
  13710. *
  13711. * @return int Number of whitespace characters passed
  13712. */
  13713. public function skip_whitespace()
  13714. {
  13715. $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
  13716. $this->position += $whitespace;
  13717. return $whitespace;
  13718. }
  13719. /**
  13720. * Read value
  13721. */
  13722. public function get_value()
  13723. {
  13724. $quote = substr($this->data, $this->position, 1);
  13725. if ($quote === '"' || $quote === "'")
  13726. {
  13727. $this->position++;
  13728. $len = strcspn($this->data, $quote, $this->position);
  13729. if ($this->has_data())
  13730. {
  13731. $value = substr($this->data, $this->position, $len);
  13732. $this->position += $len + 1;
  13733. return $value;
  13734. }
  13735. }
  13736. return false;
  13737. }
  13738. public function before_version_name()
  13739. {
  13740. if ($this->skip_whitespace())
  13741. {
  13742. $this->state = 'version_name';
  13743. }
  13744. else
  13745. {
  13746. $this->state = false;
  13747. }
  13748. }
  13749. public function version_name()
  13750. {
  13751. if (substr($this->data, $this->position, 7) === 'version')
  13752. {
  13753. $this->position += 7;
  13754. $this->skip_whitespace();
  13755. $this->state = 'version_equals';
  13756. }
  13757. else
  13758. {
  13759. $this->state = false;
  13760. }
  13761. }
  13762. public function version_equals()
  13763. {
  13764. if (substr($this->data, $this->position, 1) === '=')
  13765. {
  13766. $this->position++;
  13767. $this->skip_whitespace();
  13768. $this->state = 'version_value';
  13769. }
  13770. else
  13771. {
  13772. $this->state = false;
  13773. }
  13774. }
  13775. public function version_value()
  13776. {
  13777. if ($this->version = $this->get_value())
  13778. {
  13779. $this->skip_whitespace();
  13780. if ($this->has_data())
  13781. {
  13782. $this->state = 'encoding_name';
  13783. }
  13784. else
  13785. {
  13786. $this->state = 'emit';
  13787. }
  13788. }
  13789. else
  13790. {
  13791. $this->state = false;
  13792. }
  13793. }
  13794. public function encoding_name()
  13795. {
  13796. if (substr($this->data, $this->position, 8) === 'encoding')
  13797. {
  13798. $this->position += 8;
  13799. $this->skip_whitespace();
  13800. $this->state = 'encoding_equals';
  13801. }
  13802. else
  13803. {
  13804. $this->state = 'standalone_name';
  13805. }
  13806. }
  13807. public function encoding_equals()
  13808. {
  13809. if (substr($this->data, $this->position, 1) === '=')
  13810. {
  13811. $this->position++;
  13812. $this->skip_whitespace();
  13813. $this->state = 'encoding_value';
  13814. }
  13815. else
  13816. {
  13817. $this->state = false;
  13818. }
  13819. }
  13820. public function encoding_value()
  13821. {
  13822. if ($this->encoding = $this->get_value())
  13823. {
  13824. $this->skip_whitespace();
  13825. if ($this->has_data())
  13826. {
  13827. $this->state = 'standalone_name';
  13828. }
  13829. else
  13830. {
  13831. $this->state = 'emit';
  13832. }
  13833. }
  13834. else
  13835. {
  13836. $this->state = false;
  13837. }
  13838. }
  13839. public function standalone_name()
  13840. {
  13841. if (substr($this->data, $this->position, 10) === 'standalone')
  13842. {
  13843. $this->position += 10;
  13844. $this->skip_whitespace();
  13845. $this->state = 'standalone_equals';
  13846. }
  13847. else
  13848. {
  13849. $this->state = false;
  13850. }
  13851. }
  13852. public function standalone_equals()
  13853. {
  13854. if (substr($this->data, $this->position, 1) === '=')
  13855. {
  13856. $this->position++;
  13857. $this->skip_whitespace();
  13858. $this->state = 'standalone_value';
  13859. }
  13860. else
  13861. {
  13862. $this->state = false;
  13863. }
  13864. }
  13865. public function standalone_value()
  13866. {
  13867. if ($standalone = $this->get_value())
  13868. {
  13869. switch ($standalone)
  13870. {
  13871. case 'yes':
  13872. $this->standalone = true;
  13873. break;
  13874. case 'no':
  13875. $this->standalone = false;
  13876. break;
  13877. default:
  13878. $this->state = false;
  13879. return;
  13880. }
  13881. $this->skip_whitespace();
  13882. if ($this->has_data())
  13883. {
  13884. $this->state = false;
  13885. }
  13886. else
  13887. {
  13888. $this->state = 'emit';
  13889. }
  13890. }
  13891. else
  13892. {
  13893. $this->state = false;
  13894. }
  13895. }
  13896. }