PageRenderTime 68ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 2ms

/lib/simplepie/simplepie.class.php

https://bitbucket.org/ngmares/moodle
PHP | 14538 lines | 11496 code | 1022 blank | 2020 comment | 1074 complexity | a3779241186efe0fe666f139a541cd3e MD5 | raw file
Possible License(s): LGPL-2.1, AGPL-3.0, MPL-2.0-no-copyleft-exception, GPL-3.0, Apache-2.0, BSD-3-Clause
  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-2009, 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-2009 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 Name
  47. */
  48. define('SIMPLEPIE_NAME', 'SimplePie');
  49. /**
  50. * SimplePie Version
  51. */
  52. define('SIMPLEPIE_VERSION', '1.3-dev');
  53. /**
  54. * SimplePie Build
  55. * @todo Hardcode for release (there's no need to have to call SimplePie_Misc::parse_date() only every load of simplepie.inc)
  56. */
  57. define('SIMPLEPIE_BUILD', gmdate('YmdHis', SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) ? SimplePie_Misc::parse_date(substr('$Date$', 7, 25)) : filemtime(__FILE__)));
  58. /**
  59. * SimplePie Website URL
  60. */
  61. define('SIMPLEPIE_URL', 'http://simplepie.org');
  62. /**
  63. * SimplePie Useragent
  64. * @see SimplePie::set_useragent()
  65. */
  66. define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
  67. /**
  68. * SimplePie Linkback
  69. */
  70. define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
  71. /**
  72. * No Autodiscovery
  73. * @see SimplePie::set_autodiscovery_level()
  74. */
  75. define('SIMPLEPIE_LOCATOR_NONE', 0);
  76. /**
  77. * Feed Link Element Autodiscovery
  78. * @see SimplePie::set_autodiscovery_level()
  79. */
  80. define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
  81. /**
  82. * Local Feed Extension Autodiscovery
  83. * @see SimplePie::set_autodiscovery_level()
  84. */
  85. define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
  86. /**
  87. * Local Feed Body Autodiscovery
  88. * @see SimplePie::set_autodiscovery_level()
  89. */
  90. define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
  91. /**
  92. * Remote Feed Extension Autodiscovery
  93. * @see SimplePie::set_autodiscovery_level()
  94. */
  95. define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
  96. /**
  97. * Remote Feed Body Autodiscovery
  98. * @see SimplePie::set_autodiscovery_level()
  99. */
  100. define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
  101. /**
  102. * All Feed Autodiscovery
  103. * @see SimplePie::set_autodiscovery_level()
  104. */
  105. define('SIMPLEPIE_LOCATOR_ALL', 31);
  106. /**
  107. * No known feed type
  108. */
  109. define('SIMPLEPIE_TYPE_NONE', 0);
  110. /**
  111. * RSS 0.90
  112. */
  113. define('SIMPLEPIE_TYPE_RSS_090', 1);
  114. /**
  115. * RSS 0.91 (Netscape)
  116. */
  117. define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
  118. /**
  119. * RSS 0.91 (Userland)
  120. */
  121. define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
  122. /**
  123. * RSS 0.91 (both Netscape and Userland)
  124. */
  125. define('SIMPLEPIE_TYPE_RSS_091', 6);
  126. /**
  127. * RSS 0.92
  128. */
  129. define('SIMPLEPIE_TYPE_RSS_092', 8);
  130. /**
  131. * RSS 0.93
  132. */
  133. define('SIMPLEPIE_TYPE_RSS_093', 16);
  134. /**
  135. * RSS 0.94
  136. */
  137. define('SIMPLEPIE_TYPE_RSS_094', 32);
  138. /**
  139. * RSS 1.0
  140. */
  141. define('SIMPLEPIE_TYPE_RSS_10', 64);
  142. /**
  143. * RSS 2.0
  144. */
  145. define('SIMPLEPIE_TYPE_RSS_20', 128);
  146. /**
  147. * RDF-based RSS
  148. */
  149. define('SIMPLEPIE_TYPE_RSS_RDF', 65);
  150. /**
  151. * Non-RDF-based RSS (truly intended as syndication format)
  152. */
  153. define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
  154. /**
  155. * All RSS
  156. */
  157. define('SIMPLEPIE_TYPE_RSS_ALL', 255);
  158. /**
  159. * Atom 0.3
  160. */
  161. define('SIMPLEPIE_TYPE_ATOM_03', 256);
  162. /**
  163. * Atom 1.0
  164. */
  165. define('SIMPLEPIE_TYPE_ATOM_10', 512);
  166. /**
  167. * All Atom
  168. */
  169. define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
  170. /**
  171. * All feed types
  172. */
  173. define('SIMPLEPIE_TYPE_ALL', 1023);
  174. /**
  175. * No construct
  176. */
  177. define('SIMPLEPIE_CONSTRUCT_NONE', 0);
  178. /**
  179. * Text construct
  180. */
  181. define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
  182. /**
  183. * HTML construct
  184. */
  185. define('SIMPLEPIE_CONSTRUCT_HTML', 2);
  186. /**
  187. * XHTML construct
  188. */
  189. define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
  190. /**
  191. * base64-encoded construct
  192. */
  193. define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
  194. /**
  195. * IRI construct
  196. */
  197. define('SIMPLEPIE_CONSTRUCT_IRI', 16);
  198. /**
  199. * A construct that might be HTML
  200. */
  201. define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
  202. /**
  203. * All constructs
  204. */
  205. define('SIMPLEPIE_CONSTRUCT_ALL', 63);
  206. /**
  207. * Don't change case
  208. */
  209. define('SIMPLEPIE_SAME_CASE', 1);
  210. /**
  211. * Change to lowercase
  212. */
  213. define('SIMPLEPIE_LOWERCASE', 2);
  214. /**
  215. * Change to uppercase
  216. */
  217. define('SIMPLEPIE_UPPERCASE', 4);
  218. /**
  219. * PCRE for HTML attributes
  220. */
  221. 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]*');
  222. /**
  223. * PCRE for XML attributes
  224. */
  225. define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
  226. /**
  227. * XML Namespace
  228. */
  229. define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
  230. /**
  231. * Atom 1.0 Namespace
  232. */
  233. define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
  234. /**
  235. * Atom 0.3 Namespace
  236. */
  237. define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
  238. /**
  239. * RDF Namespace
  240. */
  241. define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  242. /**
  243. * RSS 0.90 Namespace
  244. */
  245. define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
  246. /**
  247. * RSS 1.0 Namespace
  248. */
  249. define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
  250. /**
  251. * RSS 1.0 Content Module Namespace
  252. */
  253. define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
  254. /**
  255. * RSS 2.0 Namespace
  256. * (Stupid, I know, but I'm certain it will confuse people less with support.)
  257. */
  258. define('SIMPLEPIE_NAMESPACE_RSS_20', '');
  259. /**
  260. * DC 1.0 Namespace
  261. */
  262. define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
  263. /**
  264. * DC 1.1 Namespace
  265. */
  266. define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
  267. /**
  268. * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
  269. */
  270. define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
  271. /**
  272. * GeoRSS Namespace
  273. */
  274. define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
  275. /**
  276. * Media RSS Namespace
  277. */
  278. define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
  279. /**
  280. * Wrong Media RSS Namespace. Caused by a long-standing typo in the spec.
  281. */
  282. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
  283. /**
  284. * Wrong Media RSS Namespace #2. New namespace introduced in Media RSS 1.5.
  285. */
  286. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2', 'http://video.search.yahoo.com/mrss');
  287. /**
  288. * Wrong Media RSS Namespace #3. A possible typo of the Media RSS 1.5 namespace.
  289. */
  290. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3', 'http://video.search.yahoo.com/mrss/');
  291. /**
  292. * Wrong Media RSS Namespace #4. New spec location after the RSS Advisory Board takes it over, but not a valid namespace.
  293. */
  294. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4', 'http://www.rssboard.org/media-rss');
  295. /**
  296. * Wrong Media RSS Namespace #5. A possible typo of the RSS Advisory Board URL.
  297. */
  298. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5', 'http://www.rssboard.org/media-rss/');
  299. /**
  300. * iTunes RSS Namespace
  301. */
  302. define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
  303. /**
  304. * XHTML Namespace
  305. */
  306. define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  307. /**
  308. * IANA Link Relations Registry
  309. */
  310. define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
  311. /**
  312. * Whether we're running on PHP5
  313. */
  314. define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
  315. /**
  316. * No file source
  317. */
  318. define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
  319. /**
  320. * Remote file source
  321. */
  322. define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
  323. /**
  324. * Local file source
  325. */
  326. define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
  327. /**
  328. * fsockopen() file source
  329. */
  330. define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
  331. /**
  332. * cURL file source
  333. */
  334. define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
  335. /**
  336. * file_get_contents() file source
  337. */
  338. define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  339. /**
  340. * SimplePie
  341. *
  342. * @package SimplePie
  343. */
  344. class SimplePie
  345. {
  346. /**
  347. * @var array Raw data
  348. * @access private
  349. */
  350. public $data = array();
  351. /**
  352. * @var mixed Error string
  353. * @access private
  354. */
  355. public $error;
  356. /**
  357. * @var object Instance of SimplePie_Sanitize (or other class)
  358. * @see SimplePie::set_sanitize_class()
  359. * @access private
  360. */
  361. public $sanitize;
  362. /**
  363. * @var string SimplePie Useragent
  364. * @see SimplePie::set_useragent()
  365. * @access private
  366. */
  367. public $useragent = SIMPLEPIE_USERAGENT;
  368. /**
  369. * @var string Feed URL
  370. * @see SimplePie::set_feed_url()
  371. * @access private
  372. */
  373. public $feed_url;
  374. /**
  375. * @var object Instance of SimplePie_File to use as a feed
  376. * @see SimplePie::set_file()
  377. * @access private
  378. */
  379. public $file;
  380. /**
  381. * @var string Raw feed data
  382. * @see SimplePie::set_raw_data()
  383. * @access private
  384. */
  385. public $raw_data;
  386. /**
  387. * @var int Timeout for fetching remote files
  388. * @see SimplePie::set_timeout()
  389. * @access private
  390. */
  391. public $timeout = 10;
  392. /**
  393. * @var bool Forces fsockopen() to be used for remote files instead
  394. * of cURL, even if a new enough version is installed
  395. * @see SimplePie::force_fsockopen()
  396. * @access private
  397. */
  398. public $force_fsockopen = false;
  399. /**
  400. * @var bool Force the given data/URL to be treated as a feed no matter what
  401. * it appears like
  402. * @see SimplePie::force_feed()
  403. * @access private
  404. */
  405. public $force_feed = false;
  406. /**
  407. * @var bool Enable/Disable XML dump
  408. * @see SimplePie::enable_xml_dump()
  409. * @access private
  410. */
  411. public $xml_dump = false;
  412. /**
  413. * @var bool Enable/Disable Caching
  414. * @see SimplePie::enable_cache()
  415. * @access private
  416. */
  417. public $cache = true;
  418. /**
  419. * @var int Cache duration (in seconds)
  420. * @see SimplePie::set_cache_duration()
  421. * @access private
  422. */
  423. public $cache_duration = 3600;
  424. /**
  425. * @var int Auto-discovery cache duration (in seconds)
  426. * @see SimplePie::set_autodiscovery_cache_duration()
  427. * @access private
  428. */
  429. public $autodiscovery_cache_duration = 604800; // 7 Days.
  430. /**
  431. * @var string Cache location (relative to executing script)
  432. * @see SimplePie::set_cache_location()
  433. * @access private
  434. */
  435. public $cache_location = './cache';
  436. /**
  437. * @var string Function that creates the cache filename
  438. * @see SimplePie::set_cache_name_function()
  439. * @access private
  440. */
  441. public $cache_name_function = 'md5';
  442. /**
  443. * @var bool Reorder feed by date descending
  444. * @see SimplePie::enable_order_by_date()
  445. * @access private
  446. */
  447. public $order_by_date = true;
  448. /**
  449. * @var mixed Force input encoding to be set to the follow value
  450. * (false, or anything type-cast to false, disables this feature)
  451. * @see SimplePie::set_input_encoding()
  452. * @access private
  453. */
  454. public $input_encoding = false;
  455. /**
  456. * @var int Feed Autodiscovery Level
  457. * @see SimplePie::set_autodiscovery_level()
  458. * @access private
  459. */
  460. public $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
  461. /**
  462. * @var string Class used for caching feeds
  463. * @see SimplePie::set_cache_class()
  464. * @access private
  465. */
  466. public $cache_class = 'SimplePie_Cache';
  467. /**
  468. * @var string Class used for locating feeds
  469. * @see SimplePie::set_locator_class()
  470. * @access private
  471. */
  472. public $locator_class = 'SimplePie_Locator';
  473. /**
  474. * @var string Class used for parsing feeds
  475. * @see SimplePie::set_parser_class()
  476. * @access private
  477. */
  478. public $parser_class = 'SimplePie_Parser';
  479. /**
  480. * @var string Class used for fetching feeds
  481. * @see SimplePie::set_file_class()
  482. * @access private
  483. */
  484. public $file_class = 'SimplePie_File';
  485. /**
  486. * @var string Class used for items
  487. * @see SimplePie::set_item_class()
  488. * @access private
  489. */
  490. public $item_class = 'SimplePie_Item';
  491. /**
  492. * @var string Class used for authors
  493. * @see SimplePie::set_author_class()
  494. * @access private
  495. */
  496. public $author_class = 'SimplePie_Author';
  497. /**
  498. * @var string Class used for categories
  499. * @see SimplePie::set_category_class()
  500. * @access private
  501. */
  502. public $category_class = 'SimplePie_Category';
  503. /**
  504. * @var string Class used for enclosures
  505. * @see SimplePie::set_enclosures_class()
  506. * @access private
  507. */
  508. public $enclosure_class = 'SimplePie_Enclosure';
  509. /**
  510. * @var string Class used for Media RSS <media:text> captions
  511. * @see SimplePie::set_caption_class()
  512. * @access private
  513. */
  514. public $caption_class = 'SimplePie_Caption';
  515. /**
  516. * @var string Class used for Media RSS <media:copyright>
  517. * @see SimplePie::set_copyright_class()
  518. * @access private
  519. */
  520. public $copyright_class = 'SimplePie_Copyright';
  521. /**
  522. * @var string Class used for Media RSS <media:credit>
  523. * @see SimplePie::set_credit_class()
  524. * @access private
  525. */
  526. public $credit_class = 'SimplePie_Credit';
  527. /**
  528. * @var string Class used for Media RSS <media:rating>
  529. * @see SimplePie::set_rating_class()
  530. * @access private
  531. */
  532. public $rating_class = 'SimplePie_Rating';
  533. /**
  534. * @var string Class used for Media RSS <media:restriction>
  535. * @see SimplePie::set_restriction_class()
  536. * @access private
  537. */
  538. public $restriction_class = 'SimplePie_Restriction';
  539. /**
  540. * @var string Class used for content-type sniffing
  541. * @see SimplePie::set_content_type_sniffer_class()
  542. * @access private
  543. */
  544. public $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  545. /**
  546. * @var string Class used for item sources.
  547. * @see SimplePie::set_source_class()
  548. * @access private
  549. */
  550. public $source_class = 'SimplePie_Source';
  551. /**
  552. * @var mixed Set javascript query string parameter (false, or
  553. * anything type-cast to false, disables this feature)
  554. * @see SimplePie::set_javascript()
  555. * @access private
  556. */
  557. public $javascript = 'js';
  558. /**
  559. * @var int Maximum number of feeds to check with autodiscovery
  560. * @see SimplePie::set_max_checked_feeds()
  561. * @access private
  562. */
  563. public $max_checked_feeds = 10;
  564. /**
  565. * @var array All the feeds found during the autodiscovery process
  566. * @see SimplePie::get_all_discovered_feeds()
  567. * @access private
  568. */
  569. public $all_discovered_feeds = array();
  570. /**
  571. * @var string Web-accessible path to the handler_image.php file.
  572. * @see SimplePie::set_image_handler()
  573. * @access private
  574. */
  575. public $image_handler = '';
  576. /**
  577. * @var array Stores the URLs when multiple feeds are being initialized.
  578. * @see SimplePie::set_feed_url()
  579. * @access private
  580. */
  581. public $multifeed_url = array();
  582. /**
  583. * @var array Stores SimplePie objects when multiple feeds initialized.
  584. * @access private
  585. */
  586. public $multifeed_objects = array();
  587. /**
  588. * @var array Stores the get_object_vars() array for use with multifeeds.
  589. * @see SimplePie::set_feed_url()
  590. * @access private
  591. */
  592. public $config_settings = null;
  593. /**
  594. * @var integer Stores the number of items to return per-feed with multifeeds.
  595. * @see SimplePie::set_item_limit()
  596. * @access private
  597. */
  598. public $item_limit = 0;
  599. /**
  600. * @var array Stores the default attributes to be stripped by strip_attributes().
  601. * @see SimplePie::strip_attributes()
  602. * @access private
  603. */
  604. public $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  605. /**
  606. * @var array Stores the default tags to be stripped by strip_htmltags().
  607. * @see SimplePie::strip_htmltags()
  608. * @access private
  609. */
  610. public $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  611. /**
  612. * The SimplePie class contains feed level data and options
  613. *
  614. * There are two ways that you can create a new SimplePie object. The first
  615. * is by passing a feed URL as a parameter to the SimplePie constructor
  616. * (as well as optionally setting the cache location and cache expiry). This
  617. * will initialise the whole feed with all of the default settings, and you
  618. * can begin accessing methods and properties immediately.
  619. *
  620. * The second way is to create the SimplePie object with no parameters
  621. * at all. This will enable you to set configuration options. After setting
  622. * them, you must initialise the feed using $feed->init(). At that point the
  623. * object's methods and properties will be available to you. This format is
  624. * what is used throughout this documentation.
  625. *
  626. * @access public
  627. * @since 1.0 Preview Release
  628. */
  629. public function __construct()
  630. {
  631. if (version_compare(PHP_VERSION, '5.0', '<'))
  632. {
  633. trigger_error('PHP 4.x is no longer supported. Please upgrade to PHP 5.2 or newer.');
  634. die();
  635. }
  636. // Other objects, instances created here so we can set options on them
  637. $this->sanitize = new SimplePie_Sanitize();
  638. if (func_num_args() > 0)
  639. {
  640. trigger_error('Passing parameters to the constructor is no longer supported. Please use set_feed_url(), set_cache_location(), and set_cache_location() directly.');
  641. }
  642. }
  643. /**
  644. * Used for converting object to a string
  645. */
  646. public function __toString()
  647. {
  648. return md5(serialize($this->data));
  649. }
  650. /**
  651. * Remove items that link back to this before destroying this object
  652. */
  653. public function __destruct()
  654. {
  655. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  656. {
  657. if (!empty($this->data['items']))
  658. {
  659. foreach ($this->data['items'] as $item)
  660. {
  661. $item->__destruct();
  662. }
  663. unset($item, $this->data['items']);
  664. }
  665. if (!empty($this->data['ordered_items']))
  666. {
  667. foreach ($this->data['ordered_items'] as $item)
  668. {
  669. $item->__destruct();
  670. }
  671. unset($item, $this->data['ordered_items']);
  672. }
  673. }
  674. }
  675. /**
  676. * Force the given data/URL to be treated as a feed no matter what it
  677. * appears like
  678. *
  679. * @access public
  680. * @since 1.1
  681. * @param bool $enable Force the given data/URL to be treated as a feed
  682. */
  683. public function force_feed($enable = false)
  684. {
  685. $this->force_feed = (bool) $enable;
  686. }
  687. /**
  688. * This is the URL of the feed you want to parse.
  689. *
  690. * This allows you to enter the URL of the feed you want to parse, or the
  691. * website you want to try to use auto-discovery on. This takes priority
  692. * over any set raw data.
  693. *
  694. * You can set multiple feeds to mash together by passing an array instead
  695. * of a string for the $url. Remember that with each additional feed comes
  696. * additional processing and resources.
  697. *
  698. * @access public
  699. * @since 1.0 Preview Release
  700. * @param mixed $url This is the URL (or array of URLs) that you want to parse.
  701. * @see SimplePie::set_raw_data()
  702. */
  703. public function set_feed_url($url)
  704. {
  705. if (is_array($url))
  706. {
  707. $this->multifeed_url = array();
  708. foreach ($url as $value)
  709. {
  710. $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
  711. }
  712. }
  713. else
  714. {
  715. $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
  716. }
  717. }
  718. /**
  719. * Provides an instance of SimplePie_File to use as a feed
  720. *
  721. * @access public
  722. * @param object &$file Instance of SimplePie_File (or subclass)
  723. * @return bool True on success, false on failure
  724. */
  725. public function set_file(&$file)
  726. {
  727. if (is_a($file, 'SimplePie_File'))
  728. {
  729. $this->feed_url = $file->url;
  730. $this->file =& $file;
  731. return true;
  732. }
  733. return false;
  734. }
  735. /**
  736. * Allows you to use a string of RSS/Atom data instead of a remote feed.
  737. *
  738. * If you have a feed available as a string in PHP, you can tell SimplePie
  739. * to parse that data string instead of a remote feed. Any set feed URL
  740. * takes precedence.
  741. *
  742. * @access public
  743. * @since 1.0 Beta 3
  744. * @param string $data RSS or Atom data as a string.
  745. * @see SimplePie::set_feed_url()
  746. */
  747. public function set_raw_data($data)
  748. {
  749. $this->raw_data = $data;
  750. }
  751. /**
  752. * Allows you to override the default timeout for fetching remote feeds.
  753. *
  754. * This allows you to change the maximum time the feed's server to respond
  755. * and send the feed back.
  756. *
  757. * @access public
  758. * @since 1.0 Beta 3
  759. * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
  760. */
  761. public function set_timeout($timeout = 10)
  762. {
  763. $this->timeout = (int) $timeout;
  764. }
  765. /**
  766. * Forces SimplePie to use fsockopen() instead of the preferred cURL
  767. * functions.
  768. *
  769. * @access public
  770. * @since 1.0 Beta 3
  771. * @param bool $enable Force fsockopen() to be used
  772. */
  773. public function force_fsockopen($enable = false)
  774. {
  775. $this->force_fsockopen = (bool) $enable;
  776. }
  777. /**
  778. * Enables/disables caching in SimplePie.
  779. *
  780. * This option allows you to disable caching all-together in SimplePie.
  781. * However, disabling the cache can lead to longer load times.
  782. *
  783. * @access public
  784. * @since 1.0 Preview Release
  785. * @param bool $enable Enable caching
  786. */
  787. public function enable_cache($enable = true)
  788. {
  789. $this->cache = (bool) $enable;
  790. }
  791. /**
  792. * Set the length of time (in seconds) that the contents of a feed
  793. * will be cached.
  794. *
  795. * @access public
  796. * @param int $seconds The feed content cache duration.
  797. */
  798. public function set_cache_duration($seconds = 3600)
  799. {
  800. $this->cache_duration = (int) $seconds;
  801. }
  802. /**
  803. * Set the length of time (in seconds) that the autodiscovered feed
  804. * URL will be cached.
  805. *
  806. * @access public
  807. * @param int $seconds The autodiscovered feed URL cache duration.
  808. */
  809. public function set_autodiscovery_cache_duration($seconds = 604800)
  810. {
  811. $this->autodiscovery_cache_duration = (int) $seconds;
  812. }
  813. /**
  814. * Set the file system location where the cached files should be stored.
  815. *
  816. * @access public
  817. * @param string $location The file system location.
  818. */
  819. public function set_cache_location($location = './cache')
  820. {
  821. $this->cache_location = (string) $location;
  822. }
  823. /**
  824. * Determines whether feed items should be sorted into reverse chronological order.
  825. *
  826. * @access public
  827. * @param bool $enable Sort as reverse chronological order.
  828. */
  829. public function enable_order_by_date($enable = true)
  830. {
  831. $this->order_by_date = (bool) $enable;
  832. }
  833. /**
  834. * Allows you to override the character encoding reported by the feed.
  835. *
  836. * @access public
  837. * @param string $encoding Character encoding.
  838. */
  839. public function set_input_encoding($encoding = false)
  840. {
  841. if ($encoding)
  842. {
  843. $this->input_encoding = (string) $encoding;
  844. }
  845. else
  846. {
  847. $this->input_encoding = false;
  848. }
  849. }
  850. /**
  851. * Set how much feed autodiscovery to do
  852. *
  853. * @access public
  854. * @see SIMPLEPIE_LOCATOR_NONE
  855. * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
  856. * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
  857. * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
  858. * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
  859. * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
  860. * @see SIMPLEPIE_LOCATOR_ALL
  861. * @param int $level Feed Autodiscovery Level (level can be a
  862. * combination of the above constants, see bitwise OR operator)
  863. */
  864. public function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
  865. {
  866. $this->autodiscovery = (int) $level;
  867. }
  868. /**
  869. * Allows you to change which class SimplePie uses for caching.
  870. * Useful when you are overloading or extending SimplePie's default classes.
  871. *
  872. * @access public
  873. * @param string $class Name of custom class.
  874. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  875. */
  876. public function set_cache_class($class = 'SimplePie_Cache')
  877. {
  878. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
  879. {
  880. $this->cache_class = $class;
  881. return true;
  882. }
  883. return false;
  884. }
  885. /**
  886. * Allows you to change which class SimplePie uses for auto-discovery.
  887. * Useful when you are overloading or extending SimplePie's default classes.
  888. *
  889. * @access public
  890. * @param string $class Name of custom class.
  891. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  892. */
  893. public function set_locator_class($class = 'SimplePie_Locator')
  894. {
  895. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
  896. {
  897. $this->locator_class = $class;
  898. return true;
  899. }
  900. return false;
  901. }
  902. /**
  903. * Allows you to change which class SimplePie uses for XML parsing.
  904. * Useful when you are overloading or extending SimplePie's default classes.
  905. *
  906. * @access public
  907. * @param string $class Name of custom class.
  908. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  909. */
  910. public function set_parser_class($class = 'SimplePie_Parser')
  911. {
  912. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
  913. {
  914. $this->parser_class = $class;
  915. return true;
  916. }
  917. return false;
  918. }
  919. /**
  920. * Allows you to change which class SimplePie uses for remote file fetching.
  921. * Useful when you are overloading or extending SimplePie's default classes.
  922. *
  923. * @access public
  924. * @param string $class Name of custom class.
  925. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  926. */
  927. public function set_file_class($class = 'SimplePie_File')
  928. {
  929. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
  930. {
  931. $this->file_class = $class;
  932. return true;
  933. }
  934. return false;
  935. }
  936. /**
  937. * Allows you to change which class SimplePie uses for data sanitization.
  938. * Useful when you are overloading or extending SimplePie's default classes.
  939. *
  940. * @access public
  941. * @param string $class Name of custom class.
  942. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  943. */
  944. public function set_sanitize_class($class = 'SimplePie_Sanitize')
  945. {
  946. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
  947. {
  948. $this->sanitize = new $class();
  949. return true;
  950. }
  951. return false;
  952. }
  953. /**
  954. * Allows you to change which class SimplePie uses for handling feed items.
  955. * Useful when you are overloading or extending SimplePie's default classes.
  956. *
  957. * @access public
  958. * @param string $class Name of custom class.
  959. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  960. */
  961. public function set_item_class($class = 'SimplePie_Item')
  962. {
  963. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
  964. {
  965. $this->item_class = $class;
  966. return true;
  967. }
  968. return false;
  969. }
  970. /**
  971. * Allows you to change which class SimplePie uses for handling author data.
  972. * Useful when you are overloading or extending SimplePie's default classes.
  973. *
  974. * @access public
  975. * @param string $class Name of custom class.
  976. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  977. */
  978. public function set_author_class($class = 'SimplePie_Author')
  979. {
  980. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
  981. {
  982. $this->author_class = $class;
  983. return true;
  984. }
  985. return false;
  986. }
  987. /**
  988. * Allows you to change which class SimplePie uses for handling category data.
  989. * Useful when you are overloading or extending SimplePie's default classes.
  990. *
  991. * @access public
  992. * @param string $class Name of custom class.
  993. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  994. */
  995. public function set_category_class($class = 'SimplePie_Category')
  996. {
  997. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
  998. {
  999. $this->category_class = $class;
  1000. return true;
  1001. }
  1002. return false;
  1003. }
  1004. /**
  1005. * Allows you to change which class SimplePie uses for feed enclosures.
  1006. * Useful when you are overloading or extending SimplePie's default classes.
  1007. *
  1008. * @access public
  1009. * @param string $class Name of custom class.
  1010. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1011. */
  1012. public function set_enclosure_class($class = 'SimplePie_Enclosure')
  1013. {
  1014. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
  1015. {
  1016. $this->enclosure_class = $class;
  1017. return true;
  1018. }
  1019. return false;
  1020. }
  1021. /**
  1022. * Allows you to change which class SimplePie uses for <media:text> captions
  1023. * Useful when you are overloading or extending SimplePie's default classes.
  1024. *
  1025. * @access public
  1026. * @param string $class Name of custom class.
  1027. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1028. */
  1029. public function set_caption_class($class = 'SimplePie_Caption')
  1030. {
  1031. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
  1032. {
  1033. $this->caption_class = $class;
  1034. return true;
  1035. }
  1036. return false;
  1037. }
  1038. /**
  1039. * Allows you to change which class SimplePie uses for <media:copyright>
  1040. * Useful when you are overloading or extending SimplePie's default classes.
  1041. *
  1042. * @access public
  1043. * @param string $class Name of custom class.
  1044. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1045. */
  1046. public function set_copyright_class($class = 'SimplePie_Copyright')
  1047. {
  1048. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
  1049. {
  1050. $this->copyright_class = $class;
  1051. return true;
  1052. }
  1053. return false;
  1054. }
  1055. /**
  1056. * Allows you to change which class SimplePie uses for <media:credit>
  1057. * Useful when you are overloading or extending SimplePie's default classes.
  1058. *
  1059. * @access public
  1060. * @param string $class Name of custom class.
  1061. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1062. */
  1063. public function set_credit_class($class = 'SimplePie_Credit')
  1064. {
  1065. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
  1066. {
  1067. $this->credit_class = $class;
  1068. return true;
  1069. }
  1070. return false;
  1071. }
  1072. /**
  1073. * Allows you to change which class SimplePie uses for <media:rating>
  1074. * Useful when you are overloading or extending SimplePie's default classes.
  1075. *
  1076. * @access public
  1077. * @param string $class Name of custom class.
  1078. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1079. */
  1080. public function set_rating_class($class = 'SimplePie_Rating')
  1081. {
  1082. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
  1083. {
  1084. $this->rating_class = $class;
  1085. return true;
  1086. }
  1087. return false;
  1088. }
  1089. /**
  1090. * Allows you to change which class SimplePie uses for <media:restriction>
  1091. * Useful when you are overloading or extending SimplePie's default classes.
  1092. *
  1093. * @access public
  1094. * @param string $class Name of custom class.
  1095. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1096. */
  1097. public function set_restriction_class($class = 'SimplePie_Restriction')
  1098. {
  1099. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
  1100. {
  1101. $this->restriction_class = $class;
  1102. return true;
  1103. }
  1104. return false;
  1105. }
  1106. /**
  1107. * Allows you to change which class SimplePie uses for content-type sniffing.
  1108. * Useful when you are overloading or extending SimplePie's default classes.
  1109. *
  1110. * @access public
  1111. * @param string $class Name of custom class.
  1112. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1113. */
  1114. public function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
  1115. {
  1116. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
  1117. {
  1118. $this->content_type_sniffer_class = $class;
  1119. return true;
  1120. }
  1121. return false;
  1122. }
  1123. /**
  1124. * Allows you to change which class SimplePie uses item sources.
  1125. * Useful when you are overloading or extending SimplePie's default classes.
  1126. *
  1127. * @access public
  1128. * @param string $class Name of custom class.
  1129. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1130. */
  1131. public function set_source_class($class = 'SimplePie_Source')
  1132. {
  1133. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
  1134. {
  1135. $this->source_class = $class;
  1136. return true;
  1137. }
  1138. return false;
  1139. }
  1140. /**
  1141. * Allows you to override the default user agent string.
  1142. *
  1143. * @access public
  1144. * @param string $ua New user agent string.
  1145. */
  1146. public function set_useragent($ua = SIMPLEPIE_USERAGENT)
  1147. {
  1148. $this->useragent = (string) $ua;
  1149. }
  1150. /**
  1151. * Set callback function to create cache filename with
  1152. *
  1153. * @access public
  1154. * @param mixed $function Callback function
  1155. */
  1156. public function set_cache_name_function($function = 'md5')
  1157. {
  1158. if (is_callable($function))
  1159. {
  1160. $this->cache_name_function = $function;
  1161. }
  1162. }
  1163. /**
  1164. * Set javascript query string parameter
  1165. *
  1166. * @access public
  1167. * @param mixed $get Javascript query string parameter
  1168. */
  1169. public function set_javascript($get = 'js')
  1170. {
  1171. if ($get)
  1172. {
  1173. $this->javascript = (string) $get;
  1174. }
  1175. else
  1176. {
  1177. $this->javascript = false;
  1178. }
  1179. }
  1180. /**
  1181. * Set options to make SP as fast as possible. Forgoes a
  1182. * substantial amount of data sanitization in favor of speed.
  1183. *
  1184. * @access public
  1185. * @param bool $set Whether to set them or not
  1186. */
  1187. public function set_stupidly_fast($set = false)
  1188. {
  1189. if ($set)
  1190. {
  1191. $this->enable_order_by_date(false);
  1192. $this->remove_div(false);
  1193. $this->strip_comments(false);
  1194. $this->strip_htmltags(false);
  1195. $this->strip_attributes(false);
  1196. $this->set_image_handler(false);
  1197. }
  1198. }
  1199. /**
  1200. * Set maximum number of feeds to check with autodiscovery
  1201. *
  1202. * @access public
  1203. * @param int $max Maximum number of feeds to check
  1204. */
  1205. public function set_max_checked_feeds($max = 10)
  1206. {
  1207. $this->max_checked_feeds = (int) $max;
  1208. }
  1209. public function remove_div($enable = true)
  1210. {
  1211. $this->sanitize->remove_div($enable);
  1212. }
  1213. public function strip_htmltags($tags = '', $encode = null)
  1214. {
  1215. if ($tags === '')
  1216. {
  1217. $tags = $this->strip_htmltags;
  1218. }
  1219. $this->sanitize->strip_htmltags($tags);
  1220. if ($encode !== null)
  1221. {
  1222. $this->sanitize->encode_instead_of_strip($tags);
  1223. }
  1224. }
  1225. public function encode_instead_of_strip($enable = true)
  1226. {
  1227. $this->sanitize->encode_instead_of_strip($enable);
  1228. }
  1229. public function strip_attributes($attribs = '')
  1230. {
  1231. if ($attribs === '')
  1232. {
  1233. $attribs = $this->strip_attributes;
  1234. }
  1235. $this->sanitize->strip_attributes($attribs);
  1236. }
  1237. public function set_output_encoding($encoding = 'UTF-8')
  1238. {
  1239. $this->sanitize->set_output_encoding($encoding);
  1240. }
  1241. public function strip_comments($strip = false)
  1242. {
  1243. $this->sanitize->strip_comments($strip);
  1244. }
  1245. /**
  1246. * Set element/attribute key/value pairs of HTML attributes
  1247. * containing URLs that need to be resolved relative to the feed
  1248. *
  1249. * @access public
  1250. * @since 1.0
  1251. * @param array $element_attribute Element/attribute key/value pairs
  1252. */
  1253. 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'))
  1254. {
  1255. $this->sanitize->set_url_replacements($element_attribute);
  1256. }
  1257. /**
  1258. * Set the handler to enable the display of cached images.
  1259. *
  1260. * @access public
  1261. * @param str $page Web-accessible path to the handler_image.php file.
  1262. * @param str $qs The query string that the value should be passed to.
  1263. */
  1264. public function set_image_handler($page = false, $qs = 'i')
  1265. {
  1266. if ($page !== false)
  1267. {
  1268. $this->sanitize->set_image_handler($page . '?' . $qs . '=');
  1269. }
  1270. else
  1271. {
  1272. $this->image_handler = '';
  1273. }
  1274. }
  1275. /**
  1276. * Set the limit for items returned per-feed with multifeeds.
  1277. *
  1278. * @access public
  1279. * @param integer $limit The maximum number of items to return.
  1280. */
  1281. public function set_item_limit($limit = 0)
  1282. {
  1283. $this->item_limit = (int) $limit;
  1284. }
  1285. public function init()
  1286. {
  1287. // Check absolute bare minimum requirements.
  1288. if ((function_exists('version_compare') && version_compare(PHP_VERSION, '5.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
  1289. {
  1290. return false;
  1291. }
  1292. // 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.
  1293. elseif (!extension_loaded('xmlreader'))
  1294. {
  1295. static $xml_is_sane = null;
  1296. if ($xml_is_sane === null)
  1297. {
  1298. $parser_check = xml_parser_create();
  1299. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  1300. xml_parser_free($parser_check);
  1301. $xml_is_sane = isset($values[0]['value']);
  1302. }
  1303. if (!$xml_is_sane)
  1304. {
  1305. return false;
  1306. }
  1307. }
  1308. if (isset($_GET[$this->javascript]))
  1309. {
  1310. SimplePie_Misc::output_javascript();
  1311. exit;
  1312. }
  1313. // Pass whatever was set with config options over to the sanitizer.
  1314. $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
  1315. $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
  1316. if ($this->feed_url !== null || $this->raw_data !== null)
  1317. {
  1318. $this->error = null;
  1319. $this->data = array();
  1320. $this->multifeed_objects = array();
  1321. $cache = false;
  1322. if ($this->feed_url !== null)
  1323. {
  1324. $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
  1325. // Decide whether to enable caching
  1326. if ($this->cache && $parsed_feed_url['scheme'] !== '')
  1327. {
  1328. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
  1329. }
  1330. // If it's enabled and we don't want an XML dump, use the cache
  1331. if ($cache && !$this->xml_dump)
  1332. {
  1333. // Load the Cache
  1334. $this->data = $cache->load();
  1335. if (!empty($this->data))
  1336. {
  1337. // If the cache is for an outdated build of SimplePie
  1338. if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
  1339. {
  1340. $cache->unlink();
  1341. $this->data = array();
  1342. }
  1343. // If we've hit a collision just rerun it with caching disabled
  1344. elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
  1345. {
  1346. $cache = false;
  1347. $this->data = array();
  1348. }
  1349. // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
  1350. elseif (isset($this->data['feed_url']))
  1351. {
  1352. // If the autodiscovery cache is still valid use it.
  1353. if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
  1354. {
  1355. // Do not need to do feed autodiscovery yet.
  1356. if ($this->data['feed_url'] === $this->data['url'])
  1357. {
  1358. $cache->unlink();
  1359. $this->data = array();
  1360. }
  1361. else
  1362. {
  1363. $this->set_feed_url($this->data['feed_url']);
  1364. return $this->init();
  1365. }
  1366. }
  1367. }
  1368. // Check if the cache has been updated
  1369. elseif ($cache->mtime() + $this->cache_duration < time())
  1370. {
  1371. // If we have last-modified and/or etag set
  1372. if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
  1373. {
  1374. $headers = array();
  1375. if (isset($this->data['headers']['last-modified']))
  1376. {
  1377. $headers['if-modified-since'] = $this->data['headers']['last-modified'];
  1378. }
  1379. if (isset($this->data['headers']['etag']))
  1380. {
  1381. $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
  1382. }
  1383. $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
  1384. if ($file->success)
  1385. {
  1386. if ($file->status_code === 304)
  1387. {
  1388. $cache->touch();
  1389. return true;
  1390. }
  1391. else
  1392. {
  1393. $headers = $file->headers;
  1394. }
  1395. }
  1396. else
  1397. {
  1398. unset($file);
  1399. }
  1400. }
  1401. }
  1402. // If the cache is still valid, just return true
  1403. else
  1404. {
  1405. return true;
  1406. }
  1407. }
  1408. // If the cache is empty, delete it
  1409. else
  1410. {
  1411. $cache->unlink();
  1412. $this->data = array();
  1413. }
  1414. }
  1415. // 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.
  1416. if (!isset($file))
  1417. {
  1418. if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
  1419. {
  1420. $file =& $this->file;
  1421. }
  1422. else
  1423. {
  1424. $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
  1425. }
  1426. }
  1427. // If the file connection has an error, set SimplePie::error to that and quit
  1428. if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  1429. {
  1430. $this->error = $file->error;
  1431. if (!empty($this->data))
  1432. {
  1433. return true;
  1434. }
  1435. else
  1436. {
  1437. return false;
  1438. }
  1439. }
  1440. if (!$this->force_feed)
  1441. {
  1442. // Check if the supplied URL is a feed, if it isn't, look for it.
  1443. $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
  1444. if (!$locate->is_feed($file))
  1445. {
  1446. // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
  1447. unset($file);
  1448. if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
  1449. {
  1450. if ($cache)
  1451. {
  1452. $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
  1453. if (!$cache->save($this))
  1454. {
  1455. 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);
  1456. }
  1457. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
  1458. }
  1459. $this->feed_url = $file->url;
  1460. }
  1461. else
  1462. {
  1463. $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.";
  1464. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1465. return false;
  1466. }
  1467. }
  1468. $locate = null;
  1469. }
  1470. $headers = $file->headers;
  1471. $data = $file->body;
  1472. $sniffer = new $this->content_type_sniffer_class($file);
  1473. $sniffed = $sniffer->get_type();
  1474. }
  1475. else
  1476. {
  1477. $data = $this->raw_data;
  1478. }
  1479. // Set up array of possible encodings
  1480. $encodings = array();
  1481. // First check to see if input has been overridden.
  1482. if ($this->input_encoding !== false)
  1483. {
  1484. $encodings[] = $this->input_encoding;
  1485. }
  1486. $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
  1487. $text_types = array('text/xml', 'text/xml-external-parsed-entity');
  1488. // RFC 3023 (only applies to sniffed content)
  1489. if (isset($sniffed))
  1490. {
  1491. if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
  1492. {
  1493. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1494. {
  1495. $encodings[] = strtoupper($charset[1]);
  1496. }
  1497. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  1498. $encodings[] = 'UTF-8';
  1499. }
  1500. elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
  1501. {
  1502. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1503. {
  1504. $encodings[] = $charset[1];
  1505. }
  1506. $encodings[] = 'US-ASCII';
  1507. }
  1508. // Text MIME-type default
  1509. elseif (substr($sniffed, 0, 5) === 'text/')
  1510. {
  1511. $encodings[] = 'US-ASCII';
  1512. }
  1513. }
  1514. // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
  1515. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  1516. $encodings[] = 'UTF-8';
  1517. $encodings[] = 'ISO-8859-1';
  1518. // There's no point in trying an encoding twice
  1519. $encodings = array_unique($encodings);
  1520. // If we want the XML, just output that with the most likely encoding and quit
  1521. if ($this->xml_dump)
  1522. {
  1523. header('Content-type: text/xml; charset=' . $encodings[0]);
  1524. echo $data;
  1525. exit;
  1526. }
  1527. // Loop through each possible encoding, till we return something, or run out of possibilities
  1528. foreach ($encodings as $encoding)
  1529. {
  1530. // Change the encoding to UTF-8 (as we always use UTF-8 internally)
  1531. if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
  1532. {
  1533. // Create new parser
  1534. $parser = new $this->parser_class();
  1535. // If it's parsed fine
  1536. if ($parser->parse($utf8_data, 'UTF-8'))
  1537. {
  1538. $this->data = $parser->get_data();
  1539. if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
  1540. {
  1541. if (isset($headers))
  1542. {
  1543. $this->data['headers'] = $headers;
  1544. }
  1545. $this->data['build'] = SIMPLEPIE_BUILD;
  1546. // Cache the file if caching is enabled
  1547. if ($cache && !$cache->save($this))
  1548. {
  1549. 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);
  1550. }
  1551. return true;
  1552. }
  1553. else
  1554. {
  1555. $this->error = "A feed could not be found at $this->feed_url. This does not appear to be a valid RSS or Atom feed.";
  1556. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1557. return false;
  1558. }
  1559. }
  1560. }
  1561. }
  1562. if (isset($parser))
  1563. {
  1564. // We have an error, just set SimplePie_Misc::error to it and quit
  1565. $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());
  1566. }
  1567. else
  1568. {
  1569. $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.';
  1570. }
  1571. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1572. return false;
  1573. }
  1574. elseif (!empty($this->multifeed_url))
  1575. {
  1576. $i = 0;
  1577. $success = 0;
  1578. $this->multifeed_objects = array();
  1579. foreach ($this->multifeed_url as $url)
  1580. {
  1581. $this->multifeed_objects[$i] = clone $this;
  1582. $this->multifeed_objects[$i]->set_feed_url($url);
  1583. $success |= $this->multifeed_objects[$i]->init();
  1584. $i++;
  1585. }
  1586. return (bool) $success;
  1587. }
  1588. else
  1589. {
  1590. return false;
  1591. }
  1592. }
  1593. /**
  1594. * Return the error message for the occured error
  1595. *
  1596. * @access public
  1597. * @return string Error message
  1598. */
  1599. public function error()
  1600. {
  1601. return $this->error;
  1602. }
  1603. public function get_encoding()
  1604. {
  1605. return $this->sanitize->output_encoding;
  1606. }
  1607. public function handle_content_type($mime = 'text/html')
  1608. {
  1609. if (!headers_sent())
  1610. {
  1611. $header = "Content-type: $mime;";
  1612. if ($this->get_encoding())
  1613. {
  1614. $header .= ' charset=' . $this->get_encoding();
  1615. }
  1616. else
  1617. {
  1618. $header .= ' charset=UTF-8';
  1619. }
  1620. header($header);
  1621. }
  1622. }
  1623. public function get_type()
  1624. {
  1625. if (!isset($this->data['type']))
  1626. {
  1627. $this->data['type'] = SIMPLEPIE_TYPE_ALL;
  1628. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
  1629. {
  1630. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
  1631. }
  1632. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
  1633. {
  1634. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
  1635. }
  1636. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
  1637. {
  1638. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
  1639. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
  1640. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
  1641. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
  1642. {
  1643. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
  1644. }
  1645. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
  1646. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
  1647. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
  1648. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
  1649. {
  1650. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
  1651. }
  1652. }
  1653. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
  1654. {
  1655. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
  1656. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1657. {
  1658. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1659. {
  1660. case '0.91':
  1661. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
  1662. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1663. {
  1664. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1665. {
  1666. case '0':
  1667. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
  1668. break;
  1669. case '24':
  1670. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
  1671. break;
  1672. }
  1673. }
  1674. break;
  1675. case '0.92':
  1676. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
  1677. break;
  1678. case '0.93':
  1679. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
  1680. break;
  1681. case '0.94':
  1682. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
  1683. break;
  1684. case '2.0':
  1685. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
  1686. break;
  1687. }
  1688. }
  1689. }
  1690. else
  1691. {
  1692. $this->data['type'] = SIMPLEPIE_TYPE_NONE;
  1693. }
  1694. }
  1695. return $this->data['type'];
  1696. }
  1697. /**
  1698. * @todo If we have a perm redirect we should return the new URL
  1699. * @todo When we make the above change, let's support <itunes:new-feed-url> as well
  1700. * @todo Also, |atom:link|@rel=self
  1701. */
  1702. public function subscribe_url()
  1703. {
  1704. if ($this->feed_url !== null)
  1705. {
  1706. return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
  1707. }
  1708. else
  1709. {
  1710. return null;
  1711. }
  1712. }
  1713. public function get_feed_tags($namespace, $tag)
  1714. {
  1715. $type = $this->get_type();
  1716. if ($type & SIMPLEPIE_TYPE_ATOM_10)
  1717. {
  1718. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
  1719. {
  1720. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
  1721. }
  1722. }
  1723. if ($type & SIMPLEPIE_TYPE_ATOM_03)
  1724. {
  1725. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
  1726. {
  1727. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
  1728. }
  1729. }
  1730. if ($type & SIMPLEPIE_TYPE_RSS_RDF)
  1731. {
  1732. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
  1733. {
  1734. return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
  1735. }
  1736. }
  1737. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1738. {
  1739. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
  1740. {
  1741. return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
  1742. }
  1743. }
  1744. return null;
  1745. }
  1746. public function get_channel_tags($namespace, $tag)
  1747. {
  1748. $type = $this->get_type();
  1749. if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
  1750. {
  1751. if ($return = $this->get_feed_tags($namespace, $tag))
  1752. {
  1753. return $return;
  1754. }
  1755. }
  1756. if ($type & SIMPLEPIE_TYPE_RSS_10)
  1757. {
  1758. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
  1759. {
  1760. if (isset($channel[0]['child'][$namespace][$tag]))
  1761. {
  1762. return $channel[0]['child'][$namespace][$tag];
  1763. }
  1764. }
  1765. }
  1766. if ($type & SIMPLEPIE_TYPE_RSS_090)
  1767. {
  1768. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
  1769. {
  1770. if (isset($channel[0]['child'][$namespace][$tag]))
  1771. {
  1772. return $channel[0]['child'][$namespace][$tag];
  1773. }
  1774. }
  1775. }
  1776. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1777. {
  1778. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
  1779. {
  1780. if (isset($channel[0]['child'][$namespace][$tag]))
  1781. {
  1782. return $channel[0]['child'][$namespace][$tag];
  1783. }
  1784. }
  1785. }
  1786. return null;
  1787. }
  1788. public function get_image_tags($namespace, $tag)
  1789. {
  1790. $type = $this->get_type();
  1791. if ($type & SIMPLEPIE_TYPE_RSS_10)
  1792. {
  1793. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
  1794. {
  1795. if (isset($image[0]['child'][$namespace][$tag]))
  1796. {
  1797. return $image[0]['child'][$namespace][$tag];
  1798. }
  1799. }
  1800. }
  1801. if ($type & SIMPLEPIE_TYPE_RSS_090)
  1802. {
  1803. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
  1804. {
  1805. if (isset($image[0]['child'][$namespace][$tag]))
  1806. {
  1807. return $image[0]['child'][$namespace][$tag];
  1808. }
  1809. }
  1810. }
  1811. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1812. {
  1813. if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
  1814. {
  1815. if (isset($image[0]['child'][$namespace][$tag]))
  1816. {
  1817. return $image[0]['child'][$namespace][$tag];
  1818. }
  1819. }
  1820. }
  1821. return null;
  1822. }
  1823. public function get_base($element = array())
  1824. {
  1825. if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
  1826. {
  1827. return $element['xml_base'];
  1828. }
  1829. elseif ($this->get_link() !== null)
  1830. {
  1831. return $this->get_link();
  1832. }
  1833. else
  1834. {
  1835. return $this->subscribe_url();
  1836. }
  1837. }
  1838. public function sanitize($data, $type, $base = '')
  1839. {
  1840. return $this->sanitize->sanitize($data, $type, $base);
  1841. }
  1842. public function get_title()
  1843. {
  1844. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  1845. {
  1846. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  1847. }
  1848. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  1849. {
  1850. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  1851. }
  1852. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  1853. {
  1854. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1855. }
  1856. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  1857. {
  1858. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1859. }
  1860. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  1861. {
  1862. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  1863. }
  1864. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  1865. {
  1866. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1867. }
  1868. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  1869. {
  1870. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1871. }
  1872. else
  1873. {
  1874. return null;
  1875. }
  1876. }
  1877. public function get_category($key = 0)
  1878. {
  1879. $categories = $this->get_categories();
  1880. if (isset($categories[$key]))
  1881. {
  1882. return $categories[$key];
  1883. }
  1884. else
  1885. {
  1886. return null;
  1887. }
  1888. }
  1889. public function get_categories()
  1890. {
  1891. $categories = array();
  1892. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  1893. {
  1894. $term = null;
  1895. $scheme = null;
  1896. $label = null;
  1897. if (isset($category['attribs']['']['term']))
  1898. {
  1899. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  1900. }
  1901. if (isset($category['attribs']['']['scheme']))
  1902. {
  1903. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  1904. }
  1905. if (isset($category['attribs']['']['label']))
  1906. {
  1907. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  1908. }
  1909. $categories[] = new $this->category_class($term, $scheme, $label);
  1910. }
  1911. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  1912. {
  1913. // This is really the label, but keep this as the term also for BC.
  1914. // Label will also work on retrieving because that falls back to term.
  1915. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1916. if (isset($category['attribs']['']['domain']))
  1917. {
  1918. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  1919. }
  1920. else
  1921. {
  1922. $scheme = null;
  1923. }
  1924. $categories[] = new $this->category_class($term, $scheme, null);
  1925. }
  1926. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  1927. {
  1928. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  1929. }
  1930. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  1931. {
  1932. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  1933. }
  1934. if (!empty($categories))
  1935. {
  1936. return SimplePie_Misc::array_unique($categories);
  1937. }
  1938. else
  1939. {
  1940. return null;
  1941. }
  1942. }
  1943. public function get_author($key = 0)
  1944. {
  1945. $authors = $this->get_authors();
  1946. if (isset($authors[$key]))
  1947. {
  1948. return $authors[$key];
  1949. }
  1950. else
  1951. {
  1952. return null;
  1953. }
  1954. }
  1955. public function get_authors()
  1956. {
  1957. $authors = array();
  1958. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  1959. {
  1960. $name = null;
  1961. $uri = null;
  1962. $email = null;
  1963. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  1964. {
  1965. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1966. }
  1967. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  1968. {
  1969. $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]));
  1970. }
  1971. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  1972. {
  1973. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1974. }
  1975. if ($name !== null || $email !== null || $uri !== null)
  1976. {
  1977. $authors[] = new $this->author_class($name, $uri, $email);
  1978. }
  1979. }
  1980. if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  1981. {
  1982. $name = null;
  1983. $url = null;
  1984. $email = null;
  1985. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  1986. {
  1987. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1988. }
  1989. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  1990. {
  1991. $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]));
  1992. }
  1993. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  1994. {
  1995. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  1996. }
  1997. if ($name !== null || $email !== null || $url !== null)
  1998. {
  1999. $authors[] = new $this->author_class($name, $url, $email);
  2000. }
  2001. }
  2002. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  2003. {
  2004. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2005. }
  2006. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  2007. {
  2008. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2009. }
  2010. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  2011. {
  2012. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2013. }
  2014. if (!empty($authors))
  2015. {
  2016. return SimplePie_Misc::array_unique($authors);
  2017. }
  2018. else
  2019. {
  2020. return null;
  2021. }
  2022. }
  2023. public function get_contributor($key = 0)
  2024. {
  2025. $contributors = $this->get_contributors();
  2026. if (isset($contributors[$key]))
  2027. {
  2028. return $contributors[$key];
  2029. }
  2030. else
  2031. {
  2032. return null;
  2033. }
  2034. }
  2035. public function get_contributors()
  2036. {
  2037. $contributors = array();
  2038. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  2039. {
  2040. $name = null;
  2041. $uri = null;
  2042. $email = null;
  2043. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2044. {
  2045. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2046. }
  2047. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2048. {
  2049. $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]));
  2050. }
  2051. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2052. {
  2053. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2054. }
  2055. if ($name !== null || $email !== null || $uri !== null)
  2056. {
  2057. $contributors[] = new $this->author_class($name, $uri, $email);
  2058. }
  2059. }
  2060. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  2061. {
  2062. $name = null;
  2063. $url = null;
  2064. $email = null;
  2065. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2066. {
  2067. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2068. }
  2069. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2070. {
  2071. $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]));
  2072. }
  2073. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2074. {
  2075. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2076. }
  2077. if ($name !== null || $email !== null || $url !== null)
  2078. {
  2079. $contributors[] = new $this->author_class($name, $url, $email);
  2080. }
  2081. }
  2082. if (!empty($contributors))
  2083. {
  2084. return SimplePie_Misc::array_unique($contributors);
  2085. }
  2086. else
  2087. {
  2088. return null;
  2089. }
  2090. }
  2091. public function get_link($key = 0, $rel = 'alternate')
  2092. {
  2093. $links = $this->get_links($rel);
  2094. if (isset($links[$key]))
  2095. {
  2096. return $links[$key];
  2097. }
  2098. else
  2099. {
  2100. return null;
  2101. }
  2102. }
  2103. /**
  2104. * Added for parity between the parent-level and the item/entry-level.
  2105. */
  2106. public function get_permalink()
  2107. {
  2108. return $this->get_link(0);
  2109. }
  2110. public function get_links($rel = 'alternate')
  2111. {
  2112. if (!isset($this->data['links']))
  2113. {
  2114. $this->data['links'] = array();
  2115. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  2116. {
  2117. foreach ($links as $link)
  2118. {
  2119. if (isset($link['attribs']['']['href']))
  2120. {
  2121. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2122. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2123. }
  2124. }
  2125. }
  2126. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  2127. {
  2128. foreach ($links as $link)
  2129. {
  2130. if (isset($link['attribs']['']['href']))
  2131. {
  2132. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2133. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2134. }
  2135. }
  2136. }
  2137. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2138. {
  2139. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2140. }
  2141. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2142. {
  2143. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2144. }
  2145. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2146. {
  2147. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2148. }
  2149. $keys = array_keys($this->data['links']);
  2150. foreach ($keys as $key)
  2151. {
  2152. if (SimplePie_Misc::is_isegment_nz_nc($key))
  2153. {
  2154. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  2155. {
  2156. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  2157. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  2158. }
  2159. else
  2160. {
  2161. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  2162. }
  2163. }
  2164. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  2165. {
  2166. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  2167. }
  2168. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  2169. }
  2170. }
  2171. if (isset($this->data['links'][$rel]))
  2172. {
  2173. return $this->data['links'][$rel];
  2174. }
  2175. else
  2176. {
  2177. return null;
  2178. }
  2179. }
  2180. public function get_all_discovered_feeds()
  2181. {
  2182. return $this->all_discovered_feeds;
  2183. }
  2184. public function get_description()
  2185. {
  2186. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  2187. {
  2188. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2189. }
  2190. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  2191. {
  2192. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2193. }
  2194. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2195. {
  2196. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2197. }
  2198. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  2199. {
  2200. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2201. }
  2202. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2203. {
  2204. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2205. }
  2206. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  2207. {
  2208. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2209. }
  2210. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  2211. {
  2212. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2213. }
  2214. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  2215. {
  2216. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2217. }
  2218. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  2219. {
  2220. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2221. }
  2222. else
  2223. {
  2224. return null;
  2225. }
  2226. }
  2227. public function get_copyright()
  2228. {
  2229. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  2230. {
  2231. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2232. }
  2233. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  2234. {
  2235. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2236. }
  2237. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  2238. {
  2239. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2240. }
  2241. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  2242. {
  2243. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2244. }
  2245. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  2246. {
  2247. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2248. }
  2249. else
  2250. {
  2251. return null;
  2252. }
  2253. }
  2254. public function get_language()
  2255. {
  2256. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  2257. {
  2258. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2259. }
  2260. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  2261. {
  2262. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2263. }
  2264. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  2265. {
  2266. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2267. }
  2268. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
  2269. {
  2270. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2271. }
  2272. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
  2273. {
  2274. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2275. }
  2276. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
  2277. {
  2278. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2279. }
  2280. elseif (isset($this->data['headers']['content-language']))
  2281. {
  2282. return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
  2283. }
  2284. else
  2285. {
  2286. return null;
  2287. }
  2288. }
  2289. public function get_latitude()
  2290. {
  2291. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  2292. {
  2293. return (float) $return[0]['data'];
  2294. }
  2295. 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))
  2296. {
  2297. return (float) $match[1];
  2298. }
  2299. else
  2300. {
  2301. return null;
  2302. }
  2303. }
  2304. public function get_longitude()
  2305. {
  2306. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  2307. {
  2308. return (float) $return[0]['data'];
  2309. }
  2310. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  2311. {
  2312. return (float) $return[0]['data'];
  2313. }
  2314. 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))
  2315. {
  2316. return (float) $match[2];
  2317. }
  2318. else
  2319. {
  2320. return null;
  2321. }
  2322. }
  2323. public function get_image_title()
  2324. {
  2325. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2326. {
  2327. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2328. }
  2329. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2330. {
  2331. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2332. }
  2333. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2334. {
  2335. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2336. }
  2337. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2338. {
  2339. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2340. }
  2341. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2342. {
  2343. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2344. }
  2345. else
  2346. {
  2347. return null;
  2348. }
  2349. }
  2350. public function get_image_url()
  2351. {
  2352. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  2353. {
  2354. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  2355. }
  2356. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  2357. {
  2358. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2359. }
  2360. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  2361. {
  2362. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2363. }
  2364. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
  2365. {
  2366. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2367. }
  2368. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
  2369. {
  2370. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2371. }
  2372. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2373. {
  2374. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2375. }
  2376. else
  2377. {
  2378. return null;
  2379. }
  2380. }
  2381. public function get_image_link()
  2382. {
  2383. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2384. {
  2385. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2386. }
  2387. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2388. {
  2389. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2390. }
  2391. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2392. {
  2393. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2394. }
  2395. else
  2396. {
  2397. return null;
  2398. }
  2399. }
  2400. public function get_image_width()
  2401. {
  2402. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
  2403. {
  2404. return round($return[0]['data']);
  2405. }
  2406. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2407. {
  2408. return 88.0;
  2409. }
  2410. else
  2411. {
  2412. return null;
  2413. }
  2414. }
  2415. public function get_image_height()
  2416. {
  2417. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
  2418. {
  2419. return round($return[0]['data']);
  2420. }
  2421. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2422. {
  2423. return 31.0;
  2424. }
  2425. else
  2426. {
  2427. return null;
  2428. }
  2429. }
  2430. public function get_item_quantity($max = 0)
  2431. {
  2432. $max = (int) $max;
  2433. $qty = count($this->get_items());
  2434. if ($max === 0)
  2435. {
  2436. return $qty;
  2437. }
  2438. else
  2439. {
  2440. return ($qty > $max) ? $max : $qty;
  2441. }
  2442. }
  2443. public function get_item($key = 0)
  2444. {
  2445. $items = $this->get_items();
  2446. if (isset($items[$key]))
  2447. {
  2448. return $items[$key];
  2449. }
  2450. else
  2451. {
  2452. return null;
  2453. }
  2454. }
  2455. public function get_items($start = 0, $end = 0)
  2456. {
  2457. if (!isset($this->data['items']))
  2458. {
  2459. if (!empty($this->multifeed_objects))
  2460. {
  2461. $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
  2462. }
  2463. else
  2464. {
  2465. $this->data['items'] = array();
  2466. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
  2467. {
  2468. $keys = array_keys($items);
  2469. foreach ($keys as $key)
  2470. {
  2471. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2472. }
  2473. }
  2474. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
  2475. {
  2476. $keys = array_keys($items);
  2477. foreach ($keys as $key)
  2478. {
  2479. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2480. }
  2481. }
  2482. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
  2483. {
  2484. $keys = array_keys($items);
  2485. foreach ($keys as $key)
  2486. {
  2487. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2488. }
  2489. }
  2490. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
  2491. {
  2492. $keys = array_keys($items);
  2493. foreach ($keys as $key)
  2494. {
  2495. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2496. }
  2497. }
  2498. if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
  2499. {
  2500. $keys = array_keys($items);
  2501. foreach ($keys as $key)
  2502. {
  2503. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2504. }
  2505. }
  2506. }
  2507. }
  2508. if (!empty($this->data['items']))
  2509. {
  2510. // If we want to order it by date, check if all items have a date, and then sort it
  2511. if ($this->order_by_date && empty($this->multifeed_objects))
  2512. {
  2513. if (!isset($this->data['ordered_items']))
  2514. {
  2515. $do_sort = true;
  2516. foreach ($this->data['items'] as $item)
  2517. {
  2518. if (!$item->get_date('U'))
  2519. {
  2520. $do_sort = false;
  2521. break;
  2522. }
  2523. }
  2524. $item = null;
  2525. $this->data['ordered_items'] = $this->data['items'];
  2526. if ($do_sort)
  2527. {
  2528. usort($this->data['ordered_items'], array(&$this, 'sort_items'));
  2529. }
  2530. }
  2531. $items = $this->data['ordered_items'];
  2532. }
  2533. else
  2534. {
  2535. $items = $this->data['items'];
  2536. }
  2537. // Slice the data as desired
  2538. if ($end === 0)
  2539. {
  2540. return array_slice($items, $start);
  2541. }
  2542. else
  2543. {
  2544. return array_slice($items, $start, $end);
  2545. }
  2546. }
  2547. else
  2548. {
  2549. return array();
  2550. }
  2551. }
  2552. /**
  2553. * @static
  2554. */
  2555. public function sort_items($a, $b)
  2556. {
  2557. return $a->get_date('U') <= $b->get_date('U');
  2558. }
  2559. /**
  2560. * @static
  2561. */
  2562. public function merge_items($urls, $start = 0, $end = 0, $limit = 0)
  2563. {
  2564. if (is_array($urls) && sizeof($urls) > 0)
  2565. {
  2566. $items = array();
  2567. foreach ($urls as $arg)
  2568. {
  2569. if (is_a($arg, 'SimplePie'))
  2570. {
  2571. $items = array_merge($items, $arg->get_items(0, $limit));
  2572. }
  2573. else
  2574. {
  2575. trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
  2576. }
  2577. }
  2578. $do_sort = true;
  2579. foreach ($items as $item)
  2580. {
  2581. if (!$item->get_date('U'))
  2582. {
  2583. $do_sort = false;
  2584. break;
  2585. }
  2586. }
  2587. $item = null;
  2588. if ($do_sort)
  2589. {
  2590. usort($items, array('SimplePie', 'sort_items'));
  2591. }
  2592. if ($end === 0)
  2593. {
  2594. return array_slice($items, $start);
  2595. }
  2596. else
  2597. {
  2598. return array_slice($items, $start, $end);
  2599. }
  2600. }
  2601. else
  2602. {
  2603. trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
  2604. return array();
  2605. }
  2606. }
  2607. }
  2608. class SimplePie_Item
  2609. {
  2610. var $feed;
  2611. var $data = array();
  2612. public function __construct($feed, $data)
  2613. {
  2614. $this->feed = $feed;
  2615. $this->data = $data;
  2616. }
  2617. public function __toString()
  2618. {
  2619. return md5(serialize($this->data));
  2620. }
  2621. /**
  2622. * Remove items that link back to this before destroying this object
  2623. */
  2624. public function __destruct()
  2625. {
  2626. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  2627. {
  2628. unset($this->feed);
  2629. }
  2630. }
  2631. public function get_item_tags($namespace, $tag)
  2632. {
  2633. if (isset($this->data['child'][$namespace][$tag]))
  2634. {
  2635. return $this->data['child'][$namespace][$tag];
  2636. }
  2637. else
  2638. {
  2639. return null;
  2640. }
  2641. }
  2642. public function get_base($element = array())
  2643. {
  2644. return $this->feed->get_base($element);
  2645. }
  2646. public function sanitize($data, $type, $base = '')
  2647. {
  2648. return $this->feed->sanitize($data, $type, $base);
  2649. }
  2650. public function get_feed()
  2651. {
  2652. return $this->feed;
  2653. }
  2654. public function get_id($hash = false)
  2655. {
  2656. if (!$hash)
  2657. {
  2658. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
  2659. {
  2660. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2661. }
  2662. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
  2663. {
  2664. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2665. }
  2666. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  2667. {
  2668. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2669. }
  2670. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
  2671. {
  2672. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2673. }
  2674. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
  2675. {
  2676. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2677. }
  2678. elseif (($return = $this->get_permalink()) !== null)
  2679. {
  2680. return $return;
  2681. }
  2682. elseif (($return = $this->get_title()) !== null)
  2683. {
  2684. return $return;
  2685. }
  2686. }
  2687. if ($this->get_permalink() !== null || $this->get_title() !== null)
  2688. {
  2689. return md5($this->get_permalink() . $this->get_title());
  2690. }
  2691. else
  2692. {
  2693. return md5(serialize($this->data));
  2694. }
  2695. }
  2696. public function get_title()
  2697. {
  2698. if (!isset($this->data['title']))
  2699. {
  2700. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  2701. {
  2702. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2703. }
  2704. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  2705. {
  2706. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2707. }
  2708. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2709. {
  2710. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2711. }
  2712. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2713. {
  2714. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2715. }
  2716. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2717. {
  2718. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2719. }
  2720. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2721. {
  2722. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2723. }
  2724. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2725. {
  2726. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2727. }
  2728. else
  2729. {
  2730. $this->data['title'] = null;
  2731. }
  2732. }
  2733. return $this->data['title'];
  2734. }
  2735. public function get_description($description_only = false)
  2736. {
  2737. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
  2738. {
  2739. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2740. }
  2741. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
  2742. {
  2743. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2744. }
  2745. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2746. {
  2747. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2748. }
  2749. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2750. {
  2751. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2752. }
  2753. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  2754. {
  2755. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2756. }
  2757. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  2758. {
  2759. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2760. }
  2761. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  2762. {
  2763. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2764. }
  2765. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  2766. {
  2767. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2768. }
  2769. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  2770. {
  2771. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML);
  2772. }
  2773. elseif (!$description_only)
  2774. {
  2775. return $this->get_content(true);
  2776. }
  2777. else
  2778. {
  2779. return null;
  2780. }
  2781. }
  2782. public function get_content($content_only = false)
  2783. {
  2784. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
  2785. {
  2786. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2787. }
  2788. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
  2789. {
  2790. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2791. }
  2792. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
  2793. {
  2794. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2795. }
  2796. elseif (!$content_only)
  2797. {
  2798. return $this->get_description(true);
  2799. }
  2800. else
  2801. {
  2802. return null;
  2803. }
  2804. }
  2805. public function get_category($key = 0)
  2806. {
  2807. $categories = $this->get_categories();
  2808. if (isset($categories[$key]))
  2809. {
  2810. return $categories[$key];
  2811. }
  2812. else
  2813. {
  2814. return null;
  2815. }
  2816. }
  2817. public function get_categories()
  2818. {
  2819. $categories = array();
  2820. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  2821. {
  2822. $term = null;
  2823. $scheme = null;
  2824. $label = null;
  2825. if (isset($category['attribs']['']['term']))
  2826. {
  2827. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  2828. }
  2829. if (isset($category['attribs']['']['scheme']))
  2830. {
  2831. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  2832. }
  2833. if (isset($category['attribs']['']['label']))
  2834. {
  2835. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  2836. }
  2837. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  2838. }
  2839. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  2840. {
  2841. // This is really the label, but keep this as the term also for BC.
  2842. // Label will also work on retrieving because that falls back to term.
  2843. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2844. if (isset($category['attribs']['']['domain']))
  2845. {
  2846. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  2847. }
  2848. else
  2849. {
  2850. $scheme = null;
  2851. }
  2852. $categories[] = new $this->feed->category_class($term, $scheme, null);
  2853. }
  2854. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  2855. {
  2856. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2857. }
  2858. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  2859. {
  2860. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2861. }
  2862. if (!empty($categories))
  2863. {
  2864. return SimplePie_Misc::array_unique($categories);
  2865. }
  2866. else
  2867. {
  2868. return null;
  2869. }
  2870. }
  2871. public function get_author($key = 0)
  2872. {
  2873. $authors = $this->get_authors();
  2874. if (isset($authors[$key]))
  2875. {
  2876. return $authors[$key];
  2877. }
  2878. else
  2879. {
  2880. return null;
  2881. }
  2882. }
  2883. public function get_contributor($key = 0)
  2884. {
  2885. $contributors = $this->get_contributors();
  2886. if (isset($contributors[$key]))
  2887. {
  2888. return $contributors[$key];
  2889. }
  2890. else
  2891. {
  2892. return null;
  2893. }
  2894. }
  2895. public function get_contributors()
  2896. {
  2897. $contributors = array();
  2898. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  2899. {
  2900. $name = null;
  2901. $uri = null;
  2902. $email = null;
  2903. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2904. {
  2905. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2906. }
  2907. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2908. {
  2909. $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]));
  2910. }
  2911. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2912. {
  2913. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2914. }
  2915. if ($name !== null || $email !== null || $uri !== null)
  2916. {
  2917. $contributors[] = new $this->feed->author_class($name, $uri, $email);
  2918. }
  2919. }
  2920. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  2921. {
  2922. $name = null;
  2923. $url = null;
  2924. $email = null;
  2925. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2926. {
  2927. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2928. }
  2929. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2930. {
  2931. $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]));
  2932. }
  2933. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2934. {
  2935. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2936. }
  2937. if ($name !== null || $email !== null || $url !== null)
  2938. {
  2939. $contributors[] = new $this->feed->author_class($name, $url, $email);
  2940. }
  2941. }
  2942. if (!empty($contributors))
  2943. {
  2944. return SimplePie_Misc::array_unique($contributors);
  2945. }
  2946. else
  2947. {
  2948. return null;
  2949. }
  2950. }
  2951. public function get_authors()
  2952. {
  2953. $authors = array();
  2954. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  2955. {
  2956. $name = null;
  2957. $uri = null;
  2958. $email = null;
  2959. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2960. {
  2961. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2962. }
  2963. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2964. {
  2965. $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]));
  2966. }
  2967. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2968. {
  2969. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2970. }
  2971. if ($name !== null || $email !== null || $uri !== null)
  2972. {
  2973. $authors[] = new $this->feed->author_class($name, $uri, $email);
  2974. }
  2975. }
  2976. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  2977. {
  2978. $name = null;
  2979. $url = null;
  2980. $email = null;
  2981. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2982. {
  2983. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2984. }
  2985. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2986. {
  2987. $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]));
  2988. }
  2989. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2990. {
  2991. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2992. }
  2993. if ($name !== null || $email !== null || $url !== null)
  2994. {
  2995. $authors[] = new $this->feed->author_class($name, $url, $email);
  2996. }
  2997. }
  2998. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
  2999. {
  3000. $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3001. }
  3002. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  3003. {
  3004. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3005. }
  3006. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  3007. {
  3008. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3009. }
  3010. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  3011. {
  3012. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3013. }
  3014. if (!empty($authors))
  3015. {
  3016. return SimplePie_Misc::array_unique($authors);
  3017. }
  3018. elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
  3019. {
  3020. return $authors;
  3021. }
  3022. elseif ($authors = $this->feed->get_authors())
  3023. {
  3024. return $authors;
  3025. }
  3026. else
  3027. {
  3028. return null;
  3029. }
  3030. }
  3031. public function get_copyright()
  3032. {
  3033. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  3034. {
  3035. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3036. }
  3037. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  3038. {
  3039. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3040. }
  3041. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  3042. {
  3043. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3044. }
  3045. else
  3046. {
  3047. return null;
  3048. }
  3049. }
  3050. public function get_date($date_format = 'j F Y, g:i a')
  3051. {
  3052. if (!isset($this->data['date']))
  3053. {
  3054. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
  3055. {
  3056. $this->data['date']['raw'] = $return[0]['data'];
  3057. }
  3058. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
  3059. {
  3060. $this->data['date']['raw'] = $return[0]['data'];
  3061. }
  3062. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
  3063. {
  3064. $this->data['date']['raw'] = $return[0]['data'];
  3065. }
  3066. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
  3067. {
  3068. $this->data['date']['raw'] = $return[0]['data'];
  3069. }
  3070. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
  3071. {
  3072. $this->data['date']['raw'] = $return[0]['data'];
  3073. }
  3074. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
  3075. {
  3076. $this->data['date']['raw'] = $return[0]['data'];
  3077. }
  3078. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
  3079. {
  3080. $this->data['date']['raw'] = $return[0]['data'];
  3081. }
  3082. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
  3083. {
  3084. $this->data['date']['raw'] = $return[0]['data'];
  3085. }
  3086. if (!empty($this->data['date']['raw']))
  3087. {
  3088. $parser = SimplePie_Parse_Date::get();
  3089. $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
  3090. }
  3091. else
  3092. {
  3093. $this->data['date'] = null;
  3094. }
  3095. }
  3096. if ($this->data['date'])
  3097. {
  3098. $date_format = (string) $date_format;
  3099. switch ($date_format)
  3100. {
  3101. case '':
  3102. return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
  3103. case 'U':
  3104. return $this->data['date']['parsed'];
  3105. default:
  3106. return date($date_format, $this->data['date']['parsed']);
  3107. }
  3108. }
  3109. else
  3110. {
  3111. return null;
  3112. }
  3113. }
  3114. public function get_local_date($date_format = '%c')
  3115. {
  3116. if (!$date_format)
  3117. {
  3118. return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
  3119. }
  3120. elseif (($date = $this->get_date('U')) !== null && $date !== false)
  3121. {
  3122. return strftime($date_format, $date);
  3123. }
  3124. else
  3125. {
  3126. return null;
  3127. }
  3128. }
  3129. public function get_permalink()
  3130. {
  3131. $link = $this->get_link();
  3132. $enclosure = $this->get_enclosure(0);
  3133. if ($link !== null)
  3134. {
  3135. return $link;
  3136. }
  3137. elseif ($enclosure !== null)
  3138. {
  3139. return $enclosure->get_link();
  3140. }
  3141. else
  3142. {
  3143. return null;
  3144. }
  3145. }
  3146. public function get_link($key = 0, $rel = 'alternate')
  3147. {
  3148. $links = $this->get_links($rel);
  3149. if ($links[$key] !== null)
  3150. {
  3151. return $links[$key];
  3152. }
  3153. else
  3154. {
  3155. return null;
  3156. }
  3157. }
  3158. public function get_links($rel = 'alternate')
  3159. {
  3160. if (!isset($this->data['links']))
  3161. {
  3162. $this->data['links'] = array();
  3163. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  3164. {
  3165. if (isset($link['attribs']['']['href']))
  3166. {
  3167. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3168. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3169. }
  3170. }
  3171. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  3172. {
  3173. if (isset($link['attribs']['']['href']))
  3174. {
  3175. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3176. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3177. }
  3178. }
  3179. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  3180. {
  3181. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3182. }
  3183. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  3184. {
  3185. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3186. }
  3187. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  3188. {
  3189. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3190. }
  3191. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  3192. {
  3193. if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
  3194. {
  3195. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3196. }
  3197. }
  3198. $keys = array_keys($this->data['links']);
  3199. foreach ($keys as $key)
  3200. {
  3201. if (SimplePie_Misc::is_isegment_nz_nc($key))
  3202. {
  3203. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  3204. {
  3205. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  3206. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  3207. }
  3208. else
  3209. {
  3210. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  3211. }
  3212. }
  3213. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  3214. {
  3215. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  3216. }
  3217. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  3218. }
  3219. }
  3220. if (isset($this->data['links'][$rel]))
  3221. {
  3222. return $this->data['links'][$rel];
  3223. }
  3224. else
  3225. {
  3226. return null;
  3227. }
  3228. }
  3229. /**
  3230. * @todo Add ability to prefer one type of content over another (in a media group).
  3231. */
  3232. public function get_enclosure($key = 0, $prefer = null)
  3233. {
  3234. $enclosures = $this->get_enclosures();
  3235. if (isset($enclosures[$key]))
  3236. {
  3237. return $enclosures[$key];
  3238. }
  3239. else
  3240. {
  3241. return null;
  3242. }
  3243. }
  3244. /**
  3245. * Grabs all available enclosures (podcasts, etc.)
  3246. *
  3247. * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
  3248. *
  3249. * 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.
  3250. *
  3251. * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
  3252. * @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).
  3253. */
  3254. public function get_enclosures()
  3255. {
  3256. if (!isset($this->data['enclosures']))
  3257. {
  3258. $this->data['enclosures'] = array();
  3259. // Elements
  3260. $captions_parent = null;
  3261. $categories_parent = null;
  3262. $copyrights_parent = null;
  3263. $credits_parent = null;
  3264. $description_parent = null;
  3265. $duration_parent = null;
  3266. $hashes_parent = null;
  3267. $keywords_parent = null;
  3268. $player_parent = null;
  3269. $ratings_parent = null;
  3270. $restrictions_parent = null;
  3271. $thumbnails_parent = null;
  3272. $title_parent = null;
  3273. // Let's do the channel and item-level ones first, and just re-use them if we need to.
  3274. $parent = $this->get_feed();
  3275. // CAPTIONS
  3276. if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  3277. {
  3278. foreach ($captions as $caption)
  3279. {
  3280. $caption_type = null;
  3281. $caption_lang = null;
  3282. $caption_startTime = null;
  3283. $caption_endTime = null;
  3284. $caption_text = null;
  3285. if (isset($caption['attribs']['']['type']))
  3286. {
  3287. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3288. }
  3289. if (isset($caption['attribs']['']['lang']))
  3290. {
  3291. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3292. }
  3293. if (isset($caption['attribs']['']['start']))
  3294. {
  3295. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  3296. }
  3297. if (isset($caption['attribs']['']['end']))
  3298. {
  3299. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  3300. }
  3301. if (isset($caption['data']))
  3302. {
  3303. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3304. }
  3305. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  3306. }
  3307. }
  3308. elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  3309. {
  3310. foreach ($captions as $caption)
  3311. {
  3312. $caption_type = null;
  3313. $caption_lang = null;
  3314. $caption_startTime = null;
  3315. $caption_endTime = null;
  3316. $caption_text = null;
  3317. if (isset($caption['attribs']['']['type']))
  3318. {
  3319. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3320. }
  3321. if (isset($caption['attribs']['']['lang']))
  3322. {
  3323. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3324. }
  3325. if (isset($caption['attribs']['']['start']))
  3326. {
  3327. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  3328. }
  3329. if (isset($caption['attribs']['']['end']))
  3330. {
  3331. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  3332. }
  3333. if (isset($caption['data']))
  3334. {
  3335. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3336. }
  3337. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  3338. }
  3339. }
  3340. if (is_array($captions_parent))
  3341. {
  3342. $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
  3343. }
  3344. // CATEGORIES
  3345. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  3346. {
  3347. $term = null;
  3348. $scheme = null;
  3349. $label = null;
  3350. if (isset($category['data']))
  3351. {
  3352. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3353. }
  3354. if (isset($category['attribs']['']['scheme']))
  3355. {
  3356. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3357. }
  3358. else
  3359. {
  3360. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  3361. }
  3362. if (isset($category['attribs']['']['label']))
  3363. {
  3364. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  3365. }
  3366. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3367. }
  3368. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  3369. {
  3370. $term = null;
  3371. $scheme = null;
  3372. $label = null;
  3373. if (isset($category['data']))
  3374. {
  3375. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3376. }
  3377. if (isset($category['attribs']['']['scheme']))
  3378. {
  3379. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3380. }
  3381. else
  3382. {
  3383. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  3384. }
  3385. if (isset($category['attribs']['']['label']))
  3386. {
  3387. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  3388. }
  3389. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3390. }
  3391. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
  3392. {
  3393. $term = null;
  3394. $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
  3395. $label = null;
  3396. if (isset($category['attribs']['']['text']))
  3397. {
  3398. $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  3399. }
  3400. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3401. if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
  3402. {
  3403. foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
  3404. {
  3405. if (isset($subcategory['attribs']['']['text']))
  3406. {
  3407. $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  3408. }
  3409. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3410. }
  3411. }
  3412. }
  3413. if (is_array($categories_parent))
  3414. {
  3415. $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
  3416. }
  3417. // COPYRIGHT
  3418. if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  3419. {
  3420. $copyright_url = null;
  3421. $copyright_label = null;
  3422. if (isset($copyright[0]['attribs']['']['url']))
  3423. {
  3424. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  3425. }
  3426. if (isset($copyright[0]['data']))
  3427. {
  3428. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3429. }
  3430. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  3431. }
  3432. elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  3433. {
  3434. $copyright_url = null;
  3435. $copyright_label = null;
  3436. if (isset($copyright[0]['attribs']['']['url']))
  3437. {
  3438. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  3439. }
  3440. if (isset($copyright[0]['data']))
  3441. {
  3442. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3443. }
  3444. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  3445. }
  3446. // CREDITS
  3447. if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  3448. {
  3449. foreach ($credits as $credit)
  3450. {
  3451. $credit_role = null;
  3452. $credit_scheme = null;
  3453. $credit_name = null;
  3454. if (isset($credit['attribs']['']['role']))
  3455. {
  3456. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  3457. }
  3458. if (isset($credit['attribs']['']['scheme']))
  3459. {
  3460. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3461. }
  3462. else
  3463. {
  3464. $credit_scheme = 'urn:ebu';
  3465. }
  3466. if (isset($credit['data']))
  3467. {
  3468. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3469. }
  3470. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  3471. }
  3472. }
  3473. elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  3474. {
  3475. foreach ($credits as $credit)
  3476. {
  3477. $credit_role = null;
  3478. $credit_scheme = null;
  3479. $credit_name = null;
  3480. if (isset($credit['attribs']['']['role']))
  3481. {
  3482. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  3483. }
  3484. if (isset($credit['attribs']['']['scheme']))
  3485. {
  3486. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3487. }
  3488. else
  3489. {
  3490. $credit_scheme = 'urn:ebu';
  3491. }
  3492. if (isset($credit['data']))
  3493. {
  3494. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3495. }
  3496. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  3497. }
  3498. }
  3499. if (is_array($credits_parent))
  3500. {
  3501. $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
  3502. }
  3503. // DESCRIPTION
  3504. if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  3505. {
  3506. if (isset($description_parent[0]['data']))
  3507. {
  3508. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3509. }
  3510. }
  3511. elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  3512. {
  3513. if (isset($description_parent[0]['data']))
  3514. {
  3515. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3516. }
  3517. }
  3518. // DURATION
  3519. if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
  3520. {
  3521. $seconds = null;
  3522. $minutes = null;
  3523. $hours = null;
  3524. if (isset($duration_parent[0]['data']))
  3525. {
  3526. $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3527. if (sizeof($temp) > 0)
  3528. {
  3529. $seconds = (int) array_pop($temp);
  3530. }
  3531. if (sizeof($temp) > 0)
  3532. {
  3533. $minutes = (int) array_pop($temp);
  3534. $seconds += $minutes * 60;
  3535. }
  3536. if (sizeof($temp) > 0)
  3537. {
  3538. $hours = (int) array_pop($temp);
  3539. $seconds += $hours * 3600;
  3540. }
  3541. unset($temp);
  3542. $duration_parent = $seconds;
  3543. }
  3544. }
  3545. // HASHES
  3546. if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  3547. {
  3548. foreach ($hashes_iterator as $hash)
  3549. {
  3550. $value = null;
  3551. $algo = null;
  3552. if (isset($hash['data']))
  3553. {
  3554. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3555. }
  3556. if (isset($hash['attribs']['']['algo']))
  3557. {
  3558. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  3559. }
  3560. else
  3561. {
  3562. $algo = 'md5';
  3563. }
  3564. $hashes_parent[] = $algo.':'.$value;
  3565. }
  3566. }
  3567. elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  3568. {
  3569. foreach ($hashes_iterator as $hash)
  3570. {
  3571. $value = null;
  3572. $algo = null;
  3573. if (isset($hash['data']))
  3574. {
  3575. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3576. }
  3577. if (isset($hash['attribs']['']['algo']))
  3578. {
  3579. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  3580. }
  3581. else
  3582. {
  3583. $algo = 'md5';
  3584. }
  3585. $hashes_parent[] = $algo.':'.$value;
  3586. }
  3587. }
  3588. if (is_array($hashes_parent))
  3589. {
  3590. $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
  3591. }
  3592. // KEYWORDS
  3593. if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  3594. {
  3595. if (isset($keywords[0]['data']))
  3596. {
  3597. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3598. foreach ($temp as $word)
  3599. {
  3600. $keywords_parent[] = trim($word);
  3601. }
  3602. }
  3603. unset($temp);
  3604. }
  3605. elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  3606. {
  3607. if (isset($keywords[0]['data']))
  3608. {
  3609. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3610. foreach ($temp as $word)
  3611. {
  3612. $keywords_parent[] = trim($word);
  3613. }
  3614. }
  3615. unset($temp);
  3616. }
  3617. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  3618. {
  3619. if (isset($keywords[0]['data']))
  3620. {
  3621. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3622. foreach ($temp as $word)
  3623. {
  3624. $keywords_parent[] = trim($word);
  3625. }
  3626. }
  3627. unset($temp);
  3628. }
  3629. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  3630. {
  3631. if (isset($keywords[0]['data']))
  3632. {
  3633. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3634. foreach ($temp as $word)
  3635. {
  3636. $keywords_parent[] = trim($word);
  3637. }
  3638. }
  3639. unset($temp);
  3640. }
  3641. if (is_array($keywords_parent))
  3642. {
  3643. $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
  3644. }
  3645. // PLAYER
  3646. if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  3647. {
  3648. if (isset($player_parent[0]['attribs']['']['url']))
  3649. {
  3650. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3651. }
  3652. }
  3653. elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  3654. {
  3655. if (isset($player_parent[0]['attribs']['']['url']))
  3656. {
  3657. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3658. }
  3659. }
  3660. // RATINGS
  3661. if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  3662. {
  3663. foreach ($ratings as $rating)
  3664. {
  3665. $rating_scheme = null;
  3666. $rating_value = null;
  3667. if (isset($rating['attribs']['']['scheme']))
  3668. {
  3669. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3670. }
  3671. else
  3672. {
  3673. $rating_scheme = 'urn:simple';
  3674. }
  3675. if (isset($rating['data']))
  3676. {
  3677. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3678. }
  3679. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3680. }
  3681. }
  3682. elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  3683. {
  3684. foreach ($ratings as $rating)
  3685. {
  3686. $rating_scheme = 'urn:itunes';
  3687. $rating_value = null;
  3688. if (isset($rating['data']))
  3689. {
  3690. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3691. }
  3692. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3693. }
  3694. }
  3695. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  3696. {
  3697. foreach ($ratings as $rating)
  3698. {
  3699. $rating_scheme = null;
  3700. $rating_value = null;
  3701. if (isset($rating['attribs']['']['scheme']))
  3702. {
  3703. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3704. }
  3705. else
  3706. {
  3707. $rating_scheme = 'urn:simple';
  3708. }
  3709. if (isset($rating['data']))
  3710. {
  3711. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3712. }
  3713. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3714. }
  3715. }
  3716. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  3717. {
  3718. foreach ($ratings as $rating)
  3719. {
  3720. $rating_scheme = 'urn:itunes';
  3721. $rating_value = null;
  3722. if (isset($rating['data']))
  3723. {
  3724. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3725. }
  3726. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3727. }
  3728. }
  3729. if (is_array($ratings_parent))
  3730. {
  3731. $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
  3732. }
  3733. // RESTRICTIONS
  3734. if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  3735. {
  3736. foreach ($restrictions as $restriction)
  3737. {
  3738. $restriction_relationship = null;
  3739. $restriction_type = null;
  3740. $restriction_value = null;
  3741. if (isset($restriction['attribs']['']['relationship']))
  3742. {
  3743. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  3744. }
  3745. if (isset($restriction['attribs']['']['type']))
  3746. {
  3747. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3748. }
  3749. if (isset($restriction['data']))
  3750. {
  3751. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3752. }
  3753. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  3754. }
  3755. }
  3756. elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  3757. {
  3758. foreach ($restrictions as $restriction)
  3759. {
  3760. $restriction_relationship = 'allow';
  3761. $restriction_type = null;
  3762. $restriction_value = 'itunes';
  3763. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  3764. {
  3765. $restriction_relationship = 'deny';
  3766. }
  3767. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  3768. }
  3769. }
  3770. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  3771. {
  3772. foreach ($restrictions as $restriction)
  3773. {
  3774. $restriction_relationship = null;
  3775. $restriction_type = null;
  3776. $restriction_value = null;
  3777. if (isset($restriction['attribs']['']['relationship']))
  3778. {
  3779. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  3780. }
  3781. if (isset($restriction['attribs']['']['type']))
  3782. {
  3783. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3784. }
  3785. if (isset($restriction['data']))
  3786. {
  3787. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3788. }
  3789. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  3790. }
  3791. }
  3792. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  3793. {
  3794. foreach ($restrictions as $restriction)
  3795. {
  3796. $restriction_relationship = 'allow';
  3797. $restriction_type = null;
  3798. $restriction_value = 'itunes';
  3799. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  3800. {
  3801. $restriction_relationship = 'deny';
  3802. }
  3803. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  3804. }
  3805. }
  3806. if (is_array($restrictions_parent))
  3807. {
  3808. $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
  3809. }
  3810. // THUMBNAILS
  3811. if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  3812. {
  3813. foreach ($thumbnails as $thumbnail)
  3814. {
  3815. if (isset($thumbnail['attribs']['']['url']))
  3816. {
  3817. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3818. }
  3819. }
  3820. }
  3821. elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  3822. {
  3823. foreach ($thumbnails as $thumbnail)
  3824. {
  3825. if (isset($thumbnail['attribs']['']['url']))
  3826. {
  3827. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3828. }
  3829. }
  3830. }
  3831. // TITLES
  3832. if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  3833. {
  3834. if (isset($title_parent[0]['data']))
  3835. {
  3836. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3837. }
  3838. }
  3839. elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  3840. {
  3841. if (isset($title_parent[0]['data']))
  3842. {
  3843. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3844. }
  3845. }
  3846. // Clear the memory
  3847. unset($parent);
  3848. // Attributes
  3849. $bitrate = null;
  3850. $channels = null;
  3851. $duration = null;
  3852. $expression = null;
  3853. $framerate = null;
  3854. $height = null;
  3855. $javascript = null;
  3856. $lang = null;
  3857. $length = null;
  3858. $medium = null;
  3859. $samplingrate = null;
  3860. $type = null;
  3861. $url = null;
  3862. $width = null;
  3863. // Elements
  3864. $captions = null;
  3865. $categories = null;
  3866. $copyrights = null;
  3867. $credits = null;
  3868. $description = null;
  3869. $hashes = null;
  3870. $keywords = null;
  3871. $player = null;
  3872. $ratings = null;
  3873. $restrictions = null;
  3874. $thumbnails = null;
  3875. $title = null;
  3876. // If we have media:group tags, loop through them.
  3877. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
  3878. {
  3879. if(isset($group['child']) && isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  3880. {
  3881. // If we have media:content tags, loop through them.
  3882. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  3883. {
  3884. if (isset($content['attribs']['']['url']))
  3885. {
  3886. // Attributes
  3887. $bitrate = null;
  3888. $channels = null;
  3889. $duration = null;
  3890. $expression = null;
  3891. $framerate = null;
  3892. $height = null;
  3893. $javascript = null;
  3894. $lang = null;
  3895. $length = null;
  3896. $medium = null;
  3897. $samplingrate = null;
  3898. $type = null;
  3899. $url = null;
  3900. $width = null;
  3901. // Elements
  3902. $captions = null;
  3903. $categories = null;
  3904. $copyrights = null;
  3905. $credits = null;
  3906. $description = null;
  3907. $hashes = null;
  3908. $keywords = null;
  3909. $player = null;
  3910. $ratings = null;
  3911. $restrictions = null;
  3912. $thumbnails = null;
  3913. $title = null;
  3914. // Start checking the attributes of media:content
  3915. if (isset($content['attribs']['']['bitrate']))
  3916. {
  3917. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  3918. }
  3919. if (isset($content['attribs']['']['channels']))
  3920. {
  3921. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  3922. }
  3923. if (isset($content['attribs']['']['duration']))
  3924. {
  3925. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  3926. }
  3927. else
  3928. {
  3929. $duration = $duration_parent;
  3930. }
  3931. if (isset($content['attribs']['']['expression']))
  3932. {
  3933. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  3934. }
  3935. if (isset($content['attribs']['']['framerate']))
  3936. {
  3937. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  3938. }
  3939. if (isset($content['attribs']['']['height']))
  3940. {
  3941. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  3942. }
  3943. if (isset($content['attribs']['']['lang']))
  3944. {
  3945. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3946. }
  3947. if (isset($content['attribs']['']['fileSize']))
  3948. {
  3949. $length = ceil($content['attribs']['']['fileSize']);
  3950. }
  3951. if (isset($content['attribs']['']['medium']))
  3952. {
  3953. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  3954. }
  3955. if (isset($content['attribs']['']['samplingrate']))
  3956. {
  3957. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  3958. }
  3959. if (isset($content['attribs']['']['type']))
  3960. {
  3961. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3962. }
  3963. if (isset($content['attribs']['']['width']))
  3964. {
  3965. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  3966. }
  3967. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3968. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  3969. // CAPTIONS
  3970. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  3971. {
  3972. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  3973. {
  3974. $caption_type = null;
  3975. $caption_lang = null;
  3976. $caption_startTime = null;
  3977. $caption_endTime = null;
  3978. $caption_text = null;
  3979. if (isset($caption['attribs']['']['type']))
  3980. {
  3981. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3982. }
  3983. if (isset($caption['attribs']['']['lang']))
  3984. {
  3985. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3986. }
  3987. if (isset($caption['attribs']['']['start']))
  3988. {
  3989. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  3990. }
  3991. if (isset($caption['attribs']['']['end']))
  3992. {
  3993. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  3994. }
  3995. if (isset($caption['data']))
  3996. {
  3997. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3998. }
  3999. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4000. }
  4001. if (is_array($captions))
  4002. {
  4003. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4004. }
  4005. }
  4006. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  4007. {
  4008. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  4009. {
  4010. $caption_type = null;
  4011. $caption_lang = null;
  4012. $caption_startTime = null;
  4013. $caption_endTime = null;
  4014. $caption_text = null;
  4015. if (isset($caption['attribs']['']['type']))
  4016. {
  4017. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4018. }
  4019. if (isset($caption['attribs']['']['lang']))
  4020. {
  4021. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4022. }
  4023. if (isset($caption['attribs']['']['start']))
  4024. {
  4025. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  4026. }
  4027. if (isset($caption['attribs']['']['end']))
  4028. {
  4029. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  4030. }
  4031. if (isset($caption['data']))
  4032. {
  4033. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4034. }
  4035. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4036. }
  4037. if (is_array($captions))
  4038. {
  4039. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4040. }
  4041. }
  4042. else
  4043. {
  4044. $captions = $captions_parent;
  4045. }
  4046. // CATEGORIES
  4047. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4048. {
  4049. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4050. {
  4051. $term = null;
  4052. $scheme = null;
  4053. $label = null;
  4054. if (isset($category['data']))
  4055. {
  4056. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4057. }
  4058. if (isset($category['attribs']['']['scheme']))
  4059. {
  4060. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4061. }
  4062. else
  4063. {
  4064. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4065. }
  4066. if (isset($category['attribs']['']['label']))
  4067. {
  4068. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4069. }
  4070. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4071. }
  4072. }
  4073. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4074. {
  4075. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4076. {
  4077. $term = null;
  4078. $scheme = null;
  4079. $label = null;
  4080. if (isset($category['data']))
  4081. {
  4082. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4083. }
  4084. if (isset($category['attribs']['']['scheme']))
  4085. {
  4086. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4087. }
  4088. else
  4089. {
  4090. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4091. }
  4092. if (isset($category['attribs']['']['label']))
  4093. {
  4094. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4095. }
  4096. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4097. }
  4098. }
  4099. if (is_array($categories) && is_array($categories_parent))
  4100. {
  4101. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  4102. }
  4103. elseif (is_array($categories))
  4104. {
  4105. $categories = array_values(SimplePie_Misc::array_unique($categories));
  4106. }
  4107. elseif (is_array($categories_parent))
  4108. {
  4109. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  4110. }
  4111. // COPYRIGHTS
  4112. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4113. {
  4114. $copyright_url = null;
  4115. $copyright_label = null;
  4116. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4117. {
  4118. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4119. }
  4120. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4121. {
  4122. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4123. }
  4124. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4125. }
  4126. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4127. {
  4128. $copyright_url = null;
  4129. $copyright_label = null;
  4130. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4131. {
  4132. $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4133. }
  4134. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4135. {
  4136. $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4137. }
  4138. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4139. }
  4140. else
  4141. {
  4142. $copyrights = $copyrights_parent;
  4143. }
  4144. // CREDITS
  4145. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4146. {
  4147. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4148. {
  4149. $credit_role = null;
  4150. $credit_scheme = null;
  4151. $credit_name = null;
  4152. if (isset($credit['attribs']['']['role']))
  4153. {
  4154. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4155. }
  4156. if (isset($credit['attribs']['']['scheme']))
  4157. {
  4158. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4159. }
  4160. else
  4161. {
  4162. $credit_scheme = 'urn:ebu';
  4163. }
  4164. if (isset($credit['data']))
  4165. {
  4166. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4167. }
  4168. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4169. }
  4170. if (is_array($credits))
  4171. {
  4172. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4173. }
  4174. }
  4175. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4176. {
  4177. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4178. {
  4179. $credit_role = null;
  4180. $credit_scheme = null;
  4181. $credit_name = null;
  4182. if (isset($credit['attribs']['']['role']))
  4183. {
  4184. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4185. }
  4186. if (isset($credit['attribs']['']['scheme']))
  4187. {
  4188. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4189. }
  4190. else
  4191. {
  4192. $credit_scheme = 'urn:ebu';
  4193. }
  4194. if (isset($credit['data']))
  4195. {
  4196. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4197. }
  4198. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4199. }
  4200. if (is_array($credits))
  4201. {
  4202. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4203. }
  4204. }
  4205. else
  4206. {
  4207. $credits = $credits_parent;
  4208. }
  4209. // DESCRIPTION
  4210. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4211. {
  4212. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4213. }
  4214. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4215. {
  4216. $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4217. }
  4218. else
  4219. {
  4220. $description = $description_parent;
  4221. }
  4222. // HASHES
  4223. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4224. {
  4225. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4226. {
  4227. $value = null;
  4228. $algo = null;
  4229. if (isset($hash['data']))
  4230. {
  4231. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4232. }
  4233. if (isset($hash['attribs']['']['algo']))
  4234. {
  4235. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4236. }
  4237. else
  4238. {
  4239. $algo = 'md5';
  4240. }
  4241. $hashes[] = $algo.':'.$value;
  4242. }
  4243. if (is_array($hashes))
  4244. {
  4245. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4246. }
  4247. }
  4248. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4249. {
  4250. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4251. {
  4252. $value = null;
  4253. $algo = null;
  4254. if (isset($hash['data']))
  4255. {
  4256. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4257. }
  4258. if (isset($hash['attribs']['']['algo']))
  4259. {
  4260. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4261. }
  4262. else
  4263. {
  4264. $algo = 'md5';
  4265. }
  4266. $hashes[] = $algo.':'.$value;
  4267. }
  4268. if (is_array($hashes))
  4269. {
  4270. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4271. }
  4272. }
  4273. else
  4274. {
  4275. $hashes = $hashes_parent;
  4276. }
  4277. // KEYWORDS
  4278. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4279. {
  4280. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4281. {
  4282. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4283. foreach ($temp as $word)
  4284. {
  4285. $keywords[] = trim($word);
  4286. }
  4287. unset($temp);
  4288. }
  4289. if (is_array($keywords))
  4290. {
  4291. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  4292. }
  4293. }
  4294. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4295. {
  4296. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4297. {
  4298. $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4299. foreach ($temp as $word)
  4300. {
  4301. $keywords[] = trim($word);
  4302. }
  4303. unset($temp);
  4304. }
  4305. if (is_array($keywords))
  4306. {
  4307. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  4308. }
  4309. }
  4310. else
  4311. {
  4312. $keywords = $keywords_parent;
  4313. }
  4314. // PLAYER
  4315. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4316. {
  4317. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4318. }
  4319. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4320. {
  4321. $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4322. }
  4323. else
  4324. {
  4325. $player = $player_parent;
  4326. }
  4327. // RATINGS
  4328. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  4329. {
  4330. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  4331. {
  4332. $rating_scheme = null;
  4333. $rating_value = null;
  4334. if (isset($rating['attribs']['']['scheme']))
  4335. {
  4336. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4337. }
  4338. else
  4339. {
  4340. $rating_scheme = 'urn:simple';
  4341. }
  4342. if (isset($rating['data']))
  4343. {
  4344. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4345. }
  4346. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  4347. }
  4348. if (is_array($ratings))
  4349. {
  4350. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  4351. }
  4352. }
  4353. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  4354. {
  4355. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  4356. {
  4357. $rating_scheme = null;
  4358. $rating_value = null;
  4359. if (isset($rating['attribs']['']['scheme']))
  4360. {
  4361. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4362. }
  4363. else
  4364. {
  4365. $rating_scheme = 'urn:simple';
  4366. }
  4367. if (isset($rating['data']))
  4368. {
  4369. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4370. }
  4371. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  4372. }
  4373. if (is_array($ratings))
  4374. {
  4375. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  4376. }
  4377. }
  4378. else
  4379. {
  4380. $ratings = $ratings_parent;
  4381. }
  4382. // RESTRICTIONS
  4383. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  4384. {
  4385. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  4386. {
  4387. $restriction_relationship = null;
  4388. $restriction_type = null;
  4389. $restriction_value = null;
  4390. if (isset($restriction['attribs']['']['relationship']))
  4391. {
  4392. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4393. }
  4394. if (isset($restriction['attribs']['']['type']))
  4395. {
  4396. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4397. }
  4398. if (isset($restriction['data']))
  4399. {
  4400. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4401. }
  4402. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4403. }
  4404. if (is_array($restrictions))
  4405. {
  4406. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  4407. }
  4408. }
  4409. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  4410. {
  4411. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  4412. {
  4413. $restriction_relationship = null;
  4414. $restriction_type = null;
  4415. $restriction_value = null;
  4416. if (isset($restriction['attribs']['']['relationship']))
  4417. {
  4418. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4419. }
  4420. if (isset($restriction['attribs']['']['type']))
  4421. {
  4422. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4423. }
  4424. if (isset($restriction['data']))
  4425. {
  4426. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4427. }
  4428. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4429. }
  4430. if (is_array($restrictions))
  4431. {
  4432. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  4433. }
  4434. }
  4435. else
  4436. {
  4437. $restrictions = $restrictions_parent;
  4438. }
  4439. // THUMBNAILS
  4440. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  4441. {
  4442. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  4443. {
  4444. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4445. }
  4446. if (is_array($thumbnails))
  4447. {
  4448. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  4449. }
  4450. }
  4451. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  4452. {
  4453. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  4454. {
  4455. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4456. }
  4457. if (is_array($thumbnails))
  4458. {
  4459. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  4460. }
  4461. }
  4462. else
  4463. {
  4464. $thumbnails = $thumbnails_parent;
  4465. }
  4466. // TITLES
  4467. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  4468. {
  4469. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4470. }
  4471. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  4472. {
  4473. $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4474. }
  4475. else
  4476. {
  4477. $title = $title_parent;
  4478. }
  4479. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
  4480. }
  4481. }
  4482. }
  4483. }
  4484. // If we have standalone media:content tags, loop through them.
  4485. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  4486. {
  4487. foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  4488. {
  4489. if (isset($content['attribs']['']['url']) || isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4490. {
  4491. // Attributes
  4492. $bitrate = null;
  4493. $channels = null;
  4494. $duration = null;
  4495. $expression = null;
  4496. $framerate = null;
  4497. $height = null;
  4498. $javascript = null;
  4499. $lang = null;
  4500. $length = null;
  4501. $medium = null;
  4502. $samplingrate = null;
  4503. $type = null;
  4504. $url = null;
  4505. $width = null;
  4506. // Elements
  4507. $captions = null;
  4508. $categories = null;
  4509. $copyrights = null;
  4510. $credits = null;
  4511. $description = null;
  4512. $hashes = null;
  4513. $keywords = null;
  4514. $player = null;
  4515. $ratings = null;
  4516. $restrictions = null;
  4517. $thumbnails = null;
  4518. $title = null;
  4519. // Start checking the attributes of media:content
  4520. if (isset($content['attribs']['']['bitrate']))
  4521. {
  4522. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4523. }
  4524. if (isset($content['attribs']['']['channels']))
  4525. {
  4526. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  4527. }
  4528. if (isset($content['attribs']['']['duration']))
  4529. {
  4530. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  4531. }
  4532. else
  4533. {
  4534. $duration = $duration_parent;
  4535. }
  4536. if (isset($content['attribs']['']['expression']))
  4537. {
  4538. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  4539. }
  4540. if (isset($content['attribs']['']['framerate']))
  4541. {
  4542. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4543. }
  4544. if (isset($content['attribs']['']['height']))
  4545. {
  4546. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  4547. }
  4548. if (isset($content['attribs']['']['lang']))
  4549. {
  4550. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4551. }
  4552. if (isset($content['attribs']['']['fileSize']))
  4553. {
  4554. $length = ceil($content['attribs']['']['fileSize']);
  4555. }
  4556. if (isset($content['attribs']['']['medium']))
  4557. {
  4558. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  4559. }
  4560. if (isset($content['attribs']['']['samplingrate']))
  4561. {
  4562. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4563. }
  4564. if (isset($content['attribs']['']['type']))
  4565. {
  4566. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4567. }
  4568. if (isset($content['attribs']['']['width']))
  4569. {
  4570. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  4571. }
  4572. if (isset($content['attribs']['']['url']))
  4573. {
  4574. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4575. }
  4576. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  4577. // CAPTIONS
  4578. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  4579. {
  4580. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  4581. {
  4582. $caption_type = null;
  4583. $caption_lang = null;
  4584. $caption_startTime = null;
  4585. $caption_endTime = null;
  4586. $caption_text = null;
  4587. if (isset($caption['attribs']['']['type']))
  4588. {
  4589. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4590. }
  4591. if (isset($caption['attribs']['']['lang']))
  4592. {
  4593. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4594. }
  4595. if (isset($caption['attribs']['']['start']))
  4596. {
  4597. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  4598. }
  4599. if (isset($caption['attribs']['']['end']))
  4600. {
  4601. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  4602. }
  4603. if (isset($caption['data']))
  4604. {
  4605. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4606. }
  4607. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4608. }
  4609. if (is_array($captions))
  4610. {
  4611. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4612. }
  4613. }
  4614. else
  4615. {
  4616. $captions = $captions_parent;
  4617. }
  4618. // CATEGORIES
  4619. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4620. {
  4621. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4622. {
  4623. $term = null;
  4624. $scheme = null;
  4625. $label = null;
  4626. if (isset($category['data']))
  4627. {
  4628. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4629. }
  4630. if (isset($category['attribs']['']['scheme']))
  4631. {
  4632. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4633. }
  4634. else
  4635. {
  4636. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4637. }
  4638. if (isset($category['attribs']['']['label']))
  4639. {
  4640. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4641. }
  4642. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4643. }
  4644. }
  4645. if (is_array($categories) && is_array($categories_parent))
  4646. {
  4647. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  4648. }
  4649. elseif (is_array($categories))
  4650. {
  4651. $categories = array_values(SimplePie_Misc::array_unique($categories));
  4652. }
  4653. elseif (is_array($categories_parent))
  4654. {
  4655. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  4656. }
  4657. else
  4658. {
  4659. $categories = null;
  4660. }
  4661. // COPYRIGHTS
  4662. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4663. {
  4664. $copyright_url = null;
  4665. $copyright_label = null;
  4666. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4667. {
  4668. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4669. }
  4670. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4671. {
  4672. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4673. }
  4674. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4675. }
  4676. else
  4677. {
  4678. $copyrights = $copyrights_parent;
  4679. }
  4680. // CREDITS
  4681. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4682. {
  4683. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4684. {
  4685. $credit_role = null;
  4686. $credit_scheme = null;
  4687. $credit_name = null;
  4688. if (isset($credit['attribs']['']['role']))
  4689. {
  4690. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4691. }
  4692. if (isset($credit['attribs']['']['scheme']))
  4693. {
  4694. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4695. }
  4696. else
  4697. {
  4698. $credit_scheme = 'urn:ebu';
  4699. }
  4700. if (isset($credit['data']))
  4701. {
  4702. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4703. }
  4704. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4705. }
  4706. if (is_array($credits))
  4707. {
  4708. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4709. }
  4710. }
  4711. else
  4712. {
  4713. $credits = $credits_parent;
  4714. }
  4715. // DESCRIPTION
  4716. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4717. {
  4718. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4719. }
  4720. else
  4721. {
  4722. $description = $description_parent;
  4723. }
  4724. // HASHES
  4725. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4726. {
  4727. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4728. {
  4729. $value = null;
  4730. $algo = null;
  4731. if (isset($hash['data']))
  4732. {
  4733. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4734. }
  4735. if (isset($hash['attribs']['']['algo']))
  4736. {
  4737. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4738. }
  4739. else
  4740. {
  4741. $algo = 'md5';
  4742. }
  4743. $hashes[] = $algo.':'.$value;
  4744. }
  4745. if (is_array($hashes))
  4746. {
  4747. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4748. }
  4749. }
  4750. else
  4751. {
  4752. $hashes = $hashes_parent;
  4753. }
  4754. // KEYWORDS
  4755. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4756. {
  4757. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4758. {
  4759. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4760. foreach ($temp as $word)
  4761. {
  4762. $keywords[] = trim($word);
  4763. }
  4764. unset($temp);
  4765. }
  4766. if (is_array($keywords))
  4767. {
  4768. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  4769. }
  4770. }
  4771. else
  4772. {
  4773. $keywords = $keywords_parent;
  4774. }
  4775. // PLAYER
  4776. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4777. {
  4778. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4779. }
  4780. else
  4781. {
  4782. $player = $player_parent;
  4783. }
  4784. // RATINGS
  4785. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  4786. {
  4787. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  4788. {
  4789. $rating_scheme = null;
  4790. $rating_value = null;
  4791. if (isset($rating['attribs']['']['scheme']))
  4792. {
  4793. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4794. }
  4795. else
  4796. {
  4797. $rating_scheme = 'urn:simple';
  4798. }
  4799. if (isset($rating['data']))
  4800. {
  4801. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4802. }
  4803. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  4804. }
  4805. if (is_array($ratings))
  4806. {
  4807. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  4808. }
  4809. }
  4810. else
  4811. {
  4812. $ratings = $ratings_parent;
  4813. }
  4814. // RESTRICTIONS
  4815. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  4816. {
  4817. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  4818. {
  4819. $restriction_relationship = null;
  4820. $restriction_type = null;
  4821. $restriction_value = null;
  4822. if (isset($restriction['attribs']['']['relationship']))
  4823. {
  4824. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4825. }
  4826. if (isset($restriction['attribs']['']['type']))
  4827. {
  4828. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4829. }
  4830. if (isset($restriction['data']))
  4831. {
  4832. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4833. }
  4834. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4835. }
  4836. if (is_array($restrictions))
  4837. {
  4838. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  4839. }
  4840. }
  4841. else
  4842. {
  4843. $restrictions = $restrictions_parent;
  4844. }
  4845. // THUMBNAILS
  4846. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  4847. {
  4848. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  4849. {
  4850. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4851. }
  4852. if (is_array($thumbnails))
  4853. {
  4854. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  4855. }
  4856. }
  4857. else
  4858. {
  4859. $thumbnails = $thumbnails_parent;
  4860. }
  4861. // TITLES
  4862. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  4863. {
  4864. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4865. }
  4866. else
  4867. {
  4868. $title = $title_parent;
  4869. }
  4870. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $bitrate, $captions, $categories, $channels, $copyrights, $credits, $description, $duration, $expression, $framerate, $hashes, $height, $keywords, $lang, $medium, $player, $ratings, $restrictions, $samplingrate, $thumbnails, $title, $width);
  4871. }
  4872. }
  4873. }
  4874. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  4875. {
  4876. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  4877. {
  4878. // Attributes
  4879. $bitrate = null;
  4880. $channels = null;
  4881. $duration = null;
  4882. $expression = null;
  4883. $framerate = null;
  4884. $height = null;
  4885. $javascript = null;
  4886. $lang = null;
  4887. $length = null;
  4888. $medium = null;
  4889. $samplingrate = null;
  4890. $type = null;
  4891. $url = null;
  4892. $width = null;
  4893. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  4894. if (isset($link['attribs']['']['type']))
  4895. {
  4896. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4897. }
  4898. if (isset($link['attribs']['']['length']))
  4899. {
  4900. $length = ceil($link['attribs']['']['length']);
  4901. }
  4902. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  4903. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $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);
  4904. }
  4905. }
  4906. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  4907. {
  4908. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  4909. {
  4910. // Attributes
  4911. $bitrate = null;
  4912. $channels = null;
  4913. $duration = null;
  4914. $expression = null;
  4915. $framerate = null;
  4916. $height = null;
  4917. $javascript = null;
  4918. $lang = null;
  4919. $length = null;
  4920. $medium = null;
  4921. $samplingrate = null;
  4922. $type = null;
  4923. $url = null;
  4924. $width = null;
  4925. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  4926. if (isset($link['attribs']['']['type']))
  4927. {
  4928. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4929. }
  4930. if (isset($link['attribs']['']['length']))
  4931. {
  4932. $length = ceil($link['attribs']['']['length']);
  4933. }
  4934. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  4935. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $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);
  4936. }
  4937. }
  4938. if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
  4939. {
  4940. if (isset($enclosure[0]['attribs']['']['url']))
  4941. {
  4942. // Attributes
  4943. $bitrate = null;
  4944. $channels = null;
  4945. $duration = null;
  4946. $expression = null;
  4947. $framerate = null;
  4948. $height = null;
  4949. $javascript = null;
  4950. $lang = null;
  4951. $length = null;
  4952. $medium = null;
  4953. $samplingrate = null;
  4954. $type = null;
  4955. $url = null;
  4956. $width = null;
  4957. $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
  4958. if (isset($enclosure[0]['attribs']['']['type']))
  4959. {
  4960. $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4961. }
  4962. if (isset($enclosure[0]['attribs']['']['length']))
  4963. {
  4964. $length = ceil($enclosure[0]['attribs']['']['length']);
  4965. }
  4966. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  4967. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $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);
  4968. }
  4969. }
  4970. 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))
  4971. {
  4972. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  4973. $this->data['enclosures'][] = new $this->feed->enclosure_class($url, $type, $length, $this->feed->javascript, $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);
  4974. }
  4975. $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
  4976. }
  4977. if (!empty($this->data['enclosures']))
  4978. {
  4979. return $this->data['enclosures'];
  4980. }
  4981. else
  4982. {
  4983. return null;
  4984. }
  4985. }
  4986. public function get_latitude()
  4987. {
  4988. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  4989. {
  4990. return (float) $return[0]['data'];
  4991. }
  4992. 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))
  4993. {
  4994. return (float) $match[1];
  4995. }
  4996. else
  4997. {
  4998. return null;
  4999. }
  5000. }
  5001. public function get_longitude()
  5002. {
  5003. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  5004. {
  5005. return (float) $return[0]['data'];
  5006. }
  5007. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  5008. {
  5009. return (float) $return[0]['data'];
  5010. }
  5011. 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))
  5012. {
  5013. return (float) $match[2];
  5014. }
  5015. else
  5016. {
  5017. return null;
  5018. }
  5019. }
  5020. public function get_source()
  5021. {
  5022. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
  5023. {
  5024. return new $this->feed->source_class($this, $return[0]);
  5025. }
  5026. else
  5027. {
  5028. return null;
  5029. }
  5030. }
  5031. }
  5032. class SimplePie_Source
  5033. {
  5034. var $item;
  5035. var $data = array();
  5036. public function __construct($item, $data)
  5037. {
  5038. $this->item = $item;
  5039. $this->data = $data;
  5040. }
  5041. public function __toString()
  5042. {
  5043. return md5(serialize($this->data));
  5044. }
  5045. public function get_source_tags($namespace, $tag)
  5046. {
  5047. if (isset($this->data['child'][$namespace][$tag]))
  5048. {
  5049. return $this->data['child'][$namespace][$tag];
  5050. }
  5051. else
  5052. {
  5053. return null;
  5054. }
  5055. }
  5056. public function get_base($element = array())
  5057. {
  5058. return $this->item->get_base($element);
  5059. }
  5060. public function sanitize($data, $type, $base = '')
  5061. {
  5062. return $this->item->sanitize($data, $type, $base);
  5063. }
  5064. public function get_item()
  5065. {
  5066. return $this->item;
  5067. }
  5068. public function get_title()
  5069. {
  5070. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  5071. {
  5072. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5073. }
  5074. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  5075. {
  5076. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5077. }
  5078. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  5079. {
  5080. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5081. }
  5082. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  5083. {
  5084. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5085. }
  5086. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  5087. {
  5088. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5089. }
  5090. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  5091. {
  5092. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5093. }
  5094. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  5095. {
  5096. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5097. }
  5098. else
  5099. {
  5100. return null;
  5101. }
  5102. }
  5103. public function get_category($key = 0)
  5104. {
  5105. $categories = $this->get_categories();
  5106. if (isset($categories[$key]))
  5107. {
  5108. return $categories[$key];
  5109. }
  5110. else
  5111. {
  5112. return null;
  5113. }
  5114. }
  5115. public function get_categories()
  5116. {
  5117. $categories = array();
  5118. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  5119. {
  5120. $term = null;
  5121. $scheme = null;
  5122. $label = null;
  5123. if (isset($category['attribs']['']['term']))
  5124. {
  5125. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  5126. }
  5127. if (isset($category['attribs']['']['scheme']))
  5128. {
  5129. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  5130. }
  5131. if (isset($category['attribs']['']['label']))
  5132. {
  5133. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  5134. }
  5135. $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
  5136. }
  5137. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  5138. {
  5139. // This is really the label, but keep this as the term also for BC.
  5140. // Label will also work on retrieving because that falls back to term.
  5141. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5142. if (isset($category['attribs']['']['domain']))
  5143. {
  5144. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  5145. }
  5146. else
  5147. {
  5148. $scheme = null;
  5149. }
  5150. $categories[] = new $this->item->feed->category_class($term, $scheme, null);
  5151. }
  5152. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  5153. {
  5154. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5155. }
  5156. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  5157. {
  5158. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5159. }
  5160. if (!empty($categories))
  5161. {
  5162. return SimplePie_Misc::array_unique($categories);
  5163. }
  5164. else
  5165. {
  5166. return null;
  5167. }
  5168. }
  5169. public function get_author($key = 0)
  5170. {
  5171. $authors = $this->get_authors();
  5172. if (isset($authors[$key]))
  5173. {
  5174. return $authors[$key];
  5175. }
  5176. else
  5177. {
  5178. return null;
  5179. }
  5180. }
  5181. public function get_authors()
  5182. {
  5183. $authors = array();
  5184. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  5185. {
  5186. $name = null;
  5187. $uri = null;
  5188. $email = null;
  5189. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  5190. {
  5191. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5192. }
  5193. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  5194. {
  5195. $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]));
  5196. }
  5197. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  5198. {
  5199. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5200. }
  5201. if ($name !== null || $email !== null || $uri !== null)
  5202. {
  5203. $authors[] = new $this->item->feed->author_class($name, $uri, $email);
  5204. }
  5205. }
  5206. if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  5207. {
  5208. $name = null;
  5209. $url = null;
  5210. $email = null;
  5211. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  5212. {
  5213. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5214. }
  5215. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  5216. {
  5217. $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]));
  5218. }
  5219. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  5220. {
  5221. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5222. }
  5223. if ($name !== null || $email !== null || $url !== null)
  5224. {
  5225. $authors[] = new $this->item->feed->author_class($name, $url, $email);
  5226. }
  5227. }
  5228. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  5229. {
  5230. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5231. }
  5232. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  5233. {
  5234. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5235. }
  5236. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  5237. {
  5238. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5239. }
  5240. if (!empty($authors))
  5241. {
  5242. return SimplePie_Misc::array_unique($authors);
  5243. }
  5244. else
  5245. {
  5246. return null;
  5247. }
  5248. }
  5249. public function get_contributor($key = 0)
  5250. {
  5251. $contributors = $this->get_contributors();
  5252. if (isset($contributors[$key]))
  5253. {
  5254. return $contributors[$key];
  5255. }
  5256. else
  5257. {
  5258. return null;
  5259. }
  5260. }
  5261. public function get_contributors()
  5262. {
  5263. $contributors = array();
  5264. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  5265. {
  5266. $name = null;
  5267. $uri = null;
  5268. $email = null;
  5269. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  5270. {
  5271. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5272. }
  5273. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  5274. {
  5275. $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]));
  5276. }
  5277. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  5278. {
  5279. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5280. }
  5281. if ($name !== null || $email !== null || $uri !== null)
  5282. {
  5283. $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
  5284. }
  5285. }
  5286. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  5287. {
  5288. $name = null;
  5289. $url = null;
  5290. $email = null;
  5291. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  5292. {
  5293. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5294. }
  5295. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  5296. {
  5297. $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]));
  5298. }
  5299. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  5300. {
  5301. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5302. }
  5303. if ($name !== null || $email !== null || $url !== null)
  5304. {
  5305. $contributors[] = new $this->item->feed->author_class($name, $url, $email);
  5306. }
  5307. }
  5308. if (!empty($contributors))
  5309. {
  5310. return SimplePie_Misc::array_unique($contributors);
  5311. }
  5312. else
  5313. {
  5314. return null;
  5315. }
  5316. }
  5317. public function get_link($key = 0, $rel = 'alternate')
  5318. {
  5319. $links = $this->get_links($rel);
  5320. if (isset($links[$key]))
  5321. {
  5322. return $links[$key];
  5323. }
  5324. else
  5325. {
  5326. return null;
  5327. }
  5328. }
  5329. /**
  5330. * Added for parity between the parent-level and the item/entry-level.
  5331. */
  5332. public function get_permalink()
  5333. {
  5334. return $this->get_link(0);
  5335. }
  5336. public function get_links($rel = 'alternate')
  5337. {
  5338. if (!isset($this->data['links']))
  5339. {
  5340. $this->data['links'] = array();
  5341. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  5342. {
  5343. foreach ($links as $link)
  5344. {
  5345. if (isset($link['attribs']['']['href']))
  5346. {
  5347. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  5348. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5349. }
  5350. }
  5351. }
  5352. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  5353. {
  5354. foreach ($links as $link)
  5355. {
  5356. if (isset($link['attribs']['']['href']))
  5357. {
  5358. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  5359. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5360. }
  5361. }
  5362. }
  5363. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  5364. {
  5365. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5366. }
  5367. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  5368. {
  5369. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5370. }
  5371. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  5372. {
  5373. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5374. }
  5375. $keys = array_keys($this->data['links']);
  5376. foreach ($keys as $key)
  5377. {
  5378. if (SimplePie_Misc::is_isegment_nz_nc($key))
  5379. {
  5380. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  5381. {
  5382. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  5383. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  5384. }
  5385. else
  5386. {
  5387. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  5388. }
  5389. }
  5390. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  5391. {
  5392. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  5393. }
  5394. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  5395. }
  5396. }
  5397. if (isset($this->data['links'][$rel]))
  5398. {
  5399. return $this->data['links'][$rel];
  5400. }
  5401. else
  5402. {
  5403. return null;
  5404. }
  5405. }
  5406. public function get_description()
  5407. {
  5408. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  5409. {
  5410. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5411. }
  5412. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  5413. {
  5414. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5415. }
  5416. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  5417. {
  5418. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5419. }
  5420. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  5421. {
  5422. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5423. }
  5424. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  5425. {
  5426. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5427. }
  5428. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  5429. {
  5430. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5431. }
  5432. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  5433. {
  5434. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5435. }
  5436. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  5437. {
  5438. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  5439. }
  5440. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  5441. {
  5442. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  5443. }
  5444. else
  5445. {
  5446. return null;
  5447. }
  5448. }
  5449. public function get_copyright()
  5450. {
  5451. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  5452. {
  5453. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5454. }
  5455. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  5456. {
  5457. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5458. }
  5459. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  5460. {
  5461. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5462. }
  5463. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  5464. {
  5465. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5466. }
  5467. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  5468. {
  5469. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5470. }
  5471. else
  5472. {
  5473. return null;
  5474. }
  5475. }
  5476. public function get_language()
  5477. {
  5478. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  5479. {
  5480. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5481. }
  5482. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  5483. {
  5484. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5485. }
  5486. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  5487. {
  5488. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5489. }
  5490. elseif (isset($this->data['xml_lang']))
  5491. {
  5492. return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  5493. }
  5494. else
  5495. {
  5496. return null;
  5497. }
  5498. }
  5499. public function get_latitude()
  5500. {
  5501. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  5502. {
  5503. return (float) $return[0]['data'];
  5504. }
  5505. 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))
  5506. {
  5507. return (float) $match[1];
  5508. }
  5509. else
  5510. {
  5511. return null;
  5512. }
  5513. }
  5514. public function get_longitude()
  5515. {
  5516. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  5517. {
  5518. return (float) $return[0]['data'];
  5519. }
  5520. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  5521. {
  5522. return (float) $return[0]['data'];
  5523. }
  5524. 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))
  5525. {
  5526. return (float) $match[2];
  5527. }
  5528. else
  5529. {
  5530. return null;
  5531. }
  5532. }
  5533. public function get_image_url()
  5534. {
  5535. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  5536. {
  5537. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  5538. }
  5539. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  5540. {
  5541. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  5542. }
  5543. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  5544. {
  5545. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  5546. }
  5547. else
  5548. {
  5549. return null;
  5550. }
  5551. }
  5552. }
  5553. class SimplePie_Author
  5554. {
  5555. var $name;
  5556. var $link;
  5557. var $email;
  5558. // Constructor, used to input the data
  5559. public function __construct($name = null, $link = null, $email = null)
  5560. {
  5561. $this->name = $name;
  5562. $this->link = $link;
  5563. $this->email = $email;
  5564. }
  5565. public function __toString()
  5566. {
  5567. // There is no $this->data here
  5568. return md5(serialize($this));
  5569. }
  5570. public function get_name()
  5571. {
  5572. if ($this->name !== null)
  5573. {
  5574. return $this->name;
  5575. }
  5576. else
  5577. {
  5578. return null;
  5579. }
  5580. }
  5581. public function get_link()
  5582. {
  5583. if ($this->link !== null)
  5584. {
  5585. return $this->link;
  5586. }
  5587. else
  5588. {
  5589. return null;
  5590. }
  5591. }
  5592. public function get_email()
  5593. {
  5594. if ($this->email !== null)
  5595. {
  5596. return $this->email;
  5597. }
  5598. else
  5599. {
  5600. return null;
  5601. }
  5602. }
  5603. }
  5604. class SimplePie_Category
  5605. {
  5606. var $term;
  5607. var $scheme;
  5608. var $label;
  5609. // Constructor, used to input the data
  5610. public function __construct($term = null, $scheme = null, $label = null)
  5611. {
  5612. $this->term = $term;
  5613. $this->scheme = $scheme;
  5614. $this->label = $label;
  5615. }
  5616. public function __toString()
  5617. {
  5618. // There is no $this->data here
  5619. return md5(serialize($this));
  5620. }
  5621. public function get_term()
  5622. {
  5623. if ($this->term !== null)
  5624. {
  5625. return $this->term;
  5626. }
  5627. else
  5628. {
  5629. return null;
  5630. }
  5631. }
  5632. public function get_scheme()
  5633. {
  5634. if ($this->scheme !== null)
  5635. {
  5636. return $this->scheme;
  5637. }
  5638. else
  5639. {
  5640. return null;
  5641. }
  5642. }
  5643. public function get_label()
  5644. {
  5645. if ($this->label !== null)
  5646. {
  5647. return $this->label;
  5648. }
  5649. else
  5650. {
  5651. return $this->get_term();
  5652. }
  5653. }
  5654. }
  5655. class SimplePie_Enclosure
  5656. {
  5657. var $bitrate;
  5658. var $captions;
  5659. var $categories;
  5660. var $channels;
  5661. var $copyright;
  5662. var $credits;
  5663. var $description;
  5664. var $duration;
  5665. var $expression;
  5666. var $framerate;
  5667. var $handler;
  5668. var $hashes;
  5669. var $height;
  5670. var $javascript;
  5671. var $keywords;
  5672. var $lang;
  5673. var $length;
  5674. var $link;
  5675. var $medium;
  5676. var $player;
  5677. var $ratings;
  5678. var $restrictions;
  5679. var $samplingrate;
  5680. var $thumbnails;
  5681. var $title;
  5682. var $type;
  5683. var $width;
  5684. // Constructor, used to input the data
  5685. 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)
  5686. {
  5687. $this->bitrate = $bitrate;
  5688. $this->captions = $captions;
  5689. $this->categories = $categories;
  5690. $this->channels = $channels;
  5691. $this->copyright = $copyright;
  5692. $this->credits = $credits;
  5693. $this->description = $description;
  5694. $this->duration = $duration;
  5695. $this->expression = $expression;
  5696. $this->framerate = $framerate;
  5697. $this->hashes = $hashes;
  5698. $this->height = $height;
  5699. $this->javascript = $javascript;
  5700. $this->keywords = $keywords;
  5701. $this->lang = $lang;
  5702. $this->length = $length;
  5703. $this->link = $link;
  5704. $this->medium = $medium;
  5705. $this->player = $player;
  5706. $this->ratings = $ratings;
  5707. $this->restrictions = $restrictions;
  5708. $this->samplingrate = $samplingrate;
  5709. $this->thumbnails = $thumbnails;
  5710. $this->title = $title;
  5711. $this->type = $type;
  5712. $this->width = $width;
  5713. if (class_exists('idna_convert'))
  5714. {
  5715. $idn = new idna_convert();
  5716. $parsed = SimplePie_Misc::parse_url($link);
  5717. $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  5718. }
  5719. $this->handler = $this->get_handler(); // Needs to load last
  5720. }
  5721. public function __toString()
  5722. {
  5723. // There is no $this->data here
  5724. return md5(serialize($this));
  5725. }
  5726. public function get_bitrate()
  5727. {
  5728. if ($this->bitrate !== null)
  5729. {
  5730. return $this->bitrate;
  5731. }
  5732. else
  5733. {
  5734. return null;
  5735. }
  5736. }
  5737. public function get_caption($key = 0)
  5738. {
  5739. $captions = $this->get_captions();
  5740. if (isset($captions[$key]))
  5741. {
  5742. return $captions[$key];
  5743. }
  5744. else
  5745. {
  5746. return null;
  5747. }
  5748. }
  5749. public function get_captions()
  5750. {
  5751. if ($this->captions !== null)
  5752. {
  5753. return $this->captions;
  5754. }
  5755. else
  5756. {
  5757. return null;
  5758. }
  5759. }
  5760. public function get_category($key = 0)
  5761. {
  5762. $categories = $this->get_categories();
  5763. if (isset($categories[$key]))
  5764. {
  5765. return $categories[$key];
  5766. }
  5767. else
  5768. {
  5769. return null;
  5770. }
  5771. }
  5772. public function get_categories()
  5773. {
  5774. if ($this->categories !== null)
  5775. {
  5776. return $this->categories;
  5777. }
  5778. else
  5779. {
  5780. return null;
  5781. }
  5782. }
  5783. public function get_channels()
  5784. {
  5785. if ($this->channels !== null)
  5786. {
  5787. return $this->channels;
  5788. }
  5789. else
  5790. {
  5791. return null;
  5792. }
  5793. }
  5794. public function get_copyright()
  5795. {
  5796. if ($this->copyright !== null)
  5797. {
  5798. return $this->copyright;
  5799. }
  5800. else
  5801. {
  5802. return null;
  5803. }
  5804. }
  5805. public function get_credit($key = 0)
  5806. {
  5807. $credits = $this->get_credits();
  5808. if (isset($credits[$key]))
  5809. {
  5810. return $credits[$key];
  5811. }
  5812. else
  5813. {
  5814. return null;
  5815. }
  5816. }
  5817. public function get_credits()
  5818. {
  5819. if ($this->credits !== null)
  5820. {
  5821. return $this->credits;
  5822. }
  5823. else
  5824. {
  5825. return null;
  5826. }
  5827. }
  5828. public function get_description()
  5829. {
  5830. if ($this->description !== null)
  5831. {
  5832. return $this->description;
  5833. }
  5834. else
  5835. {
  5836. return null;
  5837. }
  5838. }
  5839. public function get_duration($convert = false)
  5840. {
  5841. if ($this->duration !== null)
  5842. {
  5843. if ($convert)
  5844. {
  5845. $time = SimplePie_Misc::time_hms($this->duration);
  5846. return $time;
  5847. }
  5848. else
  5849. {
  5850. return $this->duration;
  5851. }
  5852. }
  5853. else
  5854. {
  5855. return null;
  5856. }
  5857. }
  5858. public function get_expression()
  5859. {
  5860. if ($this->expression !== null)
  5861. {
  5862. return $this->expression;
  5863. }
  5864. else
  5865. {
  5866. return 'full';
  5867. }
  5868. }
  5869. public function get_extension()
  5870. {
  5871. if ($this->link !== null)
  5872. {
  5873. $url = SimplePie_Misc::parse_url($this->link);
  5874. if ($url['path'] !== '')
  5875. {
  5876. return pathinfo($url['path'], PATHINFO_EXTENSION);
  5877. }
  5878. }
  5879. return null;
  5880. }
  5881. public function get_framerate()
  5882. {
  5883. if ($this->framerate !== null)
  5884. {
  5885. return $this->framerate;
  5886. }
  5887. else
  5888. {
  5889. return null;
  5890. }
  5891. }
  5892. public function get_handler()
  5893. {
  5894. return $this->get_real_type(true);
  5895. }
  5896. public function get_hash($key = 0)
  5897. {
  5898. $hashes = $this->get_hashes();
  5899. if (isset($hashes[$key]))
  5900. {
  5901. return $hashes[$key];
  5902. }
  5903. else
  5904. {
  5905. return null;
  5906. }
  5907. }
  5908. public function get_hashes()
  5909. {
  5910. if ($this->hashes !== null)
  5911. {
  5912. return $this->hashes;
  5913. }
  5914. else
  5915. {
  5916. return null;
  5917. }
  5918. }
  5919. public function get_height()
  5920. {
  5921. if ($this->height !== null)
  5922. {
  5923. return $this->height;
  5924. }
  5925. else
  5926. {
  5927. return null;
  5928. }
  5929. }
  5930. public function get_language()
  5931. {
  5932. if ($this->lang !== null)
  5933. {
  5934. return $this->lang;
  5935. }
  5936. else
  5937. {
  5938. return null;
  5939. }
  5940. }
  5941. public function get_keyword($key = 0)
  5942. {
  5943. $keywords = $this->get_keywords();
  5944. if (isset($keywords[$key]))
  5945. {
  5946. return $keywords[$key];
  5947. }
  5948. else
  5949. {
  5950. return null;
  5951. }
  5952. }
  5953. public function get_keywords()
  5954. {
  5955. if ($this->keywords !== null)
  5956. {
  5957. return $this->keywords;
  5958. }
  5959. else
  5960. {
  5961. return null;
  5962. }
  5963. }
  5964. public function get_length()
  5965. {
  5966. if ($this->length !== null)
  5967. {
  5968. return $this->length;
  5969. }
  5970. else
  5971. {
  5972. return null;
  5973. }
  5974. }
  5975. public function get_link()
  5976. {
  5977. if ($this->link !== null)
  5978. {
  5979. return urldecode($this->link);
  5980. }
  5981. else
  5982. {
  5983. return null;
  5984. }
  5985. }
  5986. public function get_medium()
  5987. {
  5988. if ($this->medium !== null)
  5989. {
  5990. return $this->medium;
  5991. }
  5992. else
  5993. {
  5994. return null;
  5995. }
  5996. }
  5997. public function get_player()
  5998. {
  5999. if ($this->player !== null)
  6000. {
  6001. return $this->player;
  6002. }
  6003. else
  6004. {
  6005. return null;
  6006. }
  6007. }
  6008. public function get_rating($key = 0)
  6009. {
  6010. $ratings = $this->get_ratings();
  6011. if (isset($ratings[$key]))
  6012. {
  6013. return $ratings[$key];
  6014. }
  6015. else
  6016. {
  6017. return null;
  6018. }
  6019. }
  6020. public function get_ratings()
  6021. {
  6022. if ($this->ratings !== null)
  6023. {
  6024. return $this->ratings;
  6025. }
  6026. else
  6027. {
  6028. return null;
  6029. }
  6030. }
  6031. public function get_restriction($key = 0)
  6032. {
  6033. $restrictions = $this->get_restrictions();
  6034. if (isset($restrictions[$key]))
  6035. {
  6036. return $restrictions[$key];
  6037. }
  6038. else
  6039. {
  6040. return null;
  6041. }
  6042. }
  6043. public function get_restrictions()
  6044. {
  6045. if ($this->restrictions !== null)
  6046. {
  6047. return $this->restrictions;
  6048. }
  6049. else
  6050. {
  6051. return null;
  6052. }
  6053. }
  6054. public function get_sampling_rate()
  6055. {
  6056. if ($this->samplingrate !== null)
  6057. {
  6058. return $this->samplingrate;
  6059. }
  6060. else
  6061. {
  6062. return null;
  6063. }
  6064. }
  6065. public function get_size()
  6066. {
  6067. $length = $this->get_length();
  6068. if ($length !== null)
  6069. {
  6070. return round($length/1048576, 2);
  6071. }
  6072. else
  6073. {
  6074. return null;
  6075. }
  6076. }
  6077. public function get_thumbnail($key = 0)
  6078. {
  6079. $thumbnails = $this->get_thumbnails();
  6080. if (isset($thumbnails[$key]))
  6081. {
  6082. return $thumbnails[$key];
  6083. }
  6084. else
  6085. {
  6086. return null;
  6087. }
  6088. }
  6089. public function get_thumbnails()
  6090. {
  6091. if ($this->thumbnails !== null)
  6092. {
  6093. return $this->thumbnails;
  6094. }
  6095. else
  6096. {
  6097. return null;
  6098. }
  6099. }
  6100. public function get_title()
  6101. {
  6102. if ($this->title !== null)
  6103. {
  6104. return $this->title;
  6105. }
  6106. else
  6107. {
  6108. return null;
  6109. }
  6110. }
  6111. public function get_type()
  6112. {
  6113. if ($this->type !== null)
  6114. {
  6115. return $this->type;
  6116. }
  6117. else
  6118. {
  6119. return null;
  6120. }
  6121. }
  6122. public function get_width()
  6123. {
  6124. if ($this->width !== null)
  6125. {
  6126. return $this->width;
  6127. }
  6128. else
  6129. {
  6130. return null;
  6131. }
  6132. }
  6133. public function native_embed($options='')
  6134. {
  6135. return $this->embed($options, true);
  6136. }
  6137. /**
  6138. * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
  6139. */
  6140. public function embed($options = '', $native = false)
  6141. {
  6142. // Set up defaults
  6143. $audio = '';
  6144. $video = '';
  6145. $alt = '';
  6146. $altclass = '';
  6147. $loop = 'false';
  6148. $width = 'auto';
  6149. $height = 'auto';
  6150. $bgcolor = '#ffffff';
  6151. $mediaplayer = '';
  6152. $widescreen = false;
  6153. $handler = $this->get_handler();
  6154. $type = $this->get_real_type();
  6155. // Process options and reassign values as necessary
  6156. if (is_array($options))
  6157. {
  6158. extract($options);
  6159. }
  6160. else
  6161. {
  6162. $options = explode(',', $options);
  6163. foreach($options as $option)
  6164. {
  6165. $opt = explode(':', $option, 2);
  6166. if (isset($opt[0], $opt[1]))
  6167. {
  6168. $opt[0] = trim($opt[0]);
  6169. $opt[1] = trim($opt[1]);
  6170. switch ($opt[0])
  6171. {
  6172. case 'audio':
  6173. $audio = $opt[1];
  6174. break;
  6175. case 'video':
  6176. $video = $opt[1];
  6177. break;
  6178. case 'alt':
  6179. $alt = $opt[1];
  6180. break;
  6181. case 'altclass':
  6182. $altclass = $opt[1];
  6183. break;
  6184. case 'loop':
  6185. $loop = $opt[1];
  6186. break;
  6187. case 'width':
  6188. $width = $opt[1];
  6189. break;
  6190. case 'height':
  6191. $height = $opt[1];
  6192. break;
  6193. case 'bgcolor':
  6194. $bgcolor = $opt[1];
  6195. break;
  6196. case 'mediaplayer':
  6197. $mediaplayer = $opt[1];
  6198. break;
  6199. case 'widescreen':
  6200. $widescreen = $opt[1];
  6201. break;
  6202. }
  6203. }
  6204. }
  6205. }
  6206. $mime = explode('/', $type, 2);
  6207. $mime = $mime[0];
  6208. // Process values for 'auto'
  6209. if ($width === 'auto')
  6210. {
  6211. if ($mime === 'video')
  6212. {
  6213. if ($height === 'auto')
  6214. {
  6215. $width = 480;
  6216. }
  6217. elseif ($widescreen)
  6218. {
  6219. $width = round((intval($height)/9)*16);
  6220. }
  6221. else
  6222. {
  6223. $width = round((intval($height)/3)*4);
  6224. }
  6225. }
  6226. else
  6227. {
  6228. $width = '100%';
  6229. }
  6230. }
  6231. if ($height === 'auto')
  6232. {
  6233. if ($mime === 'audio')
  6234. {
  6235. $height = 0;
  6236. }
  6237. elseif ($mime === 'video')
  6238. {
  6239. if ($width === 'auto')
  6240. {
  6241. if ($widescreen)
  6242. {
  6243. $height = 270;
  6244. }
  6245. else
  6246. {
  6247. $height = 360;
  6248. }
  6249. }
  6250. elseif ($widescreen)
  6251. {
  6252. $height = round((intval($width)/16)*9);
  6253. }
  6254. else
  6255. {
  6256. $height = round((intval($width)/4)*3);
  6257. }
  6258. }
  6259. else
  6260. {
  6261. $height = 376;
  6262. }
  6263. }
  6264. elseif ($mime === 'audio')
  6265. {
  6266. $height = 0;
  6267. }
  6268. // Set proper placeholder value
  6269. if ($mime === 'audio')
  6270. {
  6271. $placeholder = $audio;
  6272. }
  6273. elseif ($mime === 'video')
  6274. {
  6275. $placeholder = $video;
  6276. }
  6277. $embed = '';
  6278. // Make sure the JS library is included
  6279. if (!$native)
  6280. {
  6281. static $javascript_outputted = null;
  6282. if (!$javascript_outputted && $this->javascript)
  6283. {
  6284. $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
  6285. $javascript_outputted = true;
  6286. }
  6287. }
  6288. // Odeo Feed MP3's
  6289. if ($handler === 'odeo')
  6290. {
  6291. if ($native)
  6292. {
  6293. $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>';
  6294. }
  6295. else
  6296. {
  6297. $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
  6298. }
  6299. }
  6300. // Flash
  6301. elseif ($handler === 'flash')
  6302. {
  6303. if ($native)
  6304. {
  6305. $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>";
  6306. }
  6307. else
  6308. {
  6309. $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
  6310. }
  6311. }
  6312. // Flash Media Player file types.
  6313. // Preferred handler for MP3 file types.
  6314. elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
  6315. {
  6316. $height += 20;
  6317. if ($native)
  6318. {
  6319. $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>";
  6320. }
  6321. else
  6322. {
  6323. $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
  6324. }
  6325. }
  6326. // QuickTime 7 file types. Need to test with QuickTime 6.
  6327. // Only handle MP3's if the Flash Media Player is not present.
  6328. elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
  6329. {
  6330. $height += 16;
  6331. if ($native)
  6332. {
  6333. if ($placeholder !== '')
  6334. {
  6335. $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>";
  6336. }
  6337. else
  6338. {
  6339. $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>";
  6340. }
  6341. }
  6342. else
  6343. {
  6344. $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
  6345. }
  6346. }
  6347. // Windows Media
  6348. elseif ($handler === 'wmedia')
  6349. {
  6350. $height += 45;
  6351. if ($native)
  6352. {
  6353. $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>";
  6354. }
  6355. else
  6356. {
  6357. $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
  6358. }
  6359. }
  6360. // Everything else
  6361. else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
  6362. return $embed;
  6363. }
  6364. public function get_real_type($find_handler = false)
  6365. {
  6366. // If it's Odeo, let's get it out of the way.
  6367. if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
  6368. {
  6369. return 'odeo';
  6370. }
  6371. // Mime-types by handler.
  6372. $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
  6373. $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
  6374. $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
  6375. $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
  6376. $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
  6377. if ($this->get_type() !== null)
  6378. {
  6379. $type = strtolower($this->type);
  6380. }
  6381. else
  6382. {
  6383. $type = null;
  6384. }
  6385. // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
  6386. if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
  6387. {
  6388. switch (strtolower($this->get_extension()))
  6389. {
  6390. // Audio mime-types
  6391. case 'aac':
  6392. case 'adts':
  6393. $type = 'audio/acc';
  6394. break;
  6395. case 'aif':
  6396. case 'aifc':
  6397. case 'aiff':
  6398. case 'cdda':
  6399. $type = 'audio/aiff';
  6400. break;
  6401. case 'bwf':
  6402. $type = 'audio/wav';
  6403. break;
  6404. case 'kar':
  6405. case 'mid':
  6406. case 'midi':
  6407. case 'smf':
  6408. $type = 'audio/midi';
  6409. break;
  6410. case 'm4a':
  6411. $type = 'audio/x-m4a';
  6412. break;
  6413. case 'mp3':
  6414. case 'swa':
  6415. $type = 'audio/mp3';
  6416. break;
  6417. case 'wav':
  6418. $type = 'audio/wav';
  6419. break;
  6420. case 'wax':
  6421. $type = 'audio/x-ms-wax';
  6422. break;
  6423. case 'wma':
  6424. $type = 'audio/x-ms-wma';
  6425. break;
  6426. // Video mime-types
  6427. case '3gp':
  6428. case '3gpp':
  6429. $type = 'video/3gpp';
  6430. break;
  6431. case '3g2':
  6432. case '3gp2':
  6433. $type = 'video/3gpp2';
  6434. break;
  6435. case 'asf':
  6436. $type = 'video/x-ms-asf';
  6437. break;
  6438. case 'flv':
  6439. $type = 'video/x-flv';
  6440. break;
  6441. case 'm1a':
  6442. case 'm1s':
  6443. case 'm1v':
  6444. case 'm15':
  6445. case 'm75':
  6446. case 'mp2':
  6447. case 'mpa':
  6448. case 'mpeg':
  6449. case 'mpg':
  6450. case 'mpm':
  6451. case 'mpv':
  6452. $type = 'video/mpeg';
  6453. break;
  6454. case 'm4v':
  6455. $type = 'video/x-m4v';
  6456. break;
  6457. case 'mov':
  6458. case 'qt':
  6459. $type = 'video/quicktime';
  6460. break;
  6461. case 'mp4':
  6462. case 'mpg4':
  6463. $type = 'video/mp4';
  6464. break;
  6465. case 'sdv':
  6466. $type = 'video/sd-video';
  6467. break;
  6468. case 'wm':
  6469. $type = 'video/x-ms-wm';
  6470. break;
  6471. case 'wmv':
  6472. $type = 'video/x-ms-wmv';
  6473. break;
  6474. case 'wvx':
  6475. $type = 'video/x-ms-wvx';
  6476. break;
  6477. // Flash mime-types
  6478. case 'spl':
  6479. $type = 'application/futuresplash';
  6480. break;
  6481. case 'swf':
  6482. $type = 'application/x-shockwave-flash';
  6483. break;
  6484. }
  6485. }
  6486. if ($find_handler)
  6487. {
  6488. if (in_array($type, $types_flash))
  6489. {
  6490. return 'flash';
  6491. }
  6492. elseif (in_array($type, $types_fmedia))
  6493. {
  6494. return 'fmedia';
  6495. }
  6496. elseif (in_array($type, $types_quicktime))
  6497. {
  6498. return 'quicktime';
  6499. }
  6500. elseif (in_array($type, $types_wmedia))
  6501. {
  6502. return 'wmedia';
  6503. }
  6504. elseif (in_array($type, $types_mp3))
  6505. {
  6506. return 'mp3';
  6507. }
  6508. else
  6509. {
  6510. return null;
  6511. }
  6512. }
  6513. else
  6514. {
  6515. return $type;
  6516. }
  6517. }
  6518. }
  6519. class SimplePie_Caption
  6520. {
  6521. var $type;
  6522. var $lang;
  6523. var $startTime;
  6524. var $endTime;
  6525. var $text;
  6526. // Constructor, used to input the data
  6527. public function __construct($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
  6528. {
  6529. $this->type = $type;
  6530. $this->lang = $lang;
  6531. $this->startTime = $startTime;
  6532. $this->endTime = $endTime;
  6533. $this->text = $text;
  6534. }
  6535. public function __toString()
  6536. {
  6537. // There is no $this->data here
  6538. return md5(serialize($this));
  6539. }
  6540. public function get_endtime()
  6541. {
  6542. if ($this->endTime !== null)
  6543. {
  6544. return $this->endTime;
  6545. }
  6546. else
  6547. {
  6548. return null;
  6549. }
  6550. }
  6551. public function get_language()
  6552. {
  6553. if ($this->lang !== null)
  6554. {
  6555. return $this->lang;
  6556. }
  6557. else
  6558. {
  6559. return null;
  6560. }
  6561. }
  6562. public function get_starttime()
  6563. {
  6564. if ($this->startTime !== null)
  6565. {
  6566. return $this->startTime;
  6567. }
  6568. else
  6569. {
  6570. return null;
  6571. }
  6572. }
  6573. public function get_text()
  6574. {
  6575. if ($this->text !== null)
  6576. {
  6577. return $this->text;
  6578. }
  6579. else
  6580. {
  6581. return null;
  6582. }
  6583. }
  6584. public function get_type()
  6585. {
  6586. if ($this->type !== null)
  6587. {
  6588. return $this->type;
  6589. }
  6590. else
  6591. {
  6592. return null;
  6593. }
  6594. }
  6595. }
  6596. class SimplePie_Credit
  6597. {
  6598. var $role;
  6599. var $scheme;
  6600. var $name;
  6601. // Constructor, used to input the data
  6602. public function __construct($role = null, $scheme = null, $name = null)
  6603. {
  6604. $this->role = $role;
  6605. $this->scheme = $scheme;
  6606. $this->name = $name;
  6607. }
  6608. public function __toString()
  6609. {
  6610. // There is no $this->data here
  6611. return md5(serialize($this));
  6612. }
  6613. public function get_role()
  6614. {
  6615. if ($this->role !== null)
  6616. {
  6617. return $this->role;
  6618. }
  6619. else
  6620. {
  6621. return null;
  6622. }
  6623. }
  6624. public function get_scheme()
  6625. {
  6626. if ($this->scheme !== null)
  6627. {
  6628. return $this->scheme;
  6629. }
  6630. else
  6631. {
  6632. return null;
  6633. }
  6634. }
  6635. public function get_name()
  6636. {
  6637. if ($this->name !== null)
  6638. {
  6639. return $this->name;
  6640. }
  6641. else
  6642. {
  6643. return null;
  6644. }
  6645. }
  6646. }
  6647. class SimplePie_Copyright
  6648. {
  6649. var $url;
  6650. var $label;
  6651. // Constructor, used to input the data
  6652. public function __construct($url = null, $label = null)
  6653. {
  6654. $this->url = $url;
  6655. $this->label = $label;
  6656. }
  6657. public function __toString()
  6658. {
  6659. // There is no $this->data here
  6660. return md5(serialize($this));
  6661. }
  6662. public function get_url()
  6663. {
  6664. if ($this->url !== null)
  6665. {
  6666. return $this->url;
  6667. }
  6668. else
  6669. {
  6670. return null;
  6671. }
  6672. }
  6673. public function get_attribution()
  6674. {
  6675. if ($this->label !== null)
  6676. {
  6677. return $this->label;
  6678. }
  6679. else
  6680. {
  6681. return null;
  6682. }
  6683. }
  6684. }
  6685. class SimplePie_Rating
  6686. {
  6687. var $scheme;
  6688. var $value;
  6689. // Constructor, used to input the data
  6690. public function __construct($scheme = null, $value = null)
  6691. {
  6692. $this->scheme = $scheme;
  6693. $this->value = $value;
  6694. }
  6695. public function __toString()
  6696. {
  6697. // There is no $this->data here
  6698. return md5(serialize($this));
  6699. }
  6700. public function get_scheme()
  6701. {
  6702. if ($this->scheme !== null)
  6703. {
  6704. return $this->scheme;
  6705. }
  6706. else
  6707. {
  6708. return null;
  6709. }
  6710. }
  6711. public function get_value()
  6712. {
  6713. if ($this->value !== null)
  6714. {
  6715. return $this->value;
  6716. }
  6717. else
  6718. {
  6719. return null;
  6720. }
  6721. }
  6722. }
  6723. class SimplePie_Restriction
  6724. {
  6725. var $relationship;
  6726. var $type;
  6727. var $value;
  6728. // Constructor, used to input the data
  6729. public function __construct($relationship = null, $type = null, $value = null)
  6730. {
  6731. $this->relationship = $relationship;
  6732. $this->type = $type;
  6733. $this->value = $value;
  6734. }
  6735. public function __toString()
  6736. {
  6737. // There is no $this->data here
  6738. return md5(serialize($this));
  6739. }
  6740. public function get_relationship()
  6741. {
  6742. if ($this->relationship !== null)
  6743. {
  6744. return $this->relationship;
  6745. }
  6746. else
  6747. {
  6748. return null;
  6749. }
  6750. }
  6751. public function get_type()
  6752. {
  6753. if ($this->type !== null)
  6754. {
  6755. return $this->type;
  6756. }
  6757. else
  6758. {
  6759. return null;
  6760. }
  6761. }
  6762. public function get_value()
  6763. {
  6764. if ($this->value !== null)
  6765. {
  6766. return $this->value;
  6767. }
  6768. else
  6769. {
  6770. return null;
  6771. }
  6772. }
  6773. }
  6774. /**
  6775. * @todo Move to properly supporting RFC2616 (HTTP/1.1)
  6776. */
  6777. class SimplePie_File
  6778. {
  6779. var $url;
  6780. var $useragent;
  6781. var $success = true;
  6782. var $headers = array();
  6783. var $body;
  6784. var $status_code;
  6785. var $redirects = 0;
  6786. var $error;
  6787. var $method = SIMPLEPIE_FILE_SOURCE_NONE;
  6788. public function __construct($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  6789. {
  6790. if (class_exists('idna_convert'))
  6791. {
  6792. $idn = new idna_convert();
  6793. $parsed = SimplePie_Misc::parse_url($url);
  6794. $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  6795. }
  6796. $this->url = $url;
  6797. $this->useragent = $useragent;
  6798. if (preg_match('/^http(s)?:\/\//i', $url))
  6799. {
  6800. if ($useragent === null)
  6801. {
  6802. $useragent = ini_get('user_agent');
  6803. $this->useragent = $useragent;
  6804. }
  6805. if (!is_array($headers))
  6806. {
  6807. $headers = array();
  6808. }
  6809. if (!$force_fsockopen && function_exists('curl_exec'))
  6810. {
  6811. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
  6812. $fp = curl_init();
  6813. $headers2 = array();
  6814. foreach ($headers as $key => $value)
  6815. {
  6816. $headers2[] = "$key: $value";
  6817. }
  6818. if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
  6819. {
  6820. curl_setopt($fp, CURLOPT_ENCODING, '');
  6821. }
  6822. curl_setopt($fp, CURLOPT_URL, $url);
  6823. curl_setopt($fp, CURLOPT_HEADER, 1);
  6824. curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
  6825. curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
  6826. curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
  6827. curl_setopt($fp, CURLOPT_REFERER, $url);
  6828. curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
  6829. curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
  6830. if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
  6831. {
  6832. curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
  6833. curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
  6834. }
  6835. $this->headers = curl_exec($fp);
  6836. if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
  6837. {
  6838. curl_setopt($fp, CURLOPT_ENCODING, 'none');
  6839. $this->headers = curl_exec($fp);
  6840. }
  6841. if (curl_errno($fp))
  6842. {
  6843. $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
  6844. $this->success = false;
  6845. }
  6846. else
  6847. {
  6848. $info = curl_getinfo($fp);
  6849. curl_close($fp);
  6850. $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
  6851. $this->headers = array_pop($this->headers);
  6852. $parser = new SimplePie_HTTP_Parser($this->headers);
  6853. if ($parser->parse())
  6854. {
  6855. $this->headers = $parser->headers;
  6856. $this->body = $parser->body;
  6857. $this->status_code = $parser->status_code;
  6858. 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)
  6859. {
  6860. $this->redirects++;
  6861. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  6862. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  6863. }
  6864. }
  6865. }
  6866. }
  6867. else
  6868. {
  6869. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
  6870. $url_parts = parse_url($url);
  6871. if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
  6872. {
  6873. $url_parts['host'] = "ssl://$url_parts[host]";
  6874. $url_parts['port'] = 443;
  6875. }
  6876. if (!isset($url_parts['port']))
  6877. {
  6878. $url_parts['port'] = 80;
  6879. }
  6880. $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
  6881. if (!$fp)
  6882. {
  6883. $this->error = 'fsockopen error: ' . $errstr;
  6884. $this->success = false;
  6885. }
  6886. else
  6887. {
  6888. stream_set_timeout($fp, $timeout);
  6889. if (isset($url_parts['path']))
  6890. {
  6891. if (isset($url_parts['query']))
  6892. {
  6893. $get = "$url_parts[path]?$url_parts[query]";
  6894. }
  6895. else
  6896. {
  6897. $get = $url_parts['path'];
  6898. }
  6899. }
  6900. else
  6901. {
  6902. $get = '/';
  6903. }
  6904. $out = "GET $get HTTP/1.0\r\n";
  6905. $out .= "Host: $url_parts[host]\r\n";
  6906. $out .= "User-Agent: $useragent\r\n";
  6907. if (extension_loaded('zlib'))
  6908. {
  6909. $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
  6910. }
  6911. if (isset($url_parts['user']) && isset($url_parts['pass']))
  6912. {
  6913. $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
  6914. }
  6915. foreach ($headers as $key => $value)
  6916. {
  6917. $out .= "$key: $value\r\n";
  6918. }
  6919. $out .= "Connection: Close\r\n\r\n";
  6920. fwrite($fp, $out);
  6921. $info = stream_get_meta_data($fp);
  6922. $this->headers = '';
  6923. while (!$info['eof'] && !$info['timed_out'])
  6924. {
  6925. $this->headers .= fread($fp, 1160);
  6926. $info = stream_get_meta_data($fp);
  6927. }
  6928. if (!$info['timed_out'])
  6929. {
  6930. $parser = new SimplePie_HTTP_Parser($this->headers);
  6931. if ($parser->parse())
  6932. {
  6933. $this->headers = $parser->headers;
  6934. $this->body = $parser->body;
  6935. $this->status_code = $parser->status_code;
  6936. 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)
  6937. {
  6938. $this->redirects++;
  6939. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  6940. return $this->__construct($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  6941. }
  6942. if (isset($this->headers['content-encoding']))
  6943. {
  6944. // Hey, we act dumb elsewhere, so let's do that here too
  6945. switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
  6946. {
  6947. case 'gzip':
  6948. case 'x-gzip':
  6949. $decoder = new SimplePie_gzdecode($this->body);
  6950. if (!$decoder->parse())
  6951. {
  6952. $this->error = 'Unable to decode HTTP "gzip" stream';
  6953. $this->success = false;
  6954. }
  6955. else
  6956. {
  6957. $this->body = $decoder->data;
  6958. }
  6959. break;
  6960. case 'deflate':
  6961. if (($body = gzuncompress($this->body)) === false)
  6962. {
  6963. if (($body = gzinflate($this->body)) === false)
  6964. {
  6965. $this->error = 'Unable to decode HTTP "deflate" stream';
  6966. $this->success = false;
  6967. }
  6968. }
  6969. $this->body = $body;
  6970. break;
  6971. default:
  6972. $this->error = 'Unknown content coding';
  6973. $this->success = false;
  6974. }
  6975. }
  6976. }
  6977. }
  6978. else
  6979. {
  6980. $this->error = 'fsocket timed out';
  6981. $this->success = false;
  6982. }
  6983. fclose($fp);
  6984. }
  6985. }
  6986. }
  6987. else
  6988. {
  6989. $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
  6990. if (!$this->body = file_get_contents($url))
  6991. {
  6992. $this->error = 'file_get_contents could not read the file';
  6993. $this->success = false;
  6994. }
  6995. }
  6996. }
  6997. }
  6998. /**
  6999. * HTTP Response Parser
  7000. *
  7001. * @package SimplePie
  7002. */
  7003. class SimplePie_HTTP_Parser
  7004. {
  7005. /**
  7006. * HTTP Version
  7007. *
  7008. * @access public
  7009. * @var float
  7010. */
  7011. var $http_version = 0.0;
  7012. /**
  7013. * Status code
  7014. *
  7015. * @access public
  7016. * @var int
  7017. */
  7018. var $status_code = 0;
  7019. /**
  7020. * Reason phrase
  7021. *
  7022. * @access public
  7023. * @var string
  7024. */
  7025. var $reason = '';
  7026. /**
  7027. * Key/value pairs of the headers
  7028. *
  7029. * @access public
  7030. * @var array
  7031. */
  7032. var $headers = array();
  7033. /**
  7034. * Body of the response
  7035. *
  7036. * @access public
  7037. * @var string
  7038. */
  7039. var $body = '';
  7040. /**
  7041. * Current state of the state machine
  7042. *
  7043. * @access private
  7044. * @var string
  7045. */
  7046. var $state = 'http_version';
  7047. /**
  7048. * Input data
  7049. *
  7050. * @access private
  7051. * @var string
  7052. */
  7053. var $data = '';
  7054. /**
  7055. * Input data length (to avoid calling strlen() everytime this is needed)
  7056. *
  7057. * @access private
  7058. * @var int
  7059. */
  7060. var $data_length = 0;
  7061. /**
  7062. * Current position of the pointer
  7063. *
  7064. * @var int
  7065. * @access private
  7066. */
  7067. var $position = 0;
  7068. /**
  7069. * Name of the hedaer currently being parsed
  7070. *
  7071. * @access private
  7072. * @var string
  7073. */
  7074. var $name = '';
  7075. /**
  7076. * Value of the hedaer currently being parsed
  7077. *
  7078. * @access private
  7079. * @var string
  7080. */
  7081. var $value = '';
  7082. /**
  7083. * Create an instance of the class with the input data
  7084. *
  7085. * @access public
  7086. * @param string $data Input data
  7087. */
  7088. public function __construct($data)
  7089. {
  7090. $this->data = $data;
  7091. $this->data_length = strlen($this->data);
  7092. }
  7093. /**
  7094. * Parse the input data
  7095. *
  7096. * @access public
  7097. * @return bool true on success, false on failure
  7098. */
  7099. public function parse()
  7100. {
  7101. while ($this->state && $this->state !== 'emit' && $this->has_data())
  7102. {
  7103. $state = $this->state;
  7104. $this->$state();
  7105. }
  7106. $this->data = '';
  7107. if ($this->state === 'emit' || $this->state === 'body')
  7108. {
  7109. return true;
  7110. }
  7111. else
  7112. {
  7113. $this->http_version = '';
  7114. $this->status_code = '';
  7115. $this->reason = '';
  7116. $this->headers = array();
  7117. $this->body = '';
  7118. return false;
  7119. }
  7120. }
  7121. /**
  7122. * Check whether there is data beyond the pointer
  7123. *
  7124. * @access private
  7125. * @return bool true if there is further data, false if not
  7126. */
  7127. public function has_data()
  7128. {
  7129. return (bool) ($this->position < $this->data_length);
  7130. }
  7131. /**
  7132. * See if the next character is LWS
  7133. *
  7134. * @access private
  7135. * @return bool true if the next character is LWS, false if not
  7136. */
  7137. public function is_linear_whitespace()
  7138. {
  7139. return (bool) ($this->data[$this->position] === "\x09"
  7140. || $this->data[$this->position] === "\x20"
  7141. || ($this->data[$this->position] === "\x0A"
  7142. && isset($this->data[$this->position + 1])
  7143. && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
  7144. }
  7145. /**
  7146. * Parse the HTTP version
  7147. *
  7148. * @access private
  7149. */
  7150. public function http_version()
  7151. {
  7152. if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
  7153. {
  7154. $len = strspn($this->data, '0123456789.', 5);
  7155. $this->http_version = substr($this->data, 5, $len);
  7156. $this->position += 5 + $len;
  7157. if (substr_count($this->http_version, '.') <= 1)
  7158. {
  7159. $this->http_version = (float) $this->http_version;
  7160. $this->position += strspn($this->data, "\x09\x20", $this->position);
  7161. $this->state = 'status';
  7162. }
  7163. else
  7164. {
  7165. $this->state = false;
  7166. }
  7167. }
  7168. else
  7169. {
  7170. $this->state = false;
  7171. }
  7172. }
  7173. /**
  7174. * Parse the status code
  7175. *
  7176. * @access private
  7177. */
  7178. public function status()
  7179. {
  7180. if ($len = strspn($this->data, '0123456789', $this->position))
  7181. {
  7182. $this->status_code = (int) substr($this->data, $this->position, $len);
  7183. $this->position += $len;
  7184. $this->state = 'reason';
  7185. }
  7186. else
  7187. {
  7188. $this->state = false;
  7189. }
  7190. }
  7191. /**
  7192. * Parse the reason phrase
  7193. *
  7194. * @access private
  7195. */
  7196. public function reason()
  7197. {
  7198. $len = strcspn($this->data, "\x0A", $this->position);
  7199. $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
  7200. $this->position += $len + 1;
  7201. $this->state = 'new_line';
  7202. }
  7203. /**
  7204. * Deal with a new line, shifting data around as needed
  7205. *
  7206. * @access private
  7207. */
  7208. public function new_line()
  7209. {
  7210. $this->value = trim($this->value, "\x0D\x20");
  7211. if ($this->name !== '' && $this->value !== '')
  7212. {
  7213. $this->name = strtolower($this->name);
  7214. if (isset($this->headers[$this->name]))
  7215. {
  7216. $this->headers[$this->name] .= ', ' . $this->value;
  7217. }
  7218. else
  7219. {
  7220. $this->headers[$this->name] = $this->value;
  7221. }
  7222. }
  7223. $this->name = '';
  7224. $this->value = '';
  7225. if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
  7226. {
  7227. $this->position += 2;
  7228. $this->state = 'body';
  7229. }
  7230. elseif ($this->data[$this->position] === "\x0A")
  7231. {
  7232. $this->position++;
  7233. $this->state = 'body';
  7234. }
  7235. else
  7236. {
  7237. $this->state = 'name';
  7238. }
  7239. }
  7240. /**
  7241. * Parse a header name
  7242. *
  7243. * @access private
  7244. */
  7245. public function name()
  7246. {
  7247. $len = strcspn($this->data, "\x0A:", $this->position);
  7248. if (isset($this->data[$this->position + $len]))
  7249. {
  7250. if ($this->data[$this->position + $len] === "\x0A")
  7251. {
  7252. $this->position += $len;
  7253. $this->state = 'new_line';
  7254. }
  7255. else
  7256. {
  7257. $this->name = substr($this->data, $this->position, $len);
  7258. $this->position += $len + 1;
  7259. $this->state = 'value';
  7260. }
  7261. }
  7262. else
  7263. {
  7264. $this->state = false;
  7265. }
  7266. }
  7267. /**
  7268. * Parse LWS, replacing consecutive LWS characters with a single space
  7269. *
  7270. * @access private
  7271. */
  7272. public function linear_whitespace()
  7273. {
  7274. do
  7275. {
  7276. if (substr($this->data, $this->position, 2) === "\x0D\x0A")
  7277. {
  7278. $this->position += 2;
  7279. }
  7280. elseif ($this->data[$this->position] === "\x0A")
  7281. {
  7282. $this->position++;
  7283. }
  7284. $this->position += strspn($this->data, "\x09\x20", $this->position);
  7285. } while ($this->has_data() && $this->is_linear_whitespace());
  7286. $this->value .= "\x20";
  7287. }
  7288. /**
  7289. * See what state to move to while within non-quoted header values
  7290. *
  7291. * @access private
  7292. */
  7293. public function value()
  7294. {
  7295. if ($this->is_linear_whitespace())
  7296. {
  7297. $this->linear_whitespace();
  7298. }
  7299. else
  7300. {
  7301. switch ($this->data[$this->position])
  7302. {
  7303. case '"':
  7304. $this->position++;
  7305. $this->state = 'quote';
  7306. break;
  7307. case "\x0A":
  7308. $this->position++;
  7309. $this->state = 'new_line';
  7310. break;
  7311. default:
  7312. $this->state = 'value_char';
  7313. break;
  7314. }
  7315. }
  7316. }
  7317. /**
  7318. * Parse a header value while outside quotes
  7319. *
  7320. * @access private
  7321. */
  7322. public function value_char()
  7323. {
  7324. $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
  7325. $this->value .= substr($this->data, $this->position, $len);
  7326. $this->position += $len;
  7327. $this->state = 'value';
  7328. }
  7329. /**
  7330. * See what state to move to while within quoted header values
  7331. *
  7332. * @access private
  7333. */
  7334. public function quote()
  7335. {
  7336. if ($this->is_linear_whitespace())
  7337. {
  7338. $this->linear_whitespace();
  7339. }
  7340. else
  7341. {
  7342. switch ($this->data[$this->position])
  7343. {
  7344. case '"':
  7345. $this->position++;
  7346. $this->state = 'value';
  7347. break;
  7348. case "\x0A":
  7349. $this->position++;
  7350. $this->state = 'new_line';
  7351. break;
  7352. case '\\':
  7353. $this->position++;
  7354. $this->state = 'quote_escaped';
  7355. break;
  7356. default:
  7357. $this->state = 'quote_char';
  7358. break;
  7359. }
  7360. }
  7361. }
  7362. /**
  7363. * Parse a header value while within quotes
  7364. *
  7365. * @access private
  7366. */
  7367. public function quote_char()
  7368. {
  7369. $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
  7370. $this->value .= substr($this->data, $this->position, $len);
  7371. $this->position += $len;
  7372. $this->state = 'value';
  7373. }
  7374. /**
  7375. * Parse an escaped character within quotes
  7376. *
  7377. * @access private
  7378. */
  7379. public function quote_escaped()
  7380. {
  7381. $this->value .= $this->data[$this->position];
  7382. $this->position++;
  7383. $this->state = 'quote';
  7384. }
  7385. /**
  7386. * Parse the body
  7387. *
  7388. * @access private
  7389. */
  7390. public function body()
  7391. {
  7392. $this->body = substr($this->data, $this->position);
  7393. $this->state = 'emit';
  7394. }
  7395. }
  7396. /**
  7397. * gzdecode
  7398. *
  7399. * @package SimplePie
  7400. */
  7401. class SimplePie_gzdecode
  7402. {
  7403. /**
  7404. * Compressed data
  7405. *
  7406. * @access private
  7407. * @see gzdecode::$data
  7408. */
  7409. var $compressed_data;
  7410. /**
  7411. * Size of compressed data
  7412. *
  7413. * @access private
  7414. */
  7415. var $compressed_size;
  7416. /**
  7417. * Minimum size of a valid gzip string
  7418. *
  7419. * @access private
  7420. */
  7421. var $min_compressed_size = 18;
  7422. /**
  7423. * Current position of pointer
  7424. *
  7425. * @access private
  7426. */
  7427. var $position = 0;
  7428. /**
  7429. * Flags (FLG)
  7430. *
  7431. * @access private
  7432. */
  7433. var $flags;
  7434. /**
  7435. * Uncompressed data
  7436. *
  7437. * @access public
  7438. * @see gzdecode::$compressed_data
  7439. */
  7440. var $data;
  7441. /**
  7442. * Modified time
  7443. *
  7444. * @access public
  7445. */
  7446. var $MTIME;
  7447. /**
  7448. * Extra Flags
  7449. *
  7450. * @access public
  7451. */
  7452. var $XFL;
  7453. /**
  7454. * Operating System
  7455. *
  7456. * @access public
  7457. */
  7458. var $OS;
  7459. /**
  7460. * Subfield ID 1
  7461. *
  7462. * @access public
  7463. * @see gzdecode::$extra_field
  7464. * @see gzdecode::$SI2
  7465. */
  7466. var $SI1;
  7467. /**
  7468. * Subfield ID 2
  7469. *
  7470. * @access public
  7471. * @see gzdecode::$extra_field
  7472. * @see gzdecode::$SI1
  7473. */
  7474. var $SI2;
  7475. /**
  7476. * Extra field content
  7477. *
  7478. * @access public
  7479. * @see gzdecode::$SI1
  7480. * @see gzdecode::$SI2
  7481. */
  7482. var $extra_field;
  7483. /**
  7484. * Original filename
  7485. *
  7486. * @access public
  7487. */
  7488. var $filename;
  7489. /**
  7490. * Human readable comment
  7491. *
  7492. * @access public
  7493. */
  7494. var $comment;
  7495. /**
  7496. * Don't allow anything to be set
  7497. *
  7498. * @access public
  7499. */
  7500. public function __set($name, $value)
  7501. {
  7502. trigger_error("Cannot write property $name", E_USER_ERROR);
  7503. }
  7504. /**
  7505. * Set the compressed string and related properties
  7506. *
  7507. * @access public
  7508. */
  7509. public function __construct($data)
  7510. {
  7511. $this->compressed_data = $data;
  7512. $this->compressed_size = strlen($data);
  7513. }
  7514. /**
  7515. * Decode the GZIP stream
  7516. *
  7517. * @access public
  7518. */
  7519. public function parse()
  7520. {
  7521. if ($this->compressed_size >= $this->min_compressed_size)
  7522. {
  7523. // Check ID1, ID2, and CM
  7524. if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
  7525. {
  7526. return false;
  7527. }
  7528. // Get the FLG (FLaGs)
  7529. $this->flags = ord($this->compressed_data[3]);
  7530. // FLG bits above (1 << 4) are reserved
  7531. if ($this->flags > 0x1F)
  7532. {
  7533. return false;
  7534. }
  7535. // Advance the pointer after the above
  7536. $this->position += 4;
  7537. // MTIME
  7538. $mtime = substr($this->compressed_data, $this->position, 4);
  7539. // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
  7540. if (current(unpack('S', "\x00\x01")) === 1)
  7541. {
  7542. $mtime = strrev($mtime);
  7543. }
  7544. $this->MTIME = current(unpack('l', $mtime));
  7545. $this->position += 4;
  7546. // Get the XFL (eXtra FLags)
  7547. $this->XFL = ord($this->compressed_data[$this->position++]);
  7548. // Get the OS (Operating System)
  7549. $this->OS = ord($this->compressed_data[$this->position++]);
  7550. // Parse the FEXTRA
  7551. if ($this->flags & 4)
  7552. {
  7553. // Read subfield IDs
  7554. $this->SI1 = $this->compressed_data[$this->position++];
  7555. $this->SI2 = $this->compressed_data[$this->position++];
  7556. // SI2 set to zero is reserved for future use
  7557. if ($this->SI2 === "\x00")
  7558. {
  7559. return false;
  7560. }
  7561. // Get the length of the extra field
  7562. $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  7563. $position += 2;
  7564. // Check the length of the string is still valid
  7565. $this->min_compressed_size += $len + 4;
  7566. if ($this->compressed_size >= $this->min_compressed_size)
  7567. {
  7568. // Set the extra field to the given data
  7569. $this->extra_field = substr($this->compressed_data, $this->position, $len);
  7570. $this->position += $len;
  7571. }
  7572. else
  7573. {
  7574. return false;
  7575. }
  7576. }
  7577. // Parse the FNAME
  7578. if ($this->flags & 8)
  7579. {
  7580. // Get the length of the filename
  7581. $len = strcspn($this->compressed_data, "\x00", $this->position);
  7582. // Check the length of the string is still valid
  7583. $this->min_compressed_size += $len + 1;
  7584. if ($this->compressed_size >= $this->min_compressed_size)
  7585. {
  7586. // Set the original filename to the given string
  7587. $this->filename = substr($this->compressed_data, $this->position, $len);
  7588. $this->position += $len + 1;
  7589. }
  7590. else
  7591. {
  7592. return false;
  7593. }
  7594. }
  7595. // Parse the FCOMMENT
  7596. if ($this->flags & 16)
  7597. {
  7598. // Get the length of the comment
  7599. $len = strcspn($this->compressed_data, "\x00", $this->position);
  7600. // Check the length of the string is still valid
  7601. $this->min_compressed_size += $len + 1;
  7602. if ($this->compressed_size >= $this->min_compressed_size)
  7603. {
  7604. // Set the original comment to the given string
  7605. $this->comment = substr($this->compressed_data, $this->position, $len);
  7606. $this->position += $len + 1;
  7607. }
  7608. else
  7609. {
  7610. return false;
  7611. }
  7612. }
  7613. // Parse the FHCRC
  7614. if ($this->flags & 2)
  7615. {
  7616. // Check the length of the string is still valid
  7617. $this->min_compressed_size += $len + 2;
  7618. if ($this->compressed_size >= $this->min_compressed_size)
  7619. {
  7620. // Read the CRC
  7621. $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  7622. // Check the CRC matches
  7623. if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
  7624. {
  7625. $this->position += 2;
  7626. }
  7627. else
  7628. {
  7629. return false;
  7630. }
  7631. }
  7632. else
  7633. {
  7634. return false;
  7635. }
  7636. }
  7637. // Decompress the actual data
  7638. if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
  7639. {
  7640. return false;
  7641. }
  7642. else
  7643. {
  7644. $this->position = $this->compressed_size - 8;
  7645. }
  7646. // Check CRC of data
  7647. $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  7648. $this->position += 4;
  7649. /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
  7650. {
  7651. return false;
  7652. }*/
  7653. // Check ISIZE of data
  7654. $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  7655. $this->position += 4;
  7656. if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
  7657. {
  7658. return false;
  7659. }
  7660. // Wow, against all odds, we've actually got a valid gzip string
  7661. return true;
  7662. }
  7663. else
  7664. {
  7665. return false;
  7666. }
  7667. }
  7668. }
  7669. class SimplePie_Cache
  7670. {
  7671. /**
  7672. * Don't call the constructor. Please.
  7673. *
  7674. * @access private
  7675. */
  7676. private function __construct()
  7677. {
  7678. trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
  7679. }
  7680. /**
  7681. * Create a new SimplePie_Cache object
  7682. *
  7683. * @static
  7684. * @access public
  7685. */
  7686. public static function create($location, $filename, $extension)
  7687. {
  7688. $location_iri = new SimplePie_IRI($location);
  7689. switch ($location_iri->get_scheme())
  7690. {
  7691. case 'mysql':
  7692. if (extension_loaded('mysql'))
  7693. {
  7694. return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
  7695. }
  7696. break;
  7697. default:
  7698. return new SimplePie_Cache_File($location, $filename, $extension);
  7699. }
  7700. }
  7701. }
  7702. class SimplePie_Cache_File
  7703. {
  7704. var $location;
  7705. var $filename;
  7706. var $extension;
  7707. var $name;
  7708. public function __construct($location, $filename, $extension)
  7709. {
  7710. $this->location = $location;
  7711. $this->filename = $filename;
  7712. $this->extension = $extension;
  7713. $this->name = "$this->location/$this->filename.$this->extension";
  7714. }
  7715. public function save($data)
  7716. {
  7717. if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
  7718. {
  7719. if (is_a($data, 'SimplePie'))
  7720. {
  7721. $data = $data->data;
  7722. }
  7723. $data = serialize($data);
  7724. return (bool) file_put_contents($this->name, $data);
  7725. }
  7726. return false;
  7727. }
  7728. public function load()
  7729. {
  7730. if (file_exists($this->name) && is_readable($this->name))
  7731. {
  7732. return unserialize(file_get_contents($this->name));
  7733. }
  7734. return false;
  7735. }
  7736. public function mtime()
  7737. {
  7738. if (file_exists($this->name))
  7739. {
  7740. return filemtime($this->name);
  7741. }
  7742. return false;
  7743. }
  7744. public function touch()
  7745. {
  7746. if (file_exists($this->name))
  7747. {
  7748. return touch($this->name);
  7749. }
  7750. return false;
  7751. }
  7752. public function unlink()
  7753. {
  7754. if (file_exists($this->name))
  7755. {
  7756. return unlink($this->name);
  7757. }
  7758. return false;
  7759. }
  7760. }
  7761. class SimplePie_Cache_DB
  7762. {
  7763. public function prepare_simplepie_object_for_cache($data)
  7764. {
  7765. $items = $data->get_items();
  7766. $items_by_id = array();
  7767. if (!empty($items))
  7768. {
  7769. foreach ($items as $item)
  7770. {
  7771. $items_by_id[$item->get_id()] = $item;
  7772. }
  7773. if (count($items_by_id) !== count($items))
  7774. {
  7775. $items_by_id = array();
  7776. foreach ($items as $item)
  7777. {
  7778. $items_by_id[$item->get_id(true)] = $item;
  7779. }
  7780. }
  7781. if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  7782. {
  7783. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  7784. }
  7785. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  7786. {
  7787. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  7788. }
  7789. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  7790. {
  7791. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  7792. }
  7793. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
  7794. {
  7795. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
  7796. }
  7797. else
  7798. {
  7799. $channel = null;
  7800. }
  7801. if ($channel !== null)
  7802. {
  7803. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
  7804. {
  7805. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
  7806. }
  7807. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
  7808. {
  7809. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
  7810. }
  7811. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
  7812. {
  7813. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
  7814. }
  7815. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
  7816. {
  7817. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
  7818. }
  7819. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
  7820. {
  7821. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
  7822. }
  7823. }
  7824. if (isset($data->data['items']))
  7825. {
  7826. unset($data->data['items']);
  7827. }
  7828. if (isset($data->data['ordered_items']))
  7829. {
  7830. unset($data->data['ordered_items']);
  7831. }
  7832. }
  7833. return array(serialize($data->data), $items_by_id);
  7834. }
  7835. }
  7836. class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
  7837. {
  7838. var $mysql;
  7839. var $options;
  7840. var $id;
  7841. public function __construct($mysql_location, $name, $extension)
  7842. {
  7843. $host = $mysql_location->get_host();
  7844. if (stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
  7845. {
  7846. $server = ':' . substr($host, 5, -1);
  7847. }
  7848. else
  7849. {
  7850. $server = $host;
  7851. if ($mysql_location->get_port() !== null)
  7852. {
  7853. $server .= ':' . $mysql_location->get_port();
  7854. }
  7855. }
  7856. if (strpos($mysql_location->get_userinfo(), ':') !== false)
  7857. {
  7858. list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
  7859. }
  7860. else
  7861. {
  7862. $username = $mysql_location->get_userinfo();
  7863. $password = null;
  7864. }
  7865. if ($this->mysql = mysql_connect($server, $username, $password))
  7866. {
  7867. $this->id = $name . $extension;
  7868. $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
  7869. if (!isset($this->options['prefix'][0]))
  7870. {
  7871. $this->options['prefix'][0] = '';
  7872. }
  7873. if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
  7874. && mysql_query('SET NAMES utf8')
  7875. && ($query = mysql_unbuffered_query('SHOW TABLES')))
  7876. {
  7877. $db = array();
  7878. while ($row = mysql_fetch_row($query))
  7879. {
  7880. $db[] = $row[0];
  7881. }
  7882. if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
  7883. {
  7884. if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . '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)))'))
  7885. {
  7886. $this->mysql = null;
  7887. }
  7888. }
  7889. if (!in_array($this->options['prefix'][0] . 'items', $db))
  7890. {
  7891. if (!mysql_query('CREATE TABLE `' . $this->options['prefix'][0] . '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)))'))
  7892. {
  7893. $this->mysql = null;
  7894. }
  7895. }
  7896. }
  7897. else
  7898. {
  7899. $this->mysql = null;
  7900. }
  7901. }
  7902. }
  7903. public function save($data)
  7904. {
  7905. if ($this->mysql)
  7906. {
  7907. $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
  7908. if (is_a($data, 'SimplePie'))
  7909. {
  7910. $data = clone $data;
  7911. $prepared = $this->prepare_simplepie_object_for_cache($data);
  7912. if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
  7913. {
  7914. if (mysql_num_rows($query))
  7915. {
  7916. $items = count($prepared[1]);
  7917. if ($items)
  7918. {
  7919. $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
  7920. }
  7921. else
  7922. {
  7923. $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
  7924. }
  7925. if (!mysql_query($sql, $this->mysql))
  7926. {
  7927. return false;
  7928. }
  7929. }
  7930. elseif (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(' . $feed_id . ', ' . count($prepared[1]) . ', \'' . mysql_real_escape_string($prepared[0]) . '\', ' . time() . ')', $this->mysql))
  7931. {
  7932. return false;
  7933. }
  7934. $ids = array_keys($prepared[1]);
  7935. if (!empty($ids))
  7936. {
  7937. foreach ($ids as $id)
  7938. {
  7939. $database_ids[] = mysql_real_escape_string($id);
  7940. }
  7941. if ($query = mysql_unbuffered_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'items` WHERE `id` = \'' . implode('\' OR `id` = \'', $database_ids) . '\' AND `feed_id` = ' . $feed_id, $this->mysql))
  7942. {
  7943. $existing_ids = array();
  7944. while ($row = mysql_fetch_row($query))
  7945. {
  7946. $existing_ids[] = $row[0];
  7947. }
  7948. $new_ids = array_diff($ids, $existing_ids);
  7949. foreach ($new_ids as $new_id)
  7950. {
  7951. if (!($date = $prepared[1][$new_id]->get_date('U')))
  7952. {
  7953. $date = time();
  7954. }
  7955. if (!mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'items` (`feed_id`, `id`, `data`, `posted`) VALUES(' . $feed_id . ', \'' . mysql_real_escape_string($new_id) . '\', \'' . mysql_real_escape_string(serialize($prepared[1][$new_id]->data)) . '\', ' . $date . ')', $this->mysql))
  7956. {
  7957. return false;
  7958. }
  7959. }
  7960. return true;
  7961. }
  7962. }
  7963. else
  7964. {
  7965. return true;
  7966. }
  7967. }
  7968. }
  7969. elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
  7970. {
  7971. if (mysql_num_rows($query))
  7972. {
  7973. if (mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = 0, `data` = \'' . mysql_real_escape_string(serialize($data)) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id, $this->mysql))
  7974. {
  7975. return true;
  7976. }
  7977. }
  7978. elseif (mysql_query('INSERT INTO `' . $this->options['prefix'][0] . 'cache_data` (`id`, `items`, `data`, `mtime`) VALUES(\'' . mysql_real_escape_string($this->id) . '\', 0, \'' . mysql_real_escape_string(serialize($data)) . '\', ' . time() . ')', $this->mysql))
  7979. {
  7980. return true;
  7981. }
  7982. }
  7983. }
  7984. return false;
  7985. }
  7986. public function load()
  7987. {
  7988. if ($this->mysql && ($query = mysql_query('SELECT `items`, `data` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
  7989. {
  7990. $data = unserialize($row[1]);
  7991. if (isset($this->options['items'][0]))
  7992. {
  7993. $items = (int) $this->options['items'][0];
  7994. }
  7995. else
  7996. {
  7997. $items = (int) $row[0];
  7998. }
  7999. if ($items !== 0)
  8000. {
  8001. if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  8002. {
  8003. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  8004. }
  8005. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  8006. {
  8007. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  8008. }
  8009. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  8010. {
  8011. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  8012. }
  8013. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
  8014. {
  8015. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
  8016. }
  8017. else
  8018. {
  8019. $feed = null;
  8020. }
  8021. if ($feed !== null)
  8022. {
  8023. $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
  8024. if ($items > 0)
  8025. {
  8026. $sql .= ' LIMIT ' . $items;
  8027. }
  8028. if ($query = mysql_unbuffered_query($sql, $this->mysql))
  8029. {
  8030. while ($row = mysql_fetch_row($query))
  8031. {
  8032. $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
  8033. }
  8034. }
  8035. else
  8036. {
  8037. return false;
  8038. }
  8039. }
  8040. }
  8041. return $data;
  8042. }
  8043. return false;
  8044. }
  8045. public function mtime()
  8046. {
  8047. if ($this->mysql && ($query = mysql_query('SELECT `mtime` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($row = mysql_fetch_row($query)))
  8048. {
  8049. return $row[0];
  8050. }
  8051. else
  8052. {
  8053. return false;
  8054. }
  8055. }
  8056. public function touch()
  8057. {
  8058. if ($this->mysql && ($query = mysql_query('UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `mtime` = ' . time() . ' WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && mysql_affected_rows($this->mysql))
  8059. {
  8060. return true;
  8061. }
  8062. else
  8063. {
  8064. return false;
  8065. }
  8066. }
  8067. public function unlink()
  8068. {
  8069. if ($this->mysql && ($query = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)) && ($query2 = mysql_query('DELETE FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . "'", $this->mysql)))
  8070. {
  8071. return true;
  8072. }
  8073. else
  8074. {
  8075. return false;
  8076. }
  8077. }
  8078. }
  8079. class SimplePie_Misc
  8080. {
  8081. public static function time_hms($seconds)
  8082. {
  8083. $time = '';
  8084. $hours = floor($seconds / 3600);
  8085. $remainder = $seconds % 3600;
  8086. if ($hours > 0)
  8087. {
  8088. $time .= $hours.':';
  8089. }
  8090. $minutes = floor($remainder / 60);
  8091. $seconds = $remainder % 60;
  8092. if ($minutes < 10 && $hours > 0)
  8093. {
  8094. $minutes = '0' . $minutes;
  8095. }
  8096. if ($seconds < 10)
  8097. {
  8098. $seconds = '0' . $seconds;
  8099. }
  8100. $time .= $minutes.':';
  8101. $time .= $seconds;
  8102. return $time;
  8103. }
  8104. public static function absolutize_url($relative, $base)
  8105. {
  8106. $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
  8107. return $iri->get_iri();
  8108. }
  8109. public static function remove_dot_segments($input)
  8110. {
  8111. $output = '';
  8112. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  8113. {
  8114. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  8115. if (strpos($input, '../') === 0)
  8116. {
  8117. $input = substr($input, 3);
  8118. }
  8119. elseif (strpos($input, './') === 0)
  8120. {
  8121. $input = substr($input, 2);
  8122. }
  8123. // 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,
  8124. elseif (strpos($input, '/./') === 0)
  8125. {
  8126. $input = substr_replace($input, '/', 0, 3);
  8127. }
  8128. elseif ($input === '/.')
  8129. {
  8130. $input = '/';
  8131. }
  8132. // 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,
  8133. elseif (strpos($input, '/../') === 0)
  8134. {
  8135. $input = substr_replace($input, '/', 0, 4);
  8136. $output = substr_replace($output, '', strrpos($output, '/'));
  8137. }
  8138. elseif ($input === '/..')
  8139. {
  8140. $input = '/';
  8141. $output = substr_replace($output, '', strrpos($output, '/'));
  8142. }
  8143. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  8144. elseif ($input === '.' || $input === '..')
  8145. {
  8146. $input = '';
  8147. }
  8148. // 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
  8149. elseif (($pos = strpos($input, '/', 1)) !== false)
  8150. {
  8151. $output .= substr($input, 0, $pos);
  8152. $input = substr_replace($input, '', 0, $pos);
  8153. }
  8154. else
  8155. {
  8156. $output .= $input;
  8157. $input = '';
  8158. }
  8159. }
  8160. return $output . $input;
  8161. }
  8162. public static function get_element($realname, $string)
  8163. {
  8164. $return = array();
  8165. $name = preg_quote($realname, '/');
  8166. if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
  8167. {
  8168. for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
  8169. {
  8170. $return[$i]['tag'] = $realname;
  8171. $return[$i]['full'] = $matches[$i][0][0];
  8172. $return[$i]['offset'] = $matches[$i][0][1];
  8173. if (strlen($matches[$i][3][0]) <= 2)
  8174. {
  8175. $return[$i]['self_closing'] = true;
  8176. }
  8177. else
  8178. {
  8179. $return[$i]['self_closing'] = false;
  8180. $return[$i]['content'] = $matches[$i][4][0];
  8181. }
  8182. $return[$i]['attribs'] = array();
  8183. 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))
  8184. {
  8185. for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
  8186. {
  8187. if (count($attribs[$j]) === 2)
  8188. {
  8189. $attribs[$j][2] = $attribs[$j][1];
  8190. }
  8191. $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
  8192. }
  8193. }
  8194. }
  8195. }
  8196. return $return;
  8197. }
  8198. public static function element_implode($element)
  8199. {
  8200. $full = "<$element[tag]";
  8201. foreach ($element['attribs'] as $key => $value)
  8202. {
  8203. $key = strtolower($key);
  8204. $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
  8205. }
  8206. if ($element['self_closing'])
  8207. {
  8208. $full .= ' />';
  8209. }
  8210. else
  8211. {
  8212. $full .= ">$element[content]</$element[tag]>";
  8213. }
  8214. return $full;
  8215. }
  8216. public static function error($message, $level, $file, $line)
  8217. {
  8218. if ((ini_get('error_reporting') & $level) > 0)
  8219. {
  8220. switch ($level)
  8221. {
  8222. case E_USER_ERROR:
  8223. $note = 'PHP Error';
  8224. break;
  8225. case E_USER_WARNING:
  8226. $note = 'PHP Warning';
  8227. break;
  8228. case E_USER_NOTICE:
  8229. $note = 'PHP Notice';
  8230. break;
  8231. default:
  8232. $note = 'Unknown Error';
  8233. break;
  8234. }
  8235. $log_error = true;
  8236. if (!function_exists('error_log'))
  8237. {
  8238. $log_error = false;
  8239. }
  8240. $log_file = @ini_get('error_log');
  8241. if (!empty($log_file) && ('syslog' != $log_file) && !@is_writable($log_file))
  8242. {
  8243. $log_error = false;
  8244. }
  8245. if ($log_error)
  8246. {
  8247. @error_log("$note: $message in $file on line $line", 0);
  8248. }
  8249. }
  8250. return $message;
  8251. }
  8252. public static function fix_protocol($url, $http = 1)
  8253. {
  8254. $url = SimplePie_Misc::normalize_url($url);
  8255. $parsed = SimplePie_Misc::parse_url($url);
  8256. if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
  8257. {
  8258. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
  8259. }
  8260. if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
  8261. {
  8262. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
  8263. }
  8264. if ($http === 2 && $parsed['scheme'] !== '')
  8265. {
  8266. return "feed:$url";
  8267. }
  8268. elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
  8269. {
  8270. return substr_replace($url, 'podcast', 0, 4);
  8271. }
  8272. elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
  8273. {
  8274. return substr_replace($url, 'itpc', 0, 4);
  8275. }
  8276. else
  8277. {
  8278. return $url;
  8279. }
  8280. }
  8281. public static function parse_url($url)
  8282. {
  8283. $iri = new SimplePie_IRI($url);
  8284. return array(
  8285. 'scheme' => (string) $iri->get_scheme(),
  8286. 'authority' => (string) $iri->get_authority(),
  8287. 'path' => (string) $iri->get_path(),
  8288. 'query' => (string) $iri->get_query(),
  8289. 'fragment' => (string) $iri->get_fragment()
  8290. );
  8291. }
  8292. public static function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
  8293. {
  8294. $iri = new SimplePie_IRI('');
  8295. $iri->set_scheme($scheme);
  8296. $iri->set_authority($authority);
  8297. $iri->set_path($path);
  8298. $iri->set_query($query);
  8299. $iri->set_fragment($fragment);
  8300. return $iri->get_iri();
  8301. }
  8302. public static function normalize_url($url)
  8303. {
  8304. $iri = new SimplePie_IRI($url);
  8305. return $iri->get_iri();
  8306. }
  8307. public static function percent_encoding_normalization($match)
  8308. {
  8309. $integer = hexdec($match[1]);
  8310. if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
  8311. {
  8312. return chr($integer);
  8313. }
  8314. else
  8315. {
  8316. return strtoupper($match[0]);
  8317. }
  8318. }
  8319. /**
  8320. * Converts a Windows-1252 encoded string to a UTF-8 encoded string
  8321. *
  8322. * @static
  8323. * @access public
  8324. * @param string $string Windows-1252 encoded string
  8325. * @return string UTF-8 encoded string
  8326. */
  8327. public static function windows_1252_to_utf8($string)
  8328. {
  8329. 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");
  8330. return strtr($string, $convert_table);
  8331. }
  8332. public static function change_encoding($data, $input, $output)
  8333. {
  8334. $input = SimplePie_Misc::encoding($input);
  8335. $output = SimplePie_Misc::encoding($output);
  8336. // We fail to fail on non US-ASCII bytes
  8337. if ($input === 'US-ASCII')
  8338. {
  8339. static $non_ascii_octects = '';
  8340. if (!$non_ascii_octects)
  8341. {
  8342. for ($i = 0x80; $i <= 0xFF; $i++)
  8343. {
  8344. $non_ascii_octects .= chr($i);
  8345. }
  8346. }
  8347. $data = substr($data, 0, strcspn($data, $non_ascii_octects));
  8348. }
  8349. // This is first, as behaviour of this is completely predictable
  8350. if ($input === 'windows-1252' && $output === 'UTF-8')
  8351. {
  8352. return SimplePie_Misc::windows_1252_to_utf8($data);
  8353. }
  8354. // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
  8355. elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
  8356. {
  8357. return $return;
  8358. }
  8359. // This is last, as behaviour of this varies with OS userland and PHP version
  8360. elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
  8361. {
  8362. return $return;
  8363. }
  8364. // If we can't do anything, just fail
  8365. else
  8366. {
  8367. return false;
  8368. }
  8369. }
  8370. /**
  8371. * Normalize an encoding name
  8372. *
  8373. * This is automatically generated by create.php
  8374. *
  8375. * To generate it, run `php create.php` on the command line, and copy the
  8376. * output to replace this function.
  8377. *
  8378. * @param string $charset Character set to standardise
  8379. * @return string Standardised name
  8380. */
  8381. public static function encoding($charset)
  8382. {
  8383. // Normalization from UTS #22
  8384. switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
  8385. {
  8386. case 'adobestandardencoding':
  8387. case 'csadobestandardencoding':
  8388. return 'Adobe-Standard-Encoding';
  8389. case 'adobesymbolencoding':
  8390. case 'cshppsmath':
  8391. return 'Adobe-Symbol-Encoding';
  8392. case 'ami1251':
  8393. case 'amiga1251':
  8394. return 'Amiga-1251';
  8395. case 'ansix31101983':
  8396. case 'csat5001983':
  8397. case 'csiso99naplps':
  8398. case 'isoir99':
  8399. case 'naplps':
  8400. return 'ANSI_X3.110-1983';
  8401. case 'arabic7':
  8402. case 'asmo449':
  8403. case 'csiso89asmo449':
  8404. case 'iso9036':
  8405. case 'isoir89':
  8406. return 'ASMO_449';
  8407. case 'big5':
  8408. case 'csbig5':
  8409. return 'Big5';
  8410. case 'big5hkscs':
  8411. return 'Big5-HKSCS';
  8412. case 'bocu1':
  8413. case 'csbocu1':
  8414. return 'BOCU-1';
  8415. case 'brf':
  8416. case 'csbrf':
  8417. return 'BRF';
  8418. case 'bs4730':
  8419. case 'csiso4unitedkingdom':
  8420. case 'gb':
  8421. case 'iso646gb':
  8422. case 'isoir4':
  8423. case 'uk':
  8424. return 'BS_4730';
  8425. case 'bsviewdata':
  8426. case 'csiso47bsviewdata':
  8427. case 'isoir47':
  8428. return 'BS_viewdata';
  8429. case 'cesu8':
  8430. case 'cscesu8':
  8431. return 'CESU-8';
  8432. case 'ca':
  8433. case 'csa71':
  8434. case 'csaz243419851':
  8435. case 'csiso121canadian1':
  8436. case 'iso646ca':
  8437. case 'isoir121':
  8438. return 'CSA_Z243.4-1985-1';
  8439. case 'csa72':
  8440. case 'csaz243419852':
  8441. case 'csiso122canadian2':
  8442. case 'iso646ca2':
  8443. case 'isoir122':
  8444. return 'CSA_Z243.4-1985-2';
  8445. case 'csaz24341985gr':
  8446. case 'csiso123csaz24341985gr':
  8447. case 'isoir123':
  8448. return 'CSA_Z243.4-1985-gr';
  8449. case 'csiso139csn369103':
  8450. case 'csn369103':
  8451. case 'isoir139':
  8452. return 'CSN_369103';
  8453. case 'csdecmcs':
  8454. case 'dec':
  8455. case 'decmcs':
  8456. return 'DEC-MCS';
  8457. case 'csiso21german':
  8458. case 'de':
  8459. case 'din66003':
  8460. case 'iso646de':
  8461. case 'isoir21':
  8462. return 'DIN_66003';
  8463. case 'csdkus':
  8464. case 'dkus':
  8465. return 'dk-us';
  8466. case 'csiso646danish':
  8467. case 'dk':
  8468. case 'ds2089':
  8469. case 'iso646dk':
  8470. return 'DS_2089';
  8471. case 'csibmebcdicatde':
  8472. case 'ebcdicatde':
  8473. return 'EBCDIC-AT-DE';
  8474. case 'csebcdicatdea':
  8475. case 'ebcdicatdea':
  8476. return 'EBCDIC-AT-DE-A';
  8477. case 'csebcdiccafr':
  8478. case 'ebcdiccafr':
  8479. return 'EBCDIC-CA-FR';
  8480. case 'csebcdicdkno':
  8481. case 'ebcdicdkno':
  8482. return 'EBCDIC-DK-NO';
  8483. case 'csebcdicdknoa':
  8484. case 'ebcdicdknoa':
  8485. return 'EBCDIC-DK-NO-A';
  8486. case 'csebcdices':
  8487. case 'ebcdices':
  8488. return 'EBCDIC-ES';
  8489. case 'csebcdicesa':
  8490. case 'ebcdicesa':
  8491. return 'EBCDIC-ES-A';
  8492. case 'csebcdicess':
  8493. case 'ebcdicess':
  8494. return 'EBCDIC-ES-S';
  8495. case 'csebcdicfise':
  8496. case 'ebcdicfise':
  8497. return 'EBCDIC-FI-SE';
  8498. case 'csebcdicfisea':
  8499. case 'ebcdicfisea':
  8500. return 'EBCDIC-FI-SE-A';
  8501. case 'csebcdicfr':
  8502. case 'ebcdicfr':
  8503. return 'EBCDIC-FR';
  8504. case 'csebcdicit':
  8505. case 'ebcdicit':
  8506. return 'EBCDIC-IT';
  8507. case 'csebcdicpt':
  8508. case 'ebcdicpt':
  8509. return 'EBCDIC-PT';
  8510. case 'csebcdicuk':
  8511. case 'ebcdicuk':
  8512. return 'EBCDIC-UK';
  8513. case 'csebcdicus':
  8514. case 'ebcdicus':
  8515. return 'EBCDIC-US';
  8516. case 'csiso111ecmacyrillic':
  8517. case 'ecmacyrillic':
  8518. case 'isoir111':
  8519. case 'koi8e':
  8520. return 'ECMA-cyrillic';
  8521. case 'csiso17spanish':
  8522. case 'es':
  8523. case 'iso646es':
  8524. case 'isoir17':
  8525. return 'ES';
  8526. case 'csiso85spanish2':
  8527. case 'es2':
  8528. case 'iso646es2':
  8529. case 'isoir85':
  8530. return 'ES2';
  8531. case 'cseucpkdfmtjapanese':
  8532. case 'eucjp':
  8533. case 'extendedunixcodepackedformatforjapanese':
  8534. return 'EUC-JP';
  8535. case 'cseucfixwidjapanese':
  8536. case 'extendedunixcodefixedwidthforjapanese':
  8537. return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
  8538. case 'gb18030':
  8539. return 'GB18030';
  8540. case 'chinese':
  8541. case 'cp936':
  8542. case 'csgb2312':
  8543. case 'csiso58gb231280':
  8544. case 'gb2312':
  8545. case 'gb231280':
  8546. case 'gbk':
  8547. case 'isoir58':
  8548. case 'ms936':
  8549. case 'windows936':
  8550. return 'GBK';
  8551. case 'cn':
  8552. case 'csiso57gb1988':
  8553. case 'gb198880':
  8554. case 'iso646cn':
  8555. case 'isoir57':
  8556. return 'GB_1988-80';
  8557. case 'csiso153gost1976874':
  8558. case 'gost1976874':
  8559. case 'isoir153':
  8560. case 'stsev35888':
  8561. return 'GOST_19768-74';
  8562. case 'csiso150':
  8563. case 'csiso150greekccitt':
  8564. case 'greekccitt':
  8565. case 'isoir150':
  8566. return 'greek-ccitt';
  8567. case 'csiso88greek7':
  8568. case 'greek7':
  8569. case 'isoir88':
  8570. return 'greek7';
  8571. case 'csiso18greek7old':
  8572. case 'greek7old':
  8573. case 'isoir18':
  8574. return 'greek7-old';
  8575. case 'cshpdesktop':
  8576. case 'hpdesktop':
  8577. return 'HP-DeskTop';
  8578. case 'cshplegal':
  8579. case 'hplegal':
  8580. return 'HP-Legal';
  8581. case 'cshpmath8':
  8582. case 'hpmath8':
  8583. return 'HP-Math8';
  8584. case 'cshppifont':
  8585. case 'hppifont':
  8586. return 'HP-Pi-font';
  8587. case 'cshproman8':
  8588. case 'hproman8':
  8589. case 'r8':
  8590. case 'roman8':
  8591. return 'hp-roman8';
  8592. case 'hzgb2312':
  8593. return 'HZ-GB-2312';
  8594. case 'csibmsymbols':
  8595. case 'ibmsymbols':
  8596. return 'IBM-Symbols';
  8597. case 'csibmthai':
  8598. case 'ibmthai':
  8599. return 'IBM-Thai';
  8600. case 'cp37':
  8601. case 'csibm37':
  8602. case 'ebcdiccpca':
  8603. case 'ebcdiccpnl':
  8604. case 'ebcdiccpus':
  8605. case 'ebcdiccpwt':
  8606. case 'ibm37':
  8607. return 'IBM037';
  8608. case 'cp38':
  8609. case 'csibm38':
  8610. case 'ebcdicint':
  8611. case 'ibm38':
  8612. return 'IBM038';
  8613. case 'cp273':
  8614. case 'csibm273':
  8615. case 'ibm273':
  8616. return 'IBM273';
  8617. case 'cp274':
  8618. case 'csibm274':
  8619. case 'ebcdicbe':
  8620. case 'ibm274':
  8621. return 'IBM274';
  8622. case 'cp275':
  8623. case 'csibm275':
  8624. case 'ebcdicbr':
  8625. case 'ibm275':
  8626. return 'IBM275';
  8627. case 'csibm277':
  8628. case 'ebcdiccpdk':
  8629. case 'ebcdiccpno':
  8630. case 'ibm277':
  8631. return 'IBM277';
  8632. case 'cp278':
  8633. case 'csibm278':
  8634. case 'ebcdiccpfi':
  8635. case 'ebcdiccpse':
  8636. case 'ibm278':
  8637. return 'IBM278';
  8638. case 'cp280':
  8639. case 'csibm280':
  8640. case 'ebcdiccpit':
  8641. case 'ibm280':
  8642. return 'IBM280';
  8643. case 'cp281':
  8644. case 'csibm281':
  8645. case 'ebcdicjpe':
  8646. case 'ibm281':
  8647. return 'IBM281';
  8648. case 'cp284':
  8649. case 'csibm284':
  8650. case 'ebcdiccpes':
  8651. case 'ibm284':
  8652. return 'IBM284';
  8653. case 'cp285':
  8654. case 'csibm285':
  8655. case 'ebcdiccpgb':
  8656. case 'ibm285':
  8657. return 'IBM285';
  8658. case 'cp290':
  8659. case 'csibm290':
  8660. case 'ebcdicjpkana':
  8661. case 'ibm290':
  8662. return 'IBM290';
  8663. case 'cp297':
  8664. case 'csibm297':
  8665. case 'ebcdiccpfr':
  8666. case 'ibm297':
  8667. return 'IBM297';
  8668. case 'cp420':
  8669. case 'csibm420':
  8670. case 'ebcdiccpar1':
  8671. case 'ibm420':
  8672. return 'IBM420';
  8673. case 'cp423':
  8674. case 'csibm423':
  8675. case 'ebcdiccpgr':
  8676. case 'ibm423':
  8677. return 'IBM423';
  8678. case 'cp424':
  8679. case 'csibm424':
  8680. case 'ebcdiccphe':
  8681. case 'ibm424':
  8682. return 'IBM424';
  8683. case '437':
  8684. case 'cp437':
  8685. case 'cspc8codepage437':
  8686. case 'ibm437':
  8687. return 'IBM437';
  8688. case 'cp500':
  8689. case 'csibm500':
  8690. case 'ebcdiccpbe':
  8691. case 'ebcdiccpch':
  8692. case 'ibm500':
  8693. return 'IBM500';
  8694. case 'cp775':
  8695. case 'cspc775baltic':
  8696. case 'ibm775':
  8697. return 'IBM775';
  8698. case '850':
  8699. case 'cp850':
  8700. case 'cspc850multilingual':
  8701. case 'ibm850':
  8702. return 'IBM850';
  8703. case '851':
  8704. case 'cp851':
  8705. case 'csibm851':
  8706. case 'ibm851':
  8707. return 'IBM851';
  8708. case '852':
  8709. case 'cp852':
  8710. case 'cspcp852':
  8711. case 'ibm852':
  8712. return 'IBM852';
  8713. case '855':
  8714. case 'cp855':
  8715. case 'csibm855':
  8716. case 'ibm855':
  8717. return 'IBM855';
  8718. case '857':
  8719. case 'cp857':
  8720. case 'csibm857':
  8721. case 'ibm857':
  8722. return 'IBM857';
  8723. case 'ccsid858':
  8724. case 'cp858':
  8725. case 'ibm858':
  8726. case 'pcmultilingual850euro':
  8727. return 'IBM00858';
  8728. case '860':
  8729. case 'cp860':
  8730. case 'csibm860':
  8731. case 'ibm860':
  8732. return 'IBM860';
  8733. case '861':
  8734. case 'cp861':
  8735. case 'cpis':
  8736. case 'csibm861':
  8737. case 'ibm861':
  8738. return 'IBM861';
  8739. case '862':
  8740. case 'cp862':
  8741. case 'cspc862latinhebrew':
  8742. case 'ibm862':
  8743. return 'IBM862';
  8744. case '863':
  8745. case 'cp863':
  8746. case 'csibm863':
  8747. case 'ibm863':
  8748. return 'IBM863';
  8749. case 'cp864':
  8750. case 'csibm864':
  8751. case 'ibm864':
  8752. return 'IBM864';
  8753. case '865':
  8754. case 'cp865':
  8755. case 'csibm865':
  8756. case 'ibm865':
  8757. return 'IBM865';
  8758. case '866':
  8759. case 'cp866':
  8760. case 'csibm866':
  8761. case 'ibm866':
  8762. return 'IBM866';
  8763. case 'cp868':
  8764. case 'cpar':
  8765. case 'csibm868':
  8766. case 'ibm868':
  8767. return 'IBM868';
  8768. case '869':
  8769. case 'cp869':
  8770. case 'cpgr':
  8771. case 'csibm869':
  8772. case 'ibm869':
  8773. return 'IBM869';
  8774. case 'cp870':
  8775. case 'csibm870':
  8776. case 'ebcdiccproece':
  8777. case 'ebcdiccpyu':
  8778. case 'ibm870':
  8779. return 'IBM870';
  8780. case 'cp871':
  8781. case 'csibm871':
  8782. case 'ebcdiccpis':
  8783. case 'ibm871':
  8784. return 'IBM871';
  8785. case 'cp880':
  8786. case 'csibm880':
  8787. case 'ebcdiccyrillic':
  8788. case 'ibm880':
  8789. return 'IBM880';
  8790. case 'cp891':
  8791. case 'csibm891':
  8792. case 'ibm891':
  8793. return 'IBM891';
  8794. case 'cp903':
  8795. case 'csibm903':
  8796. case 'ibm903':
  8797. return 'IBM903';
  8798. case '904':
  8799. case 'cp904':
  8800. case 'csibbm904':
  8801. case 'ibm904':
  8802. return 'IBM904';
  8803. case 'cp905':
  8804. case 'csibm905':
  8805. case 'ebcdiccptr':
  8806. case 'ibm905':
  8807. return 'IBM905';
  8808. case 'cp918':
  8809. case 'csibm918':
  8810. case 'ebcdiccpar2':
  8811. case 'ibm918':
  8812. return 'IBM918';
  8813. case 'ccsid924':
  8814. case 'cp924':
  8815. case 'ebcdiclatin9euro':
  8816. case 'ibm924':
  8817. return 'IBM00924';
  8818. case 'cp1026':
  8819. case 'csibm1026':
  8820. case 'ibm1026':
  8821. return 'IBM1026';
  8822. case 'ibm1047':
  8823. return 'IBM1047';
  8824. case 'ccsid1140':
  8825. case 'cp1140':
  8826. case 'ebcdicus37euro':
  8827. case 'ibm1140':
  8828. return 'IBM01140';
  8829. case 'ccsid1141':
  8830. case 'cp1141':
  8831. case 'ebcdicde273euro':
  8832. case 'ibm1141':
  8833. return 'IBM01141';
  8834. case 'ccsid1142':
  8835. case 'cp1142':
  8836. case 'ebcdicdk277euro':
  8837. case 'ebcdicno277euro':
  8838. case 'ibm1142':
  8839. return 'IBM01142';
  8840. case 'ccsid1143':
  8841. case 'cp1143':
  8842. case 'ebcdicfi278euro':
  8843. case 'ebcdicse278euro':
  8844. case 'ibm1143':
  8845. return 'IBM01143';
  8846. case 'ccsid1144':
  8847. case 'cp1144':
  8848. case 'ebcdicit280euro':
  8849. case 'ibm1144':
  8850. return 'IBM01144';
  8851. case 'ccsid1145':
  8852. case 'cp1145':
  8853. case 'ebcdices284euro':
  8854. case 'ibm1145':
  8855. return 'IBM01145';
  8856. case 'ccsid1146':
  8857. case 'cp1146':
  8858. case 'ebcdicgb285euro':
  8859. case 'ibm1146':
  8860. return 'IBM01146';
  8861. case 'ccsid1147':
  8862. case 'cp1147':
  8863. case 'ebcdicfr297euro':
  8864. case 'ibm1147':
  8865. return 'IBM01147';
  8866. case 'ccsid1148':
  8867. case 'cp1148':
  8868. case 'ebcdicinternational500euro':
  8869. case 'ibm1148':
  8870. return 'IBM01148';
  8871. case 'ccsid1149':
  8872. case 'cp1149':
  8873. case 'ebcdicis871euro':
  8874. case 'ibm1149':
  8875. return 'IBM01149';
  8876. case 'csiso143iecp271':
  8877. case 'iecp271':
  8878. case 'isoir143':
  8879. return 'IEC_P27-1';
  8880. case 'csiso49inis':
  8881. case 'inis':
  8882. case 'isoir49':
  8883. return 'INIS';
  8884. case 'csiso50inis8':
  8885. case 'inis8':
  8886. case 'isoir50':
  8887. return 'INIS-8';
  8888. case 'csiso51iniscyrillic':
  8889. case 'iniscyrillic':
  8890. case 'isoir51':
  8891. return 'INIS-cyrillic';
  8892. case 'csinvariant':
  8893. case 'invariant':
  8894. return 'INVARIANT';
  8895. case 'iso2022cn':
  8896. return 'ISO-2022-CN';
  8897. case 'iso2022cnext':
  8898. return 'ISO-2022-CN-EXT';
  8899. case 'csiso2022jp':
  8900. case 'iso2022jp':
  8901. return 'ISO-2022-JP';
  8902. case 'csiso2022jp2':
  8903. case 'iso2022jp2':
  8904. return 'ISO-2022-JP-2';
  8905. case 'csiso2022kr':
  8906. case 'iso2022kr':
  8907. return 'ISO-2022-KR';
  8908. case 'cswindows30latin1':
  8909. case 'iso88591windows30latin1':
  8910. return 'ISO-8859-1-Windows-3.0-Latin-1';
  8911. case 'cswindows31latin1':
  8912. case 'iso88591windows31latin1':
  8913. return 'ISO-8859-1-Windows-3.1-Latin-1';
  8914. case 'csisolatin2':
  8915. case 'iso88592':
  8916. case 'iso885921987':
  8917. case 'isoir101':
  8918. case 'l2':
  8919. case 'latin2':
  8920. return 'ISO-8859-2';
  8921. case 'cswindows31latin2':
  8922. case 'iso88592windowslatin2':
  8923. return 'ISO-8859-2-Windows-Latin-2';
  8924. case 'csisolatin3':
  8925. case 'iso88593':
  8926. case 'iso885931988':
  8927. case 'isoir109':
  8928. case 'l3':
  8929. case 'latin3':
  8930. return 'ISO-8859-3';
  8931. case 'csisolatin4':
  8932. case 'iso88594':
  8933. case 'iso885941988':
  8934. case 'isoir110':
  8935. case 'l4':
  8936. case 'latin4':
  8937. return 'ISO-8859-4';
  8938. case 'csisolatincyrillic':
  8939. case 'cyrillic':
  8940. case 'iso88595':
  8941. case 'iso885951988':
  8942. case 'isoir144':
  8943. return 'ISO-8859-5';
  8944. case 'arabic':
  8945. case 'asmo708':
  8946. case 'csisolatinarabic':
  8947. case 'ecma114':
  8948. case 'iso88596':
  8949. case 'iso885961987':
  8950. case 'isoir127':
  8951. return 'ISO-8859-6';
  8952. case 'csiso88596e':
  8953. case 'iso88596e':
  8954. return 'ISO-8859-6-E';
  8955. case 'csiso88596i':
  8956. case 'iso88596i':
  8957. return 'ISO-8859-6-I';
  8958. case 'csisolatingreek':
  8959. case 'ecma118':
  8960. case 'elot928':
  8961. case 'greek':
  8962. case 'greek8':
  8963. case 'iso88597':
  8964. case 'iso885971987':
  8965. case 'isoir126':
  8966. return 'ISO-8859-7';
  8967. case 'csisolatinhebrew':
  8968. case 'hebrew':
  8969. case 'iso88598':
  8970. case 'iso885981988':
  8971. case 'isoir138':
  8972. return 'ISO-8859-8';
  8973. case 'csiso88598e':
  8974. case 'iso88598e':
  8975. return 'ISO-8859-8-E';
  8976. case 'csiso88598i':
  8977. case 'iso88598i':
  8978. return 'ISO-8859-8-I';
  8979. case 'cswindows31latin5':
  8980. case 'iso88599windowslatin5':
  8981. return 'ISO-8859-9-Windows-Latin-5';
  8982. case 'csisolatin6':
  8983. case 'iso885910':
  8984. case 'iso8859101992':
  8985. case 'isoir157':
  8986. case 'l6':
  8987. case 'latin6':
  8988. return 'ISO-8859-10';
  8989. case 'iso885913':
  8990. return 'ISO-8859-13';
  8991. case 'iso885914':
  8992. case 'iso8859141998':
  8993. case 'isoceltic':
  8994. case 'isoir199':
  8995. case 'l8':
  8996. case 'latin8':
  8997. return 'ISO-8859-14';
  8998. case 'iso885915':
  8999. case 'latin9':
  9000. return 'ISO-8859-15';
  9001. case 'iso885916':
  9002. case 'iso8859162001':
  9003. case 'isoir226':
  9004. case 'l10':
  9005. case 'latin10':
  9006. return 'ISO-8859-16';
  9007. case 'iso10646j1':
  9008. return 'ISO-10646-J-1';
  9009. case 'csunicode':
  9010. case 'iso10646ucs2':
  9011. return 'ISO-10646-UCS-2';
  9012. case 'csucs4':
  9013. case 'iso10646ucs4':
  9014. return 'ISO-10646-UCS-4';
  9015. case 'csunicodeascii':
  9016. case 'iso10646ucsbasic':
  9017. return 'ISO-10646-UCS-Basic';
  9018. case 'csunicodelatin1':
  9019. case 'iso10646':
  9020. case 'iso10646unicodelatin1':
  9021. return 'ISO-10646-Unicode-Latin1';
  9022. case 'csiso10646utf1':
  9023. case 'iso10646utf1':
  9024. return 'ISO-10646-UTF-1';
  9025. case 'csiso115481':
  9026. case 'iso115481':
  9027. case 'isotr115481':
  9028. return 'ISO-11548-1';
  9029. case 'csiso90':
  9030. case 'isoir90':
  9031. return 'iso-ir-90';
  9032. case 'csunicodeibm1261':
  9033. case 'isounicodeibm1261':
  9034. return 'ISO-Unicode-IBM-1261';
  9035. case 'csunicodeibm1264':
  9036. case 'isounicodeibm1264':
  9037. return 'ISO-Unicode-IBM-1264';
  9038. case 'csunicodeibm1265':
  9039. case 'isounicodeibm1265':
  9040. return 'ISO-Unicode-IBM-1265';
  9041. case 'csunicodeibm1268':
  9042. case 'isounicodeibm1268':
  9043. return 'ISO-Unicode-IBM-1268';
  9044. case 'csunicodeibm1276':
  9045. case 'isounicodeibm1276':
  9046. return 'ISO-Unicode-IBM-1276';
  9047. case 'csiso646basic1983':
  9048. case 'iso646basic1983':
  9049. case 'ref':
  9050. return 'ISO_646.basic:1983';
  9051. case 'csiso2intlrefversion':
  9052. case 'irv':
  9053. case 'iso646irv1983':
  9054. case 'isoir2':
  9055. return 'ISO_646.irv:1983';
  9056. case 'csiso2033':
  9057. case 'e13b':
  9058. case 'iso20331983':
  9059. case 'isoir98':
  9060. return 'ISO_2033-1983';
  9061. case 'csiso5427cyrillic':
  9062. case 'iso5427':
  9063. case 'isoir37':
  9064. return 'ISO_5427';
  9065. case 'iso5427cyrillic1981':
  9066. case 'iso54271981':
  9067. case 'isoir54':
  9068. return 'ISO_5427:1981';
  9069. case 'csiso5428greek':
  9070. case 'iso54281980':
  9071. case 'isoir55':
  9072. return 'ISO_5428:1980';
  9073. case 'csiso6937add':
  9074. case 'iso6937225':
  9075. case 'isoir152':
  9076. return 'ISO_6937-2-25';
  9077. case 'csisotextcomm':
  9078. case 'iso69372add':
  9079. case 'isoir142':
  9080. return 'ISO_6937-2-add';
  9081. case 'csiso8859supp':
  9082. case 'iso8859supp':
  9083. case 'isoir154':
  9084. case 'latin125':
  9085. return 'ISO_8859-supp';
  9086. case 'csiso10367box':
  9087. case 'iso10367box':
  9088. case 'isoir155':
  9089. return 'ISO_10367-box';
  9090. case 'csiso15italian':
  9091. case 'iso646it':
  9092. case 'isoir15':
  9093. case 'it':
  9094. return 'IT';
  9095. case 'csiso13jisc6220jp':
  9096. case 'isoir13':
  9097. case 'jisc62201969':
  9098. case 'jisc62201969jp':
  9099. case 'katakana':
  9100. case 'x2017':
  9101. return 'JIS_C6220-1969-jp';
  9102. case 'csiso14jisc6220ro':
  9103. case 'iso646jp':
  9104. case 'isoir14':
  9105. case 'jisc62201969ro':
  9106. case 'jp':
  9107. return 'JIS_C6220-1969-ro';
  9108. case 'csiso42jisc62261978':
  9109. case 'isoir42':
  9110. case 'jisc62261978':
  9111. return 'JIS_C6226-1978';
  9112. case 'csiso87jisx208':
  9113. case 'isoir87':
  9114. case 'jisc62261983':
  9115. case 'jisx2081983':
  9116. case 'x208':
  9117. return 'JIS_C6226-1983';
  9118. case 'csiso91jisc62291984a':
  9119. case 'isoir91':
  9120. case 'jisc62291984a':
  9121. case 'jpocra':
  9122. return 'JIS_C6229-1984-a';
  9123. case 'csiso92jisc62991984b':
  9124. case 'iso646jpocrb':
  9125. case 'isoir92':
  9126. case 'jisc62291984b':
  9127. case 'jpocrb':
  9128. return 'JIS_C6229-1984-b';
  9129. case 'csiso93jis62291984badd':
  9130. case 'isoir93':
  9131. case 'jisc62291984badd':
  9132. case 'jpocrbadd':
  9133. return 'JIS_C6229-1984-b-add';
  9134. case 'csiso94jis62291984hand':
  9135. case 'isoir94':
  9136. case 'jisc62291984hand':
  9137. case 'jpocrhand':
  9138. return 'JIS_C6229-1984-hand';
  9139. case 'csiso95jis62291984handadd':
  9140. case 'isoir95':
  9141. case 'jisc62291984handadd':
  9142. case 'jpocrhandadd':
  9143. return 'JIS_C6229-1984-hand-add';
  9144. case 'csiso96jisc62291984kana':
  9145. case 'isoir96':
  9146. case 'jisc62291984kana':
  9147. return 'JIS_C6229-1984-kana';
  9148. case 'csjisencoding':
  9149. case 'jisencoding':
  9150. return 'JIS_Encoding';
  9151. case 'cshalfwidthkatakana':
  9152. case 'jisx201':
  9153. case 'x201':
  9154. return 'JIS_X0201';
  9155. case 'csiso159jisx2121990':
  9156. case 'isoir159':
  9157. case 'jisx2121990':
  9158. case 'x212':
  9159. return 'JIS_X0212-1990';
  9160. case 'csiso141jusib1002':
  9161. case 'iso646yu':
  9162. case 'isoir141':
  9163. case 'js':
  9164. case 'jusib1002':
  9165. case 'yu':
  9166. return 'JUS_I.B1.002';
  9167. case 'csiso147macedonian':
  9168. case 'isoir147':
  9169. case 'jusib1003mac':
  9170. case 'macedonian':
  9171. return 'JUS_I.B1.003-mac';
  9172. case 'csiso146serbian':
  9173. case 'isoir146':
  9174. case 'jusib1003serb':
  9175. case 'serbian':
  9176. return 'JUS_I.B1.003-serb';
  9177. case 'koi7switched':
  9178. return 'KOI7-switched';
  9179. case 'cskoi8r':
  9180. case 'koi8r':
  9181. return 'KOI8-R';
  9182. case 'koi8u':
  9183. return 'KOI8-U';
  9184. case 'csksc5636':
  9185. case 'iso646kr':
  9186. case 'ksc5636':
  9187. return 'KSC5636';
  9188. case 'cskz1048':
  9189. case 'kz1048':
  9190. case 'rk1048':
  9191. case 'strk10482002':
  9192. return 'KZ-1048';
  9193. case 'csiso19latingreek':
  9194. case 'isoir19':
  9195. case 'latingreek':
  9196. return 'latin-greek';
  9197. case 'csiso27latingreek1':
  9198. case 'isoir27':
  9199. case 'latingreek1':
  9200. return 'Latin-greek-1';
  9201. case 'csiso158lap':
  9202. case 'isoir158':
  9203. case 'lap':
  9204. case 'latinlap':
  9205. return 'latin-lap';
  9206. case 'csmacintosh':
  9207. case 'mac':
  9208. case 'macintosh':
  9209. return 'macintosh';
  9210. case 'csmicrosoftpublishing':
  9211. case 'microsoftpublishing':
  9212. return 'Microsoft-Publishing';
  9213. case 'csmnem':
  9214. case 'mnem':
  9215. return 'MNEM';
  9216. case 'csmnemonic':
  9217. case 'mnemonic':
  9218. return 'MNEMONIC';
  9219. case 'csiso86hungarian':
  9220. case 'hu':
  9221. case 'iso646hu':
  9222. case 'isoir86':
  9223. case 'msz77953':
  9224. return 'MSZ_7795.3';
  9225. case 'csnatsdano':
  9226. case 'isoir91':
  9227. case 'natsdano':
  9228. return 'NATS-DANO';
  9229. case 'csnatsdanoadd':
  9230. case 'isoir92':
  9231. case 'natsdanoadd':
  9232. return 'NATS-DANO-ADD';
  9233. case 'csnatssefi':
  9234. case 'isoir81':
  9235. case 'natssefi':
  9236. return 'NATS-SEFI';
  9237. case 'csnatssefiadd':
  9238. case 'isoir82':
  9239. case 'natssefiadd':
  9240. return 'NATS-SEFI-ADD';
  9241. case 'csiso151cuba':
  9242. case 'cuba':
  9243. case 'iso646cu':
  9244. case 'isoir151':
  9245. case 'ncnc1081':
  9246. return 'NC_NC00-10:81';
  9247. case 'csiso69french':
  9248. case 'fr':
  9249. case 'iso646fr':
  9250. case 'isoir69':
  9251. case 'nfz62010':
  9252. return 'NF_Z_62-010';
  9253. case 'csiso25french':
  9254. case 'iso646fr1':
  9255. case 'isoir25':
  9256. case 'nfz620101973':
  9257. return 'NF_Z_62-010_(1973)';
  9258. case 'csiso60danishnorwegian':
  9259. case 'csiso60norwegian1':
  9260. case 'iso646no':
  9261. case 'isoir60':
  9262. case 'no':
  9263. case 'ns45511':
  9264. return 'NS_4551-1';
  9265. case 'csiso61norwegian2':
  9266. case 'iso646no2':
  9267. case 'isoir61':
  9268. case 'no2':
  9269. case 'ns45512':
  9270. return 'NS_4551-2';
  9271. case 'osdebcdicdf3irv':
  9272. return 'OSD_EBCDIC_DF03_IRV';
  9273. case 'osdebcdicdf41':
  9274. return 'OSD_EBCDIC_DF04_1';
  9275. case 'osdebcdicdf415':
  9276. return 'OSD_EBCDIC_DF04_15';
  9277. case 'cspc8danishnorwegian':
  9278. case 'pc8danishnorwegian':
  9279. return 'PC8-Danish-Norwegian';
  9280. case 'cspc8turkish':
  9281. case 'pc8turkish':
  9282. return 'PC8-Turkish';
  9283. case 'csiso16portuguese':
  9284. case 'iso646pt':
  9285. case 'isoir16':
  9286. case 'pt':
  9287. return 'PT';
  9288. case 'csiso84portuguese2':
  9289. case 'iso646pt2':
  9290. case 'isoir84':
  9291. case 'pt2':
  9292. return 'PT2';
  9293. case 'cp154':
  9294. case 'csptcp154':
  9295. case 'cyrillicasian':
  9296. case 'pt154':
  9297. case 'ptcp154':
  9298. return 'PTCP154';
  9299. case 'scsu':
  9300. return 'SCSU';
  9301. case 'csiso10swedish':
  9302. case 'fi':
  9303. case 'iso646fi':
  9304. case 'iso646se':
  9305. case 'isoir10':
  9306. case 'se':
  9307. case 'sen850200b':
  9308. return 'SEN_850200_B';
  9309. case 'csiso11swedishfornames':
  9310. case 'iso646se2':
  9311. case 'isoir11':
  9312. case 'se2':
  9313. case 'sen850200c':
  9314. return 'SEN_850200_C';
  9315. case 'csiso102t617bit':
  9316. case 'isoir102':
  9317. case 't617bit':
  9318. return 'T.61-7bit';
  9319. case 'csiso103t618bit':
  9320. case 'isoir103':
  9321. case 't61':
  9322. case 't618bit':
  9323. return 'T.61-8bit';
  9324. case 'csiso128t101g2':
  9325. case 'isoir128':
  9326. case 't101g2':
  9327. return 'T.101-G2';
  9328. case 'cstscii':
  9329. case 'tscii':
  9330. return 'TSCII';
  9331. case 'csunicode11':
  9332. case 'unicode11':
  9333. return 'UNICODE-1-1';
  9334. case 'csunicode11utf7':
  9335. case 'unicode11utf7':
  9336. return 'UNICODE-1-1-UTF-7';
  9337. case 'csunknown8bit':
  9338. case 'unknown8bit':
  9339. return 'UNKNOWN-8BIT';
  9340. case 'ansix341968':
  9341. case 'ansix341986':
  9342. case 'ascii':
  9343. case 'cp367':
  9344. case 'csascii':
  9345. case 'ibm367':
  9346. case 'iso646irv1991':
  9347. case 'iso646us':
  9348. case 'isoir6':
  9349. case 'us':
  9350. case 'usascii':
  9351. return 'US-ASCII';
  9352. case 'csusdk':
  9353. case 'usdk':
  9354. return 'us-dk';
  9355. case 'utf7':
  9356. return 'UTF-7';
  9357. case 'utf8':
  9358. return 'UTF-8';
  9359. case 'utf16':
  9360. return 'UTF-16';
  9361. case 'utf16be':
  9362. return 'UTF-16BE';
  9363. case 'utf16le':
  9364. return 'UTF-16LE';
  9365. case 'utf32':
  9366. return 'UTF-32';
  9367. case 'utf32be':
  9368. return 'UTF-32BE';
  9369. case 'utf32le':
  9370. return 'UTF-32LE';
  9371. case 'csventurainternational':
  9372. case 'venturainternational':
  9373. return 'Ventura-International';
  9374. case 'csventuramath':
  9375. case 'venturamath':
  9376. return 'Ventura-Math';
  9377. case 'csventuraus':
  9378. case 'venturaus':
  9379. return 'Ventura-US';
  9380. case 'csiso70videotexsupp1':
  9381. case 'isoir70':
  9382. case 'videotexsuppl':
  9383. return 'videotex-suppl';
  9384. case 'csviqr':
  9385. case 'viqr':
  9386. return 'VIQR';
  9387. case 'csviscii':
  9388. case 'viscii':
  9389. return 'VISCII';
  9390. case 'csshiftjis':
  9391. case 'cswindows31j':
  9392. case 'mskanji':
  9393. case 'shiftjis':
  9394. case 'windows31j':
  9395. return 'Windows-31J';
  9396. case 'iso885911':
  9397. case 'tis620':
  9398. return 'windows-874';
  9399. case 'cseuckr':
  9400. case 'csksc56011987':
  9401. case 'euckr':
  9402. case 'isoir149':
  9403. case 'korean':
  9404. case 'ksc5601':
  9405. case 'ksc56011987':
  9406. case 'ksc56011989':
  9407. case 'windows949':
  9408. return 'windows-949';
  9409. case 'windows1250':
  9410. return 'windows-1250';
  9411. case 'windows1251':
  9412. return 'windows-1251';
  9413. case 'cp819':
  9414. case 'csisolatin1':
  9415. case 'ibm819':
  9416. case 'iso88591':
  9417. case 'iso885911987':
  9418. case 'isoir100':
  9419. case 'l1':
  9420. case 'latin1':
  9421. case 'windows1252':
  9422. return 'windows-1252';
  9423. case 'windows1253':
  9424. return 'windows-1253';
  9425. case 'csisolatin5':
  9426. case 'iso88599':
  9427. case 'iso885991989':
  9428. case 'isoir148':
  9429. case 'l5':
  9430. case 'latin5':
  9431. case 'windows1254':
  9432. return 'windows-1254';
  9433. case 'windows1255':
  9434. return 'windows-1255';
  9435. case 'windows1256':
  9436. return 'windows-1256';
  9437. case 'windows1257':
  9438. return 'windows-1257';
  9439. case 'windows1258':
  9440. return 'windows-1258';
  9441. default:
  9442. return $charset;
  9443. }
  9444. }
  9445. public static function get_curl_version()
  9446. {
  9447. if (is_array($curl = curl_version()))
  9448. {
  9449. $curl = $curl['version'];
  9450. }
  9451. elseif (substr($curl, 0, 5) === 'curl/')
  9452. {
  9453. $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
  9454. }
  9455. elseif (substr($curl, 0, 8) === 'libcurl/')
  9456. {
  9457. $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
  9458. }
  9459. else
  9460. {
  9461. $curl = 0;
  9462. }
  9463. return $curl;
  9464. }
  9465. public static function is_subclass_of($class1, $class2)
  9466. {
  9467. if (func_num_args() !== 2)
  9468. {
  9469. trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
  9470. }
  9471. elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
  9472. {
  9473. return is_subclass_of($class1, $class2);
  9474. }
  9475. elseif (is_string($class1) && is_string($class2))
  9476. {
  9477. if (class_exists($class1))
  9478. {
  9479. if (class_exists($class2))
  9480. {
  9481. $class2 = strtolower($class2);
  9482. while ($class1 = strtolower(get_parent_class($class1)))
  9483. {
  9484. if ($class1 === $class2)
  9485. {
  9486. return true;
  9487. }
  9488. }
  9489. }
  9490. }
  9491. else
  9492. {
  9493. trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
  9494. }
  9495. }
  9496. return false;
  9497. }
  9498. /**
  9499. * Strip HTML comments
  9500. *
  9501. * @access public
  9502. * @param string $data Data to strip comments from
  9503. * @return string Comment stripped string
  9504. */
  9505. public static function strip_comments($data)
  9506. {
  9507. $output = '';
  9508. while (($start = strpos($data, '<!--')) !== false)
  9509. {
  9510. $output .= substr($data, 0, $start);
  9511. if (($end = strpos($data, '-->', $start)) !== false)
  9512. {
  9513. $data = substr_replace($data, '', 0, $end + 3);
  9514. }
  9515. else
  9516. {
  9517. $data = '';
  9518. }
  9519. }
  9520. return $output . $data;
  9521. }
  9522. public static function parse_date($dt)
  9523. {
  9524. $parser = SimplePie_Parse_Date::get();
  9525. return $parser->parse($dt);
  9526. }
  9527. /**
  9528. * Decode HTML entities
  9529. *
  9530. * @static
  9531. * @access public
  9532. * @param string $data Input data
  9533. * @return string Output data
  9534. */
  9535. public static function entities_decode($data)
  9536. {
  9537. $decoder = new SimplePie_Decode_HTML_Entities($data);
  9538. return $decoder->parse();
  9539. }
  9540. /**
  9541. * Remove RFC822 comments
  9542. *
  9543. * @access public
  9544. * @param string $data Data to strip comments from
  9545. * @return string Comment stripped string
  9546. */
  9547. public static function uncomment_rfc822($string)
  9548. {
  9549. $string = (string) $string;
  9550. $position = 0;
  9551. $length = strlen($string);
  9552. $depth = 0;
  9553. $output = '';
  9554. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  9555. {
  9556. $output .= substr($string, $position, $pos - $position);
  9557. $position = $pos + 1;
  9558. if ($string[$pos - 1] !== '\\')
  9559. {
  9560. $depth++;
  9561. while ($depth && $position < $length)
  9562. {
  9563. $position += strcspn($string, '()', $position);
  9564. if ($string[$position - 1] === '\\')
  9565. {
  9566. $position++;
  9567. continue;
  9568. }
  9569. elseif (isset($string[$position]))
  9570. {
  9571. switch ($string[$position])
  9572. {
  9573. case '(':
  9574. $depth++;
  9575. break;
  9576. case ')':
  9577. $depth--;
  9578. break;
  9579. }
  9580. $position++;
  9581. }
  9582. else
  9583. {
  9584. break;
  9585. }
  9586. }
  9587. }
  9588. else
  9589. {
  9590. $output .= '(';
  9591. }
  9592. }
  9593. $output .= substr($string, $position);
  9594. return $output;
  9595. }
  9596. public static function parse_mime($mime)
  9597. {
  9598. if (($pos = strpos($mime, ';')) === false)
  9599. {
  9600. return trim($mime);
  9601. }
  9602. else
  9603. {
  9604. return trim(substr($mime, 0, $pos));
  9605. }
  9606. }
  9607. public static function htmlspecialchars_decode($string, $quote_style)
  9608. {
  9609. if (function_exists('htmlspecialchars_decode'))
  9610. {
  9611. return htmlspecialchars_decode($string, $quote_style);
  9612. }
  9613. else
  9614. {
  9615. return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
  9616. }
  9617. }
  9618. public static function atom_03_construct_type($attribs)
  9619. {
  9620. if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
  9621. {
  9622. $mode = SIMPLEPIE_CONSTRUCT_BASE64;
  9623. }
  9624. else
  9625. {
  9626. $mode = SIMPLEPIE_CONSTRUCT_NONE;
  9627. }
  9628. if (isset($attribs['']['type']))
  9629. {
  9630. switch (strtolower(trim($attribs['']['type'])))
  9631. {
  9632. case 'text':
  9633. case 'text/plain':
  9634. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  9635. case 'html':
  9636. case 'text/html':
  9637. return SIMPLEPIE_CONSTRUCT_HTML | $mode;
  9638. case 'xhtml':
  9639. case 'application/xhtml+xml':
  9640. return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
  9641. default:
  9642. return SIMPLEPIE_CONSTRUCT_NONE | $mode;
  9643. }
  9644. }
  9645. else
  9646. {
  9647. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  9648. }
  9649. }
  9650. public static function atom_10_construct_type($attribs)
  9651. {
  9652. if (isset($attribs['']['type']))
  9653. {
  9654. switch (strtolower(trim($attribs['']['type'])))
  9655. {
  9656. case 'text':
  9657. return SIMPLEPIE_CONSTRUCT_TEXT;
  9658. case 'html':
  9659. return SIMPLEPIE_CONSTRUCT_HTML;
  9660. case 'xhtml':
  9661. return SIMPLEPIE_CONSTRUCT_XHTML;
  9662. default:
  9663. return SIMPLEPIE_CONSTRUCT_NONE;
  9664. }
  9665. }
  9666. return SIMPLEPIE_CONSTRUCT_TEXT;
  9667. }
  9668. public static function atom_10_content_construct_type($attribs)
  9669. {
  9670. if (isset($attribs['']['type']))
  9671. {
  9672. $type = strtolower(trim($attribs['']['type']));
  9673. switch ($type)
  9674. {
  9675. case 'text':
  9676. return SIMPLEPIE_CONSTRUCT_TEXT;
  9677. case 'html':
  9678. return SIMPLEPIE_CONSTRUCT_HTML;
  9679. case 'xhtml':
  9680. return SIMPLEPIE_CONSTRUCT_XHTML;
  9681. }
  9682. if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
  9683. {
  9684. return SIMPLEPIE_CONSTRUCT_NONE;
  9685. }
  9686. else
  9687. {
  9688. return SIMPLEPIE_CONSTRUCT_BASE64;
  9689. }
  9690. }
  9691. else
  9692. {
  9693. return SIMPLEPIE_CONSTRUCT_TEXT;
  9694. }
  9695. }
  9696. public static function is_isegment_nz_nc($string)
  9697. {
  9698. 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);
  9699. }
  9700. public static function space_seperated_tokens($string)
  9701. {
  9702. $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
  9703. $string_length = strlen($string);
  9704. $position = strspn($string, $space_characters);
  9705. $tokens = array();
  9706. while ($position < $string_length)
  9707. {
  9708. $len = strcspn($string, $space_characters, $position);
  9709. $tokens[] = substr($string, $position, $len);
  9710. $position += $len;
  9711. $position += strspn($string, $space_characters, $position);
  9712. }
  9713. return $tokens;
  9714. }
  9715. public static function array_unique($array)
  9716. {
  9717. if (version_compare(PHP_VERSION, '5.2', '>='))
  9718. {
  9719. return array_unique($array);
  9720. }
  9721. else
  9722. {
  9723. $array = (array) $array;
  9724. $new_array = array();
  9725. $new_array_strings = array();
  9726. foreach ($array as $key => $value)
  9727. {
  9728. if (is_object($value))
  9729. {
  9730. if (method_exists($value, '__toString'))
  9731. {
  9732. $cmp = $value->__toString();
  9733. }
  9734. else
  9735. {
  9736. trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
  9737. }
  9738. }
  9739. elseif (is_array($value))
  9740. {
  9741. $cmp = (string) reset($value);
  9742. }
  9743. else
  9744. {
  9745. $cmp = (string) $value;
  9746. }
  9747. if (!in_array($cmp, $new_array_strings))
  9748. {
  9749. $new_array[$key] = $value;
  9750. $new_array_strings[] = $cmp;
  9751. }
  9752. }
  9753. return $new_array;
  9754. }
  9755. }
  9756. /**
  9757. * Converts a unicode codepoint to a UTF-8 character
  9758. *
  9759. * @static
  9760. * @access public
  9761. * @param int $codepoint Unicode codepoint
  9762. * @return string UTF-8 character
  9763. */
  9764. public static function codepoint_to_utf8($codepoint)
  9765. {
  9766. $codepoint = (int) $codepoint;
  9767. if ($codepoint < 0)
  9768. {
  9769. return false;
  9770. }
  9771. else if ($codepoint <= 0x7f)
  9772. {
  9773. return chr($codepoint);
  9774. }
  9775. else if ($codepoint <= 0x7ff)
  9776. {
  9777. return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
  9778. }
  9779. else if ($codepoint <= 0xffff)
  9780. {
  9781. return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  9782. }
  9783. else if ($codepoint <= 0x10ffff)
  9784. {
  9785. return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  9786. }
  9787. else
  9788. {
  9789. // U+FFFD REPLACEMENT CHARACTER
  9790. return "\xEF\xBF\xBD";
  9791. }
  9792. }
  9793. /**
  9794. * Similar to parse_str()
  9795. *
  9796. * Returns an associative array of name/value pairs, where the value is an
  9797. * array of values that have used the same name
  9798. *
  9799. * @static
  9800. * @access string
  9801. * @param string $str The input string.
  9802. * @return array
  9803. */
  9804. public static function parse_str($str)
  9805. {
  9806. $return = array();
  9807. $str = explode('&', $str);
  9808. foreach ($str as $section)
  9809. {
  9810. if (strpos($section, '=') !== false)
  9811. {
  9812. list($name, $value) = explode('=', $section, 2);
  9813. $return[urldecode($name)][] = urldecode($value);
  9814. }
  9815. else
  9816. {
  9817. $return[urldecode($section)][] = null;
  9818. }
  9819. }
  9820. return $return;
  9821. }
  9822. /**
  9823. * Detect XML encoding, as per XML 1.0 Appendix F.1
  9824. *
  9825. * @todo Add support for EBCDIC
  9826. * @param string $data XML data
  9827. * @return array Possible encodings
  9828. */
  9829. public static function xml_encoding($data)
  9830. {
  9831. // UTF-32 Big Endian BOM
  9832. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  9833. {
  9834. $encoding[] = 'UTF-32BE';
  9835. }
  9836. // UTF-32 Little Endian BOM
  9837. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  9838. {
  9839. $encoding[] = 'UTF-32LE';
  9840. }
  9841. // UTF-16 Big Endian BOM
  9842. elseif (substr($data, 0, 2) === "\xFE\xFF")
  9843. {
  9844. $encoding[] = 'UTF-16BE';
  9845. }
  9846. // UTF-16 Little Endian BOM
  9847. elseif (substr($data, 0, 2) === "\xFF\xFE")
  9848. {
  9849. $encoding[] = 'UTF-16LE';
  9850. }
  9851. // UTF-8 BOM
  9852. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  9853. {
  9854. $encoding[] = 'UTF-8';
  9855. }
  9856. // UTF-32 Big Endian Without BOM
  9857. 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")
  9858. {
  9859. if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
  9860. {
  9861. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
  9862. if ($parser->parse())
  9863. {
  9864. $encoding[] = $parser->encoding;
  9865. }
  9866. }
  9867. $encoding[] = 'UTF-32BE';
  9868. }
  9869. // UTF-32 Little Endian Without BOM
  9870. 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")
  9871. {
  9872. if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
  9873. {
  9874. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
  9875. if ($parser->parse())
  9876. {
  9877. $encoding[] = $parser->encoding;
  9878. }
  9879. }
  9880. $encoding[] = 'UTF-32LE';
  9881. }
  9882. // UTF-16 Big Endian Without BOM
  9883. elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
  9884. {
  9885. if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
  9886. {
  9887. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
  9888. if ($parser->parse())
  9889. {
  9890. $encoding[] = $parser->encoding;
  9891. }
  9892. }
  9893. $encoding[] = 'UTF-16BE';
  9894. }
  9895. // UTF-16 Little Endian Without BOM
  9896. elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
  9897. {
  9898. if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
  9899. {
  9900. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
  9901. if ($parser->parse())
  9902. {
  9903. $encoding[] = $parser->encoding;
  9904. }
  9905. }
  9906. $encoding[] = 'UTF-16LE';
  9907. }
  9908. // US-ASCII (or superset)
  9909. elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
  9910. {
  9911. if ($pos = strpos($data, "\x3F\x3E"))
  9912. {
  9913. $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  9914. if ($parser->parse())
  9915. {
  9916. $encoding[] = $parser->encoding;
  9917. }
  9918. }
  9919. $encoding[] = 'UTF-8';
  9920. }
  9921. // Fallback to UTF-8
  9922. else
  9923. {
  9924. $encoding[] = 'UTF-8';
  9925. }
  9926. return $encoding;
  9927. }
  9928. public static function output_javascript()
  9929. {
  9930. if (function_exists('ob_gzhandler'))
  9931. {
  9932. ob_start('ob_gzhandler');
  9933. }
  9934. header('Content-type: text/javascript; charset: UTF-8');
  9935. header('Cache-Control: must-revalidate');
  9936. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
  9937. ?>
  9938. function embed_odeo(link) {
  9939. 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>');
  9940. }
  9941. function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
  9942. if (placeholder != '') {
  9943. 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>');
  9944. }
  9945. else {
  9946. 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>');
  9947. }
  9948. }
  9949. function embed_flash(bgcolor, width, height, link, loop, type) {
  9950. 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>');
  9951. }
  9952. function embed_flv(width, height, link, placeholder, loop, player) {
  9953. 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>');
  9954. }
  9955. function embed_wmedia(width, height, link) {
  9956. document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
  9957. }
  9958. <?php
  9959. }
  9960. }
  9961. /**
  9962. * Decode HTML Entities
  9963. *
  9964. * This implements HTML5 as of revision 967 (2007-06-28)
  9965. *
  9966. * @package SimplePie
  9967. */
  9968. class SimplePie_Decode_HTML_Entities
  9969. {
  9970. /**
  9971. * Data to be parsed
  9972. *
  9973. * @access private
  9974. * @var string
  9975. */
  9976. var $data = '';
  9977. /**
  9978. * Currently consumed bytes
  9979. *
  9980. * @access private
  9981. * @var string
  9982. */
  9983. var $consumed = '';
  9984. /**
  9985. * Position of the current byte being parsed
  9986. *
  9987. * @access private
  9988. * @var int
  9989. */
  9990. var $position = 0;
  9991. /**
  9992. * Create an instance of the class with the input data
  9993. *
  9994. * @access public
  9995. * @param string $data Input data
  9996. */
  9997. public function __construct($data)
  9998. {
  9999. $this->data = $data;
  10000. }
  10001. /**
  10002. * Parse the input data
  10003. *
  10004. * @access public
  10005. * @return string Output data
  10006. */
  10007. public function parse()
  10008. {
  10009. while (($this->position = strpos($this->data, '&', $this->position)) !== false)
  10010. {
  10011. $this->consume();
  10012. $this->entity();
  10013. $this->consumed = '';
  10014. }
  10015. return $this->data;
  10016. }
  10017. /**
  10018. * Consume the next byte
  10019. *
  10020. * @access private
  10021. * @return mixed The next byte, or false, if there is no more data
  10022. */
  10023. public function consume()
  10024. {
  10025. if (isset($this->data[$this->position]))
  10026. {
  10027. $this->consumed .= $this->data[$this->position];
  10028. return $this->data[$this->position++];
  10029. }
  10030. else
  10031. {
  10032. return false;
  10033. }
  10034. }
  10035. /**
  10036. * Consume a range of characters
  10037. *
  10038. * @access private
  10039. * @param string $chars Characters to consume
  10040. * @return mixed A series of characters that match the range, or false
  10041. */
  10042. public function consume_range($chars)
  10043. {
  10044. if ($len = strspn($this->data, $chars, $this->position))
  10045. {
  10046. $data = substr($this->data, $this->position, $len);
  10047. $this->consumed .= $data;
  10048. $this->position += $len;
  10049. return $data;
  10050. }
  10051. else
  10052. {
  10053. return false;
  10054. }
  10055. }
  10056. /**
  10057. * Unconsume one byte
  10058. *
  10059. * @access private
  10060. */
  10061. public function unconsume()
  10062. {
  10063. $this->consumed = substr($this->consumed, 0, -1);
  10064. $this->position--;
  10065. }
  10066. /**
  10067. * Decode an entity
  10068. *
  10069. * @access private
  10070. */
  10071. public function entity()
  10072. {
  10073. switch ($this->consume())
  10074. {
  10075. case "\x09":
  10076. case "\x0A":
  10077. case "\x0B":
  10078. case "\x0B":
  10079. case "\x0C":
  10080. case "\x20":
  10081. case "\x3C":
  10082. case "\x26":
  10083. case false:
  10084. break;
  10085. case "\x23":
  10086. switch ($this->consume())
  10087. {
  10088. case "\x78":
  10089. case "\x58":
  10090. $range = '0123456789ABCDEFabcdef';
  10091. $hex = true;
  10092. break;
  10093. default:
  10094. $range = '0123456789';
  10095. $hex = false;
  10096. $this->unconsume();
  10097. break;
  10098. }
  10099. if ($codepoint = $this->consume_range($range))
  10100. {
  10101. 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");
  10102. if ($hex)
  10103. {
  10104. $codepoint = hexdec($codepoint);
  10105. }
  10106. else
  10107. {
  10108. $codepoint = intval($codepoint);
  10109. }
  10110. if (isset($windows_1252_specials[$codepoint]))
  10111. {
  10112. $replacement = $windows_1252_specials[$codepoint];
  10113. }
  10114. else
  10115. {
  10116. $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
  10117. }
  10118. if (!in_array($this->consume(), array(';', false), true))
  10119. {
  10120. $this->unconsume();
  10121. }
  10122. $consumed_length = strlen($this->consumed);
  10123. $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
  10124. $this->position += strlen($replacement) - $consumed_length;
  10125. }
  10126. break;
  10127. default:
  10128. 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");
  10129. for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
  10130. {
  10131. $consumed = substr($this->consumed, 1);
  10132. if (isset($entities[$consumed]))
  10133. {
  10134. $match = $consumed;
  10135. }
  10136. }
  10137. if ($match !== null)
  10138. {
  10139. $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
  10140. $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
  10141. }
  10142. break;
  10143. }
  10144. }
  10145. }
  10146. /**
  10147. * IRI parser/serialiser
  10148. *
  10149. * @package SimplePie
  10150. */
  10151. class SimplePie_IRI
  10152. {
  10153. /**
  10154. * Scheme
  10155. *
  10156. * @access private
  10157. * @var string
  10158. */
  10159. var $scheme;
  10160. /**
  10161. * User Information
  10162. *
  10163. * @access private
  10164. * @var string
  10165. */
  10166. var $userinfo;
  10167. /**
  10168. * Host
  10169. *
  10170. * @access private
  10171. * @var string
  10172. */
  10173. var $host;
  10174. /**
  10175. * Port
  10176. *
  10177. * @access private
  10178. * @var string
  10179. */
  10180. var $port;
  10181. /**
  10182. * Path
  10183. *
  10184. * @access private
  10185. * @var string
  10186. */
  10187. var $path;
  10188. /**
  10189. * Query
  10190. *
  10191. * @access private
  10192. * @var string
  10193. */
  10194. var $query;
  10195. /**
  10196. * Fragment
  10197. *
  10198. * @access private
  10199. * @var string
  10200. */
  10201. var $fragment;
  10202. /**
  10203. * Whether the object represents a valid IRI
  10204. *
  10205. * @access private
  10206. * @var array
  10207. */
  10208. var $valid = array();
  10209. /**
  10210. * Return the entire IRI when you try and read the object as a string
  10211. *
  10212. * @access public
  10213. * @return string
  10214. */
  10215. public function __toString()
  10216. {
  10217. return $this->get_iri();
  10218. }
  10219. /**
  10220. * Create a new IRI object, from a specified string
  10221. *
  10222. * @access public
  10223. * @param string $iri
  10224. * @return SimplePie_IRI
  10225. */
  10226. public function __construct($iri)
  10227. {
  10228. $iri = (string) $iri;
  10229. if ($iri !== '')
  10230. {
  10231. $parsed = $this->parse_iri($iri);
  10232. $this->set_scheme($parsed['scheme']);
  10233. $this->set_authority($parsed['authority']);
  10234. $this->set_path($parsed['path']);
  10235. $this->set_query($parsed['query']);
  10236. $this->set_fragment($parsed['fragment']);
  10237. }
  10238. }
  10239. /**
  10240. * Create a new IRI object by resolving a relative IRI
  10241. *
  10242. * @static
  10243. * @access public
  10244. * @param SimplePie_IRI $base Base IRI
  10245. * @param string $relative Relative IRI
  10246. * @return SimplePie_IRI
  10247. */
  10248. public static function absolutize($base, $relative)
  10249. {
  10250. $relative = (string) $relative;
  10251. if ($relative !== '')
  10252. {
  10253. $relative = new SimplePie_IRI($relative);
  10254. if ($relative->get_scheme() !== null)
  10255. {
  10256. $target = $relative;
  10257. }
  10258. elseif ($base->get_iri() !== null)
  10259. {
  10260. if ($relative->get_authority() !== null)
  10261. {
  10262. $target = $relative;
  10263. $target->set_scheme($base->get_scheme());
  10264. }
  10265. else
  10266. {
  10267. $target = new SimplePie_IRI('');
  10268. $target->set_scheme($base->get_scheme());
  10269. $target->set_userinfo($base->get_userinfo());
  10270. $target->set_host($base->get_host());
  10271. $target->set_port($base->get_port());
  10272. if ($relative->get_path() !== null)
  10273. {
  10274. if (strpos($relative->get_path(), '/') === 0)
  10275. {
  10276. $target->set_path($relative->get_path());
  10277. }
  10278. elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
  10279. {
  10280. $target->set_path('/' . $relative->get_path());
  10281. }
  10282. elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
  10283. {
  10284. $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
  10285. }
  10286. else
  10287. {
  10288. $target->set_path($relative->get_path());
  10289. }
  10290. $target->set_query($relative->get_query());
  10291. }
  10292. else
  10293. {
  10294. $target->set_path($base->get_path());
  10295. if ($relative->get_query() !== null)
  10296. {
  10297. $target->set_query($relative->get_query());
  10298. }
  10299. elseif ($base->get_query() !== null)
  10300. {
  10301. $target->set_query($base->get_query());
  10302. }
  10303. }
  10304. }
  10305. $target->set_fragment($relative->get_fragment());
  10306. }
  10307. else
  10308. {
  10309. // No base URL, just return the relative URL
  10310. $target = $relative;
  10311. }
  10312. }
  10313. else
  10314. {
  10315. $target = $base;
  10316. }
  10317. return $target;
  10318. }
  10319. /**
  10320. * Parse an IRI into scheme/authority/path/query/fragment segments
  10321. *
  10322. * @access private
  10323. * @param string $iri
  10324. * @return array
  10325. */
  10326. public function parse_iri($iri)
  10327. {
  10328. preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
  10329. for ($i = count($match); $i <= 9; $i++)
  10330. {
  10331. $match[$i] = '';
  10332. }
  10333. return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
  10334. }
  10335. /**
  10336. * Remove dot segments from a path
  10337. *
  10338. * @access private
  10339. * @param string $input
  10340. * @return string
  10341. */
  10342. public function remove_dot_segments($input)
  10343. {
  10344. $output = '';
  10345. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  10346. {
  10347. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  10348. if (strpos($input, '../') === 0)
  10349. {
  10350. $input = substr($input, 3);
  10351. }
  10352. elseif (strpos($input, './') === 0)
  10353. {
  10354. $input = substr($input, 2);
  10355. }
  10356. // 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,
  10357. elseif (strpos($input, '/./') === 0)
  10358. {
  10359. $input = substr_replace($input, '/', 0, 3);
  10360. }
  10361. elseif ($input === '/.')
  10362. {
  10363. $input = '/';
  10364. }
  10365. // 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,
  10366. elseif (strpos($input, '/../') === 0)
  10367. {
  10368. $input = substr_replace($input, '/', 0, 4);
  10369. $output = substr_replace($output, '', strrpos($output, '/'));
  10370. }
  10371. elseif ($input === '/..')
  10372. {
  10373. $input = '/';
  10374. $output = substr_replace($output, '', strrpos($output, '/'));
  10375. }
  10376. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  10377. elseif ($input === '.' || $input === '..')
  10378. {
  10379. $input = '';
  10380. }
  10381. // 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
  10382. elseif (($pos = strpos($input, '/', 1)) !== false)
  10383. {
  10384. $output .= substr($input, 0, $pos);
  10385. $input = substr_replace($input, '', 0, $pos);
  10386. }
  10387. else
  10388. {
  10389. $output .= $input;
  10390. $input = '';
  10391. }
  10392. }
  10393. return $output . $input;
  10394. }
  10395. /**
  10396. * Replace invalid character with percent encoding
  10397. *
  10398. * @access private
  10399. * @param string $string Input string
  10400. * @param string $valid_chars Valid characters
  10401. * @param int $case Normalise case
  10402. * @return string
  10403. */
  10404. public function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
  10405. {
  10406. // Normalise case
  10407. if ($case & SIMPLEPIE_LOWERCASE)
  10408. {
  10409. $string = strtolower($string);
  10410. }
  10411. elseif ($case & SIMPLEPIE_UPPERCASE)
  10412. {
  10413. $string = strtoupper($string);
  10414. }
  10415. // Store position and string length (to avoid constantly recalculating this)
  10416. $position = 0;
  10417. $strlen = strlen($string);
  10418. // Loop as long as we have invalid characters, advancing the position to the next invalid character
  10419. while (($position += strspn($string, $valid_chars, $position)) < $strlen)
  10420. {
  10421. // If we have a % character
  10422. if ($string[$position] === '%')
  10423. {
  10424. // If we have a pct-encoded section
  10425. if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
  10426. {
  10427. // Get the the represented character
  10428. $chr = chr(hexdec(substr($string, $position + 1, 2)));
  10429. // If the character is valid, replace the pct-encoded with the actual character while normalising case
  10430. if (strpos($valid_chars, $chr) !== false)
  10431. {
  10432. if ($case & SIMPLEPIE_LOWERCASE)
  10433. {
  10434. $chr = strtolower($chr);
  10435. }
  10436. elseif ($case & SIMPLEPIE_UPPERCASE)
  10437. {
  10438. $chr = strtoupper($chr);
  10439. }
  10440. $string = substr_replace($string, $chr, $position, 3);
  10441. $strlen -= 2;
  10442. $position++;
  10443. }
  10444. // Otherwise just normalise the pct-encoded to uppercase
  10445. else
  10446. {
  10447. $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
  10448. $position += 3;
  10449. }
  10450. }
  10451. // If we don't have a pct-encoded section, just replace the % with its own esccaped form
  10452. else
  10453. {
  10454. $string = substr_replace($string, '%25', $position, 1);
  10455. $strlen += 2;
  10456. $position += 3;
  10457. }
  10458. }
  10459. // If we have an invalid character, change into its pct-encoded form
  10460. else
  10461. {
  10462. $replacement = sprintf("%%%02X", ord($string[$position]));
  10463. $string = str_replace($string[$position], $replacement, $string);
  10464. $strlen = strlen($string);
  10465. }
  10466. }
  10467. return $string;
  10468. }
  10469. /**
  10470. * Check if the object represents a valid IRI
  10471. *
  10472. * @access public
  10473. * @return bool
  10474. */
  10475. public function is_valid()
  10476. {
  10477. return array_sum($this->valid) === count($this->valid);
  10478. }
  10479. /**
  10480. * Set the scheme. Returns true on success, false on failure (if there are
  10481. * any invalid characters).
  10482. *
  10483. * @access public
  10484. * @param string $scheme
  10485. * @return bool
  10486. */
  10487. public function set_scheme($scheme)
  10488. {
  10489. if ($scheme === null || $scheme === '')
  10490. {
  10491. $this->scheme = null;
  10492. }
  10493. else
  10494. {
  10495. $len = strlen($scheme);
  10496. switch (true)
  10497. {
  10498. case $len > 1:
  10499. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
  10500. {
  10501. $this->scheme = null;
  10502. $this->valid[__FUNCTION__] = false;
  10503. return false;
  10504. }
  10505. case $len > 0:
  10506. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
  10507. {
  10508. $this->scheme = null;
  10509. $this->valid[__FUNCTION__] = false;
  10510. return false;
  10511. }
  10512. }
  10513. $this->scheme = strtolower($scheme);
  10514. }
  10515. $this->valid[__FUNCTION__] = true;
  10516. return true;
  10517. }
  10518. /**
  10519. * Set the authority. Returns true on success, false on failure (if there are
  10520. * any invalid characters).
  10521. *
  10522. * @access public
  10523. * @param string $authority
  10524. * @return bool
  10525. */
  10526. public function set_authority($authority)
  10527. {
  10528. if (($userinfo_end = strrpos($authority, '@')) !== false)
  10529. {
  10530. $userinfo = substr($authority, 0, $userinfo_end);
  10531. $authority = substr($authority, $userinfo_end + 1);
  10532. }
  10533. else
  10534. {
  10535. $userinfo = null;
  10536. }
  10537. if (($port_start = strpos($authority, ':')) !== false)
  10538. {
  10539. $port = substr($authority, $port_start + 1);
  10540. $authority = substr($authority, 0, $port_start);
  10541. }
  10542. else
  10543. {
  10544. $port = null;
  10545. }
  10546. return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
  10547. }
  10548. /**
  10549. * Set the userinfo.
  10550. *
  10551. * @access public
  10552. * @param string $userinfo
  10553. * @return bool
  10554. */
  10555. public function set_userinfo($userinfo)
  10556. {
  10557. if ($userinfo === null || $userinfo === '')
  10558. {
  10559. $this->userinfo = null;
  10560. }
  10561. else
  10562. {
  10563. $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
  10564. }
  10565. $this->valid[__FUNCTION__] = true;
  10566. return true;
  10567. }
  10568. /**
  10569. * Set the host. Returns true on success, false on failure (if there are
  10570. * any invalid characters).
  10571. *
  10572. * @access public
  10573. * @param string $host
  10574. * @return bool
  10575. */
  10576. public function set_host($host)
  10577. {
  10578. if ($host === null || $host === '')
  10579. {
  10580. $this->host = null;
  10581. $this->valid[__FUNCTION__] = true;
  10582. return true;
  10583. }
  10584. elseif ($host[0] === '[' && substr($host, -1) === ']')
  10585. {
  10586. if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
  10587. {
  10588. $this->host = $host;
  10589. $this->valid[__FUNCTION__] = true;
  10590. return true;
  10591. }
  10592. else
  10593. {
  10594. $this->host = null;
  10595. $this->valid[__FUNCTION__] = false;
  10596. return false;
  10597. }
  10598. }
  10599. else
  10600. {
  10601. $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
  10602. $this->valid[__FUNCTION__] = true;
  10603. return true;
  10604. }
  10605. }
  10606. /**
  10607. * Set the port. Returns true on success, false on failure (if there are
  10608. * any invalid characters).
  10609. *
  10610. * @access public
  10611. * @param string $port
  10612. * @return bool
  10613. */
  10614. public function set_port($port)
  10615. {
  10616. if ($port === null || $port === '')
  10617. {
  10618. $this->port = null;
  10619. $this->valid[__FUNCTION__] = true;
  10620. return true;
  10621. }
  10622. elseif (strspn($port, '0123456789') === strlen($port))
  10623. {
  10624. $this->port = (int) $port;
  10625. $this->valid[__FUNCTION__] = true;
  10626. return true;
  10627. }
  10628. else
  10629. {
  10630. $this->port = null;
  10631. $this->valid[__FUNCTION__] = false;
  10632. return false;
  10633. }
  10634. }
  10635. /**
  10636. * Set the path.
  10637. *
  10638. * @access public
  10639. * @param string $path
  10640. * @return bool
  10641. */
  10642. public function set_path($path)
  10643. {
  10644. if ($path === null || $path === '')
  10645. {
  10646. $this->path = null;
  10647. $this->valid[__FUNCTION__] = true;
  10648. return true;
  10649. }
  10650. elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
  10651. {
  10652. $this->path = null;
  10653. $this->valid[__FUNCTION__] = false;
  10654. return false;
  10655. }
  10656. else
  10657. {
  10658. $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
  10659. if ($this->scheme !== null)
  10660. {
  10661. $this->path = $this->remove_dot_segments($this->path);
  10662. }
  10663. $this->valid[__FUNCTION__] = true;
  10664. return true;
  10665. }
  10666. }
  10667. /**
  10668. * Set the query.
  10669. *
  10670. * @access public
  10671. * @param string $query
  10672. * @return bool
  10673. */
  10674. public function set_query($query)
  10675. {
  10676. if ($query === null || $query === '')
  10677. {
  10678. $this->query = null;
  10679. }
  10680. else
  10681. {
  10682. $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$\'()*+,;:@/?&=');
  10683. }
  10684. $this->valid[__FUNCTION__] = true;
  10685. return true;
  10686. }
  10687. /**
  10688. * Set the fragment.
  10689. *
  10690. * @access public
  10691. * @param string $fragment
  10692. * @return bool
  10693. */
  10694. public function set_fragment($fragment)
  10695. {
  10696. if ($fragment === null || $fragment === '')
  10697. {
  10698. $this->fragment = null;
  10699. }
  10700. else
  10701. {
  10702. $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
  10703. }
  10704. $this->valid[__FUNCTION__] = true;
  10705. return true;
  10706. }
  10707. /**
  10708. * Get the complete IRI
  10709. *
  10710. * @access public
  10711. * @return string
  10712. */
  10713. public function get_iri()
  10714. {
  10715. $iri = '';
  10716. if ($this->scheme !== null)
  10717. {
  10718. $iri .= $this->scheme . ':';
  10719. }
  10720. if (($authority = $this->get_authority()) !== null)
  10721. {
  10722. $iri .= '//' . $authority;
  10723. }
  10724. if ($this->path !== null)
  10725. {
  10726. $iri .= $this->path;
  10727. }
  10728. if ($this->query !== null)
  10729. {
  10730. $iri .= '?' . $this->query;
  10731. }
  10732. if ($this->fragment !== null)
  10733. {
  10734. $iri .= '#' . $this->fragment;
  10735. }
  10736. if ($iri !== '')
  10737. {
  10738. return $iri;
  10739. }
  10740. else
  10741. {
  10742. return null;
  10743. }
  10744. }
  10745. /**
  10746. * Get the scheme
  10747. *
  10748. * @access public
  10749. * @return string
  10750. */
  10751. public function get_scheme()
  10752. {
  10753. return $this->scheme;
  10754. }
  10755. /**
  10756. * Get the complete authority
  10757. *
  10758. * @access public
  10759. * @return string
  10760. */
  10761. public function get_authority()
  10762. {
  10763. $authority = '';
  10764. if ($this->userinfo !== null)
  10765. {
  10766. $authority .= $this->userinfo . '@';
  10767. }
  10768. if ($this->host !== null)
  10769. {
  10770. $authority .= $this->host;
  10771. }
  10772. if ($this->port !== null)
  10773. {
  10774. $authority .= ':' . $this->port;
  10775. }
  10776. if ($authority !== '')
  10777. {
  10778. return $authority;
  10779. }
  10780. else
  10781. {
  10782. return null;
  10783. }
  10784. }
  10785. /**
  10786. * Get the user information
  10787. *
  10788. * @access public
  10789. * @return string
  10790. */
  10791. public function get_userinfo()
  10792. {
  10793. return $this->userinfo;
  10794. }
  10795. /**
  10796. * Get the host
  10797. *
  10798. * @access public
  10799. * @return string
  10800. */
  10801. public function get_host()
  10802. {
  10803. return $this->host;
  10804. }
  10805. /**
  10806. * Get the port
  10807. *
  10808. * @access public
  10809. * @return string
  10810. */
  10811. public function get_port()
  10812. {
  10813. return $this->port;
  10814. }
  10815. /**
  10816. * Get the path
  10817. *
  10818. * @access public
  10819. * @return string
  10820. */
  10821. public function get_path()
  10822. {
  10823. return $this->path;
  10824. }
  10825. /**
  10826. * Get the query
  10827. *
  10828. * @access public
  10829. * @return string
  10830. */
  10831. public function get_query()
  10832. {
  10833. return $this->query;
  10834. }
  10835. /**
  10836. * Get the fragment
  10837. *
  10838. * @access public
  10839. * @return string
  10840. */
  10841. public function get_fragment()
  10842. {
  10843. return $this->fragment;
  10844. }
  10845. }
  10846. /**
  10847. * Class to validate and to work with IPv6 addresses.
  10848. *
  10849. * @package SimplePie
  10850. * @copyright 2003-2005 The PHP Group
  10851. * @license http://www.opensource.org/licenses/bsd-license.php
  10852. * @link http://pear.php.net/package/Net_IPv6
  10853. * @author Alexander Merz <alexander.merz@web.de>
  10854. * @author elfrink at introweb dot nl
  10855. * @author Josh Peck <jmp at joshpeck dot org>
  10856. * @author Geoffrey Sneddon <geoffers@gmail.com>
  10857. */
  10858. class SimplePie_Net_IPv6
  10859. {
  10860. /**
  10861. * Removes a possible existing netmask specification of an IP address.
  10862. *
  10863. * @param string $ip the (compressed) IP as Hex representation
  10864. * @return string the IP the without netmask
  10865. * @since 1.1.0
  10866. * @access public
  10867. * @static
  10868. */
  10869. public static function removeNetmaskSpec($ip)
  10870. {
  10871. if (strpos($ip, '/') !== false)
  10872. {
  10873. list($addr, $nm) = explode('/', $ip);
  10874. }
  10875. else
  10876. {
  10877. $addr = $ip;
  10878. }
  10879. return $addr;
  10880. }
  10881. /**
  10882. * Uncompresses an IPv6 address
  10883. *
  10884. * RFC 2373 allows you to compress zeros in an address to '::'. This
  10885. * function expects an valid IPv6 address and expands the '::' to
  10886. * the required zeros.
  10887. *
  10888. * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
  10889. * ::1 -> 0:0:0:0:0:0:0:1
  10890. *
  10891. * @access public
  10892. * @static
  10893. * @param string $ip a valid IPv6-address (hex format)
  10894. * @return string the uncompressed IPv6-address (hex format)
  10895. */
  10896. public static function Uncompress($ip)
  10897. {
  10898. $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
  10899. $c1 = -1;
  10900. $c2 = -1;
  10901. if (strpos($ip, '::') !== false)
  10902. {
  10903. list($ip1, $ip2) = explode('::', $ip);
  10904. if ($ip1 === '')
  10905. {
  10906. $c1 = -1;
  10907. }
  10908. else
  10909. {
  10910. $pos = 0;
  10911. if (($pos = substr_count($ip1, ':')) > 0)
  10912. {
  10913. $c1 = $pos;
  10914. }
  10915. else
  10916. {
  10917. $c1 = 0;
  10918. }
  10919. }
  10920. if ($ip2 === '')
  10921. {
  10922. $c2 = -1;
  10923. }
  10924. else
  10925. {
  10926. $pos = 0;
  10927. if (($pos = substr_count($ip2, ':')) > 0)
  10928. {
  10929. $c2 = $pos;
  10930. }
  10931. else
  10932. {
  10933. $c2 = 0;
  10934. }
  10935. }
  10936. if (strstr($ip2, '.'))
  10937. {
  10938. $c2++;
  10939. }
  10940. // ::
  10941. if ($c1 === -1 && $c2 === -1)
  10942. {
  10943. $uip = '0:0:0:0:0:0:0:0';
  10944. }
  10945. // ::xxx
  10946. else if ($c1 === -1)
  10947. {
  10948. $fill = str_repeat('0:', 7 - $c2);
  10949. $uip = str_replace('::', $fill, $uip);
  10950. }
  10951. // xxx::
  10952. else if ($c2 === -1)
  10953. {
  10954. $fill = str_repeat(':0', 7 - $c1);
  10955. $uip = str_replace('::', $fill, $uip);
  10956. }
  10957. // xxx::xxx
  10958. else
  10959. {
  10960. $fill = str_repeat(':0:', 6 - $c2 - $c1);
  10961. $uip = str_replace('::', $fill, $uip);
  10962. $uip = str_replace('::', ':', $uip);
  10963. }
  10964. }
  10965. return $uip;
  10966. }
  10967. /**
  10968. * Splits an IPv6 address into the IPv6 and a possible IPv4 part
  10969. *
  10970. * RFC 2373 allows you to note the last two parts of an IPv6 address as
  10971. * an IPv4 compatible address
  10972. *
  10973. * Example: 0:0:0:0:0:0:13.1.68.3
  10974. * 0:0:0:0:0:FFFF:129.144.52.38
  10975. *
  10976. * @access public
  10977. * @static
  10978. * @param string $ip a valid IPv6-address (hex format)
  10979. * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
  10980. */
  10981. public static function SplitV64($ip)
  10982. {
  10983. $ip = SimplePie_Net_IPv6::Uncompress($ip);
  10984. if (strstr($ip, '.'))
  10985. {
  10986. $pos = strrpos($ip, ':');
  10987. $ip[$pos] = '_';
  10988. $ipPart = explode('_', $ip);
  10989. return $ipPart;
  10990. }
  10991. else
  10992. {
  10993. return array($ip, '');
  10994. }
  10995. }
  10996. /**
  10997. * Checks an IPv6 address
  10998. *
  10999. * Checks if the given IP is IPv6-compatible
  11000. *
  11001. * @access public
  11002. * @static
  11003. * @param string $ip a valid IPv6-address
  11004. * @return bool true if $ip is an IPv6 address
  11005. */
  11006. public static function checkIPv6($ip)
  11007. {
  11008. $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
  11009. $count = 0;
  11010. if (!empty($ipPart[0]))
  11011. {
  11012. $ipv6 = explode(':', $ipPart[0]);
  11013. for ($i = 0; $i < count($ipv6); $i++)
  11014. {
  11015. $dec = hexdec($ipv6[$i]);
  11016. $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
  11017. if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
  11018. {
  11019. $count++;
  11020. }
  11021. }
  11022. if ($count === 8)
  11023. {
  11024. return true;
  11025. }
  11026. elseif ($count === 6 && !empty($ipPart[1]))
  11027. {
  11028. $ipv4 = explode('.', $ipPart[1]);
  11029. $count = 0;
  11030. foreach ($ipv4 as $ipv4_part)
  11031. {
  11032. if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
  11033. {
  11034. $count++;
  11035. }
  11036. }
  11037. if ($count === 4)
  11038. {
  11039. return true;
  11040. }
  11041. }
  11042. else
  11043. {
  11044. return false;
  11045. }
  11046. }
  11047. else
  11048. {
  11049. return false;
  11050. }
  11051. }
  11052. }
  11053. /**
  11054. * Date Parser
  11055. *
  11056. * @package SimplePie
  11057. */
  11058. class SimplePie_Parse_Date
  11059. {
  11060. /**
  11061. * Input data
  11062. *
  11063. * @access protected
  11064. * @var string
  11065. */
  11066. var $date;
  11067. /**
  11068. * List of days, calendar day name => ordinal day number in the week
  11069. *
  11070. * @access protected
  11071. * @var array
  11072. */
  11073. var $day = array(
  11074. // English
  11075. 'mon' => 1,
  11076. 'monday' => 1,
  11077. 'tue' => 2,
  11078. 'tuesday' => 2,
  11079. 'wed' => 3,
  11080. 'wednesday' => 3,
  11081. 'thu' => 4,
  11082. 'thursday' => 4,
  11083. 'fri' => 5,
  11084. 'friday' => 5,
  11085. 'sat' => 6,
  11086. 'saturday' => 6,
  11087. 'sun' => 7,
  11088. 'sunday' => 7,
  11089. // Dutch
  11090. 'maandag' => 1,
  11091. 'dinsdag' => 2,
  11092. 'woensdag' => 3,
  11093. 'donderdag' => 4,
  11094. 'vrijdag' => 5,
  11095. 'zaterdag' => 6,
  11096. 'zondag' => 7,
  11097. // French
  11098. 'lundi' => 1,
  11099. 'mardi' => 2,
  11100. 'mercredi' => 3,
  11101. 'jeudi' => 4,
  11102. 'vendredi' => 5,
  11103. 'samedi' => 6,
  11104. 'dimanche' => 7,
  11105. // German
  11106. 'montag' => 1,
  11107. 'dienstag' => 2,
  11108. 'mittwoch' => 3,
  11109. 'donnerstag' => 4,
  11110. 'freitag' => 5,
  11111. 'samstag' => 6,
  11112. 'sonnabend' => 6,
  11113. 'sonntag' => 7,
  11114. // Italian
  11115. 'lunedì' => 1,
  11116. 'martedì' => 2,
  11117. 'mercoledì' => 3,
  11118. 'giovedì' => 4,
  11119. 'venerdì' => 5,
  11120. 'sabato' => 6,
  11121. 'domenica' => 7,
  11122. // Spanish
  11123. 'lunes' => 1,
  11124. 'martes' => 2,
  11125. 'miércoles' => 3,
  11126. 'jueves' => 4,
  11127. 'viernes' => 5,
  11128. 'sábado' => 6,
  11129. 'domingo' => 7,
  11130. // Finnish
  11131. 'maanantai' => 1,
  11132. 'tiistai' => 2,
  11133. 'keskiviikko' => 3,
  11134. 'torstai' => 4,
  11135. 'perjantai' => 5,
  11136. 'lauantai' => 6,
  11137. 'sunnuntai' => 7,
  11138. // Hungarian
  11139. 'hétfő' => 1,
  11140. 'kedd' => 2,
  11141. 'szerda' => 3,
  11142. 'csütörtok' => 4,
  11143. 'péntek' => 5,
  11144. 'szombat' => 6,
  11145. 'vasárnap' => 7,
  11146. // Greek
  11147. 'Δευ' => 1,
  11148. 'Τρι' => 2,
  11149. 'Τετ' => 3,
  11150. 'Πεμ' => 4,
  11151. 'Παρ' => 5,
  11152. 'Σαβ' => 6,
  11153. 'Κυρ' => 7,
  11154. );
  11155. /**
  11156. * List of months, calendar month name => calendar month number
  11157. *
  11158. * @access protected
  11159. * @var array
  11160. */
  11161. var $month = array(
  11162. // English
  11163. 'jan' => 1,
  11164. 'january' => 1,
  11165. 'feb' => 2,
  11166. 'february' => 2,
  11167. 'mar' => 3,
  11168. 'march' => 3,
  11169. 'apr' => 4,
  11170. 'april' => 4,
  11171. 'may' => 5,
  11172. // No long form of May
  11173. 'jun' => 6,
  11174. 'june' => 6,
  11175. 'jul' => 7,
  11176. 'july' => 7,
  11177. 'aug' => 8,
  11178. 'august' => 8,
  11179. 'sep' => 9,
  11180. 'september' => 8,
  11181. 'oct' => 10,
  11182. 'october' => 10,
  11183. 'nov' => 11,
  11184. 'november' => 11,
  11185. 'dec' => 12,
  11186. 'december' => 12,
  11187. // Dutch
  11188. 'januari' => 1,
  11189. 'februari' => 2,
  11190. 'maart' => 3,
  11191. 'april' => 4,
  11192. 'mei' => 5,
  11193. 'juni' => 6,
  11194. 'juli' => 7,
  11195. 'augustus' => 8,
  11196. 'september' => 9,
  11197. 'oktober' => 10,
  11198. 'november' => 11,
  11199. 'december' => 12,
  11200. // French
  11201. 'janvier' => 1,
  11202. 'février' => 2,
  11203. 'mars' => 3,
  11204. 'avril' => 4,
  11205. 'mai' => 5,
  11206. 'juin' => 6,
  11207. 'juillet' => 7,
  11208. 'août' => 8,
  11209. 'septembre' => 9,
  11210. 'octobre' => 10,
  11211. 'novembre' => 11,
  11212. 'décembre' => 12,
  11213. // German
  11214. 'januar' => 1,
  11215. 'februar' => 2,
  11216. 'märz' => 3,
  11217. 'april' => 4,
  11218. 'mai' => 5,
  11219. 'juni' => 6,
  11220. 'juli' => 7,
  11221. 'august' => 8,
  11222. 'september' => 9,
  11223. 'oktober' => 10,
  11224. 'november' => 11,
  11225. 'dezember' => 12,
  11226. // Italian
  11227. 'gennaio' => 1,
  11228. 'febbraio' => 2,
  11229. 'marzo' => 3,
  11230. 'aprile' => 4,
  11231. 'maggio' => 5,
  11232. 'giugno' => 6,
  11233. 'luglio' => 7,
  11234. 'agosto' => 8,
  11235. 'settembre' => 9,
  11236. 'ottobre' => 10,
  11237. 'novembre' => 11,
  11238. 'dicembre' => 12,
  11239. // Spanish
  11240. 'enero' => 1,
  11241. 'febrero' => 2,
  11242. 'marzo' => 3,
  11243. 'abril' => 4,
  11244. 'mayo' => 5,
  11245. 'junio' => 6,
  11246. 'julio' => 7,
  11247. 'agosto' => 8,
  11248. 'septiembre' => 9,
  11249. 'setiembre' => 9,
  11250. 'octubre' => 10,
  11251. 'noviembre' => 11,
  11252. 'diciembre' => 12,
  11253. // Finnish
  11254. 'tammikuu' => 1,
  11255. 'helmikuu' => 2,
  11256. 'maaliskuu' => 3,
  11257. 'huhtikuu' => 4,
  11258. 'toukokuu' => 5,
  11259. 'kesäkuu' => 6,
  11260. 'heinäkuu' => 7,
  11261. 'elokuu' => 8,
  11262. 'suuskuu' => 9,
  11263. 'lokakuu' => 10,
  11264. 'marras' => 11,
  11265. 'joulukuu' => 12,
  11266. // Hungarian
  11267. 'január' => 1,
  11268. 'február' => 2,
  11269. 'március' => 3,
  11270. 'április' => 4,
  11271. 'május' => 5,
  11272. 'június' => 6,
  11273. 'július' => 7,
  11274. 'augusztus' => 8,
  11275. 'szeptember' => 9,
  11276. 'október' => 10,
  11277. 'november' => 11,
  11278. 'december' => 12,
  11279. // Greek
  11280. 'Ιαν' => 1,
  11281. 'Φεβ' => 2,
  11282. 'Μάώ' => 3,
  11283. 'Μαώ' => 3,
  11284. 'Απρ' => 4,
  11285. 'Μάι' => 5,
  11286. 'Μαϊ' => 5,
  11287. 'Μαι' => 5,
  11288. 'Ιούν' => 6,
  11289. 'Ιον' => 6,
  11290. 'Ιούλ' => 7,
  11291. 'Ιολ' => 7,
  11292. 'Αύγ' => 8,
  11293. 'Αυγ' => 8,
  11294. 'Σεπ' => 9,
  11295. 'Οκτ' => 10,
  11296. 'Νοέ' => 11,
  11297. 'Δεκ' => 12,
  11298. );
  11299. /**
  11300. * List of timezones, abbreviation => offset from UTC
  11301. *
  11302. * @access protected
  11303. * @var array
  11304. */
  11305. var $timezone = array(
  11306. 'ACDT' => 37800,
  11307. 'ACIT' => 28800,
  11308. 'ACST' => 34200,
  11309. 'ACT' => -18000,
  11310. 'ACWDT' => 35100,
  11311. 'ACWST' => 31500,
  11312. 'AEDT' => 39600,
  11313. 'AEST' => 36000,
  11314. 'AFT' => 16200,
  11315. 'AKDT' => -28800,
  11316. 'AKST' => -32400,
  11317. 'AMDT' => 18000,
  11318. 'AMT' => -14400,
  11319. 'ANAST' => 46800,
  11320. 'ANAT' => 43200,
  11321. 'ART' => -10800,
  11322. 'AZOST' => -3600,
  11323. 'AZST' => 18000,
  11324. 'AZT' => 14400,
  11325. 'BIOT' => 21600,
  11326. 'BIT' => -43200,
  11327. 'BOT' => -14400,
  11328. 'BRST' => -7200,
  11329. 'BRT' => -10800,
  11330. 'BST' => 3600,
  11331. 'BTT' => 21600,
  11332. 'CAST' => 18000,
  11333. 'CAT' => 7200,
  11334. 'CCT' => 23400,
  11335. 'CDT' => -18000,
  11336. 'CEDT' => 7200,
  11337. 'CET' => 3600,
  11338. 'CGST' => -7200,
  11339. 'CGT' => -10800,
  11340. 'CHADT' => 49500,
  11341. 'CHAST' => 45900,
  11342. 'CIST' => -28800,
  11343. 'CKT' => -36000,
  11344. 'CLDT' => -10800,
  11345. 'CLST' => -14400,
  11346. 'COT' => -18000,
  11347. 'CST' => -21600,
  11348. 'CVT' => -3600,
  11349. 'CXT' => 25200,
  11350. 'DAVT' => 25200,
  11351. 'DTAT' => 36000,
  11352. 'EADT' => -18000,
  11353. 'EAST' => -21600,
  11354. 'EAT' => 10800,
  11355. 'ECT' => -18000,
  11356. 'EDT' => -14400,
  11357. 'EEST' => 10800,
  11358. 'EET' => 7200,
  11359. 'EGT' => -3600,
  11360. 'EKST' => 21600,
  11361. 'EST' => -18000,
  11362. 'FJT' => 43200,
  11363. 'FKDT' => -10800,
  11364. 'FKST' => -14400,
  11365. 'FNT' => -7200,
  11366. 'GALT' => -21600,
  11367. 'GEDT' => 14400,
  11368. 'GEST' => 10800,
  11369. 'GFT' => -10800,
  11370. 'GILT' => 43200,
  11371. 'GIT' => -32400,
  11372. 'GST' => 14400,
  11373. 'GST' => -7200,
  11374. 'GYT' => -14400,
  11375. 'HAA' => -10800,
  11376. 'HAC' => -18000,
  11377. 'HADT' => -32400,
  11378. 'HAE' => -14400,
  11379. 'HAP' => -25200,
  11380. 'HAR' => -21600,
  11381. 'HAST' => -36000,
  11382. 'HAT' => -9000,
  11383. 'HAY' => -28800,
  11384. 'HKST' => 28800,
  11385. 'HMT' => 18000,
  11386. 'HNA' => -14400,
  11387. 'HNC' => -21600,
  11388. 'HNE' => -18000,
  11389. 'HNP' => -28800,
  11390. 'HNR' => -25200,
  11391. 'HNT' => -12600,
  11392. 'HNY' => -32400,
  11393. 'IRDT' => 16200,
  11394. 'IRKST' => 32400,
  11395. 'IRKT' => 28800,
  11396. 'IRST' => 12600,
  11397. 'JFDT' => -10800,
  11398. 'JFST' => -14400,
  11399. 'JST' => 32400,
  11400. 'KGST' => 21600,
  11401. 'KGT' => 18000,
  11402. 'KOST' => 39600,
  11403. 'KOVST' => 28800,
  11404. 'KOVT' => 25200,
  11405. 'KRAST' => 28800,
  11406. 'KRAT' => 25200,
  11407. 'KST' => 32400,
  11408. 'LHDT' => 39600,
  11409. 'LHST' => 37800,
  11410. 'LINT' => 50400,
  11411. 'LKT' => 21600,
  11412. 'MAGST' => 43200,
  11413. 'MAGT' => 39600,
  11414. 'MAWT' => 21600,
  11415. 'MDT' => -21600,
  11416. 'MESZ' => 7200,
  11417. 'MEZ' => 3600,
  11418. 'MHT' => 43200,
  11419. 'MIT' => -34200,
  11420. 'MNST' => 32400,
  11421. 'MSDT' => 14400,
  11422. 'MSST' => 10800,
  11423. 'MST' => -25200,
  11424. 'MUT' => 14400,
  11425. 'MVT' => 18000,
  11426. 'MYT' => 28800,
  11427. 'NCT' => 39600,
  11428. 'NDT' => -9000,
  11429. 'NFT' => 41400,
  11430. 'NMIT' => 36000,
  11431. 'NOVST' => 25200,
  11432. 'NOVT' => 21600,
  11433. 'NPT' => 20700,
  11434. 'NRT' => 43200,
  11435. 'NST' => -12600,
  11436. 'NUT' => -39600,
  11437. 'NZDT' => 46800,
  11438. 'NZST' => 43200,
  11439. 'OMSST' => 25200,
  11440. 'OMST' => 21600,
  11441. 'PDT' => -25200,
  11442. 'PET' => -18000,
  11443. 'PETST' => 46800,
  11444. 'PETT' => 43200,
  11445. 'PGT' => 36000,
  11446. 'PHOT' => 46800,
  11447. 'PHT' => 28800,
  11448. 'PKT' => 18000,
  11449. 'PMDT' => -7200,
  11450. 'PMST' => -10800,
  11451. 'PONT' => 39600,
  11452. 'PST' => -28800,
  11453. 'PWT' => 32400,
  11454. 'PYST' => -10800,
  11455. 'PYT' => -14400,
  11456. 'RET' => 14400,
  11457. 'ROTT' => -10800,
  11458. 'SAMST' => 18000,
  11459. 'SAMT' => 14400,
  11460. 'SAST' => 7200,
  11461. 'SBT' => 39600,
  11462. 'SCDT' => 46800,
  11463. 'SCST' => 43200,
  11464. 'SCT' => 14400,
  11465. 'SEST' => 3600,
  11466. 'SGT' => 28800,
  11467. 'SIT' => 28800,
  11468. 'SRT' => -10800,
  11469. 'SST' => -39600,
  11470. 'SYST' => 10800,
  11471. 'SYT' => 7200,
  11472. 'TFT' => 18000,
  11473. 'THAT' => -36000,
  11474. 'TJT' => 18000,
  11475. 'TKT' => -36000,
  11476. 'TMT' => 18000,
  11477. 'TOT' => 46800,
  11478. 'TPT' => 32400,
  11479. 'TRUT' => 36000,
  11480. 'TVT' => 43200,
  11481. 'TWT' => 28800,
  11482. 'UYST' => -7200,
  11483. 'UYT' => -10800,
  11484. 'UZT' => 18000,
  11485. 'VET' => -14400,
  11486. 'VLAST' => 39600,
  11487. 'VLAT' => 36000,
  11488. 'VOST' => 21600,
  11489. 'VUT' => 39600,
  11490. 'WAST' => 7200,
  11491. 'WAT' => 3600,
  11492. 'WDT' => 32400,
  11493. 'WEST' => 3600,
  11494. 'WFT' => 43200,
  11495. 'WIB' => 25200,
  11496. 'WIT' => 32400,
  11497. 'WITA' => 28800,
  11498. 'WKST' => 18000,
  11499. 'WST' => 28800,
  11500. 'YAKST' => 36000,
  11501. 'YAKT' => 32400,
  11502. 'YAPT' => 36000,
  11503. 'YEKST' => 21600,
  11504. 'YEKT' => 18000,
  11505. );
  11506. /**
  11507. * Cached PCRE for SimplePie_Parse_Date::$day
  11508. *
  11509. * @access protected
  11510. * @var string
  11511. */
  11512. var $day_pcre;
  11513. /**
  11514. * Cached PCRE for SimplePie_Parse_Date::$month
  11515. *
  11516. * @access protected
  11517. * @var string
  11518. */
  11519. var $month_pcre;
  11520. /**
  11521. * Array of user-added callback methods
  11522. *
  11523. * @access private
  11524. * @var array
  11525. */
  11526. var $built_in = array();
  11527. /**
  11528. * Array of user-added callback methods
  11529. *
  11530. * @access private
  11531. * @var array
  11532. */
  11533. var $user = array();
  11534. /**
  11535. * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  11536. * self::month_pcre, and self::built_in
  11537. *
  11538. * @access private
  11539. */
  11540. public function __construct()
  11541. {
  11542. $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  11543. $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  11544. static $cache;
  11545. if (!isset($cache[get_class($this)]))
  11546. {
  11547. $all_methods = get_class_methods($this);
  11548. foreach ($all_methods as $method)
  11549. {
  11550. if (strtolower(substr($method, 0, 5)) === 'date_')
  11551. {
  11552. $cache[get_class($this)][] = $method;
  11553. }
  11554. }
  11555. }
  11556. foreach ($cache[get_class($this)] as $method)
  11557. {
  11558. $this->built_in[] = $method;
  11559. }
  11560. }
  11561. /**
  11562. * Get the object
  11563. *
  11564. * @access public
  11565. */
  11566. public static function get()
  11567. {
  11568. static $object;
  11569. if (!$object)
  11570. {
  11571. $object = new SimplePie_Parse_Date;
  11572. }
  11573. return $object;
  11574. }
  11575. /**
  11576. * Parse a date
  11577. *
  11578. * @final
  11579. * @access public
  11580. * @param string $date Date to parse
  11581. * @return int Timestamp corresponding to date string, or false on failure
  11582. */
  11583. public function parse($date)
  11584. {
  11585. foreach ($this->user as $method)
  11586. {
  11587. if (($returned = call_user_func($method, $date)) !== false)
  11588. {
  11589. return $returned;
  11590. }
  11591. }
  11592. foreach ($this->built_in as $method)
  11593. {
  11594. if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
  11595. {
  11596. return $returned;
  11597. }
  11598. }
  11599. return false;
  11600. }
  11601. /**
  11602. * Add a callback method to parse a date
  11603. *
  11604. * @final
  11605. * @access public
  11606. * @param callback $callback
  11607. */
  11608. public function add_callback($callback)
  11609. {
  11610. if (is_callable($callback))
  11611. {
  11612. $this->user[] = $callback;
  11613. }
  11614. else
  11615. {
  11616. trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  11617. }
  11618. }
  11619. /**
  11620. * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  11621. * well as allowing any of upper or lower case "T", horizontal tabs, or
  11622. * spaces to be used as the time seperator (including more than one))
  11623. *
  11624. * @access protected
  11625. * @return int Timestamp
  11626. */
  11627. public function date_w3cdtf($date)
  11628. {
  11629. static $pcre;
  11630. if (!$pcre)
  11631. {
  11632. $year = '([0-9]{4})';
  11633. $month = $day = $hour = $minute = $second = '([0-9]{2})';
  11634. $decimal = '([0-9]*)';
  11635. $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  11636. $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  11637. }
  11638. if (preg_match($pcre, $date, $match))
  11639. {
  11640. /*
  11641. Capturing subpatterns:
  11642. 1: Year
  11643. 2: Month
  11644. 3: Day
  11645. 4: Hour
  11646. 5: Minute
  11647. 6: Second
  11648. 7: Decimal fraction of a second
  11649. 8: Zulu
  11650. 9: Timezone ±
  11651. 10: Timezone hours
  11652. 11: Timezone minutes
  11653. */
  11654. // Fill in empty matches
  11655. for ($i = count($match); $i <= 3; $i++)
  11656. {
  11657. $match[$i] = '1';
  11658. }
  11659. for ($i = count($match); $i <= 7; $i++)
  11660. {
  11661. $match[$i] = '0';
  11662. }
  11663. // Numeric timezone
  11664. if (isset($match[9]) && $match[9] !== '')
  11665. {
  11666. $timezone = $match[10] * 3600;
  11667. $timezone += $match[11] * 60;
  11668. if ($match[9] === '-')
  11669. {
  11670. $timezone = 0 - $timezone;
  11671. }
  11672. }
  11673. else
  11674. {
  11675. $timezone = 0;
  11676. }
  11677. // Convert the number of seconds to an integer, taking decimals into account
  11678. $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  11679. return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  11680. }
  11681. else
  11682. {
  11683. return false;
  11684. }
  11685. }
  11686. /**
  11687. * Remove RFC822 comments
  11688. *
  11689. * @access protected
  11690. * @param string $data Data to strip comments from
  11691. * @return string Comment stripped string
  11692. */
  11693. public function remove_rfc2822_comments($string)
  11694. {
  11695. $string = (string) $string;
  11696. $position = 0;
  11697. $length = strlen($string);
  11698. $depth = 0;
  11699. $output = '';
  11700. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  11701. {
  11702. $output .= substr($string, $position, $pos - $position);
  11703. $position = $pos + 1;
  11704. if ($string[$pos - 1] !== '\\')
  11705. {
  11706. $depth++;
  11707. while ($depth && $position < $length)
  11708. {
  11709. $position += strcspn($string, '()', $position);
  11710. if ($string[$position - 1] === '\\')
  11711. {
  11712. $position++;
  11713. continue;
  11714. }
  11715. elseif (isset($string[$position]))
  11716. {
  11717. switch ($string[$position])
  11718. {
  11719. case '(':
  11720. $depth++;
  11721. break;
  11722. case ')':
  11723. $depth--;
  11724. break;
  11725. }
  11726. $position++;
  11727. }
  11728. else
  11729. {
  11730. break;
  11731. }
  11732. }
  11733. }
  11734. else
  11735. {
  11736. $output .= '(';
  11737. }
  11738. }
  11739. $output .= substr($string, $position);
  11740. return $output;
  11741. }
  11742. /**
  11743. * Parse RFC2822's date format
  11744. *
  11745. * @access protected
  11746. * @return int Timestamp
  11747. */
  11748. public function date_rfc2822($date)
  11749. {
  11750. static $pcre;
  11751. if (!$pcre)
  11752. {
  11753. $wsp = '[\x09\x20]';
  11754. $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  11755. $optional_fws = $fws . '?';
  11756. $day_name = $this->day_pcre;
  11757. $month = $this->month_pcre;
  11758. $day = '([0-9]{1,2})';
  11759. $hour = $minute = $second = '([0-9]{2})';
  11760. $year = '([0-9]{2,4})';
  11761. $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  11762. $character_zone = '([A-Z]{1,5})';
  11763. $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  11764. $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';
  11765. }
  11766. if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  11767. {
  11768. /*
  11769. Capturing subpatterns:
  11770. 1: Day name
  11771. 2: Day
  11772. 3: Month
  11773. 4: Year
  11774. 5: Hour
  11775. 6: Minute
  11776. 7: Second
  11777. 8: Timezone ±
  11778. 9: Timezone hours
  11779. 10: Timezone minutes
  11780. 11: Alphabetic timezone
  11781. */
  11782. // Find the month number
  11783. $month = $this->month[strtolower($match[3])];
  11784. // Numeric timezone
  11785. if ($match[8] !== '')
  11786. {
  11787. $timezone = $match[9] * 3600;
  11788. $timezone += $match[10] * 60;
  11789. if ($match[8] === '-')
  11790. {
  11791. $timezone = 0 - $timezone;
  11792. }
  11793. }
  11794. // Character timezone
  11795. elseif (isset($this->timezone[strtoupper($match[11])]))
  11796. {
  11797. $timezone = $this->timezone[strtoupper($match[11])];
  11798. }
  11799. // Assume everything else to be -0000
  11800. else
  11801. {
  11802. $timezone = 0;
  11803. }
  11804. // Deal with 2/3 digit years
  11805. if ($match[4] < 50)
  11806. {
  11807. $match[4] += 2000;
  11808. }
  11809. elseif ($match[4] < 1000)
  11810. {
  11811. $match[4] += 1900;
  11812. }
  11813. // Second is optional, if it is empty set it to zero
  11814. if ($match[7] !== '')
  11815. {
  11816. $second = $match[7];
  11817. }
  11818. else
  11819. {
  11820. $second = 0;
  11821. }
  11822. return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  11823. }
  11824. else
  11825. {
  11826. return false;
  11827. }
  11828. }
  11829. /**
  11830. * Parse RFC850's date format
  11831. *
  11832. * @access protected
  11833. * @return int Timestamp
  11834. */
  11835. public function date_rfc850($date)
  11836. {
  11837. static $pcre;
  11838. if (!$pcre)
  11839. {
  11840. $space = '[\x09\x20]+';
  11841. $day_name = $this->day_pcre;
  11842. $month = $this->month_pcre;
  11843. $day = '([0-9]{1,2})';
  11844. $year = $hour = $minute = $second = '([0-9]{2})';
  11845. $zone = '([A-Z]{1,5})';
  11846. $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  11847. }
  11848. if (preg_match($pcre, $date, $match))
  11849. {
  11850. /*
  11851. Capturing subpatterns:
  11852. 1: Day name
  11853. 2: Day
  11854. 3: Month
  11855. 4: Year
  11856. 5: Hour
  11857. 6: Minute
  11858. 7: Second
  11859. 8: Timezone
  11860. */
  11861. // Month
  11862. $month = $this->month[strtolower($match[3])];
  11863. // Character timezone
  11864. if (isset($this->timezone[strtoupper($match[8])]))
  11865. {
  11866. $timezone = $this->timezone[strtoupper($match[8])];
  11867. }
  11868. // Assume everything else to be -0000
  11869. else
  11870. {
  11871. $timezone = 0;
  11872. }
  11873. // Deal with 2 digit year
  11874. if ($match[4] < 50)
  11875. {
  11876. $match[4] += 2000;
  11877. }
  11878. else
  11879. {
  11880. $match[4] += 1900;
  11881. }
  11882. return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  11883. }
  11884. else
  11885. {
  11886. return false;
  11887. }
  11888. }
  11889. /**
  11890. * Parse C99's asctime()'s date format
  11891. *
  11892. * @access protected
  11893. * @return int Timestamp
  11894. */
  11895. public function date_asctime($date)
  11896. {
  11897. static $pcre;
  11898. if (!$pcre)
  11899. {
  11900. $space = '[\x09\x20]+';
  11901. $wday_name = $this->day_pcre;
  11902. $mon_name = $this->month_pcre;
  11903. $day = '([0-9]{1,2})';
  11904. $hour = $sec = $min = '([0-9]{2})';
  11905. $year = '([0-9]{4})';
  11906. $terminator = '\x0A?\x00?';
  11907. $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  11908. }
  11909. if (preg_match($pcre, $date, $match))
  11910. {
  11911. /*
  11912. Capturing subpatterns:
  11913. 1: Day name
  11914. 2: Month
  11915. 3: Day
  11916. 4: Hour
  11917. 5: Minute
  11918. 6: Second
  11919. 7: Year
  11920. */
  11921. $month = $this->month[strtolower($match[2])];
  11922. return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  11923. }
  11924. else
  11925. {
  11926. return false;
  11927. }
  11928. }
  11929. /**
  11930. * Parse dates using strtotime()
  11931. *
  11932. * @access protected
  11933. * @return int Timestamp
  11934. */
  11935. public function date_strtotime($date)
  11936. {
  11937. $strtotime = strtotime($date);
  11938. if ($strtotime === -1 || $strtotime === false)
  11939. {
  11940. return false;
  11941. }
  11942. else
  11943. {
  11944. return $strtotime;
  11945. }
  11946. }
  11947. }
  11948. /**
  11949. * Content-type sniffing
  11950. *
  11951. * @package SimplePie
  11952. */
  11953. class SimplePie_Content_Type_Sniffer
  11954. {
  11955. /**
  11956. * File object
  11957. *
  11958. * @var SimplePie_File
  11959. * @access private
  11960. */
  11961. var $file;
  11962. /**
  11963. * Create an instance of the class with the input file
  11964. *
  11965. * @access public
  11966. * @param SimplePie_Content_Type_Sniffer $file Input file
  11967. */
  11968. public function __construct($file)
  11969. {
  11970. $this->file = $file;
  11971. }
  11972. /**
  11973. * Get the Content-Type of the specified file
  11974. *
  11975. * @access public
  11976. * @return string Actual Content-Type
  11977. */
  11978. public function get_type()
  11979. {
  11980. if (isset($this->file->headers['content-type']))
  11981. {
  11982. if (!isset($this->file->headers['content-encoding'])
  11983. && ($this->file->headers['content-type'] === 'text/plain'
  11984. || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
  11985. || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
  11986. {
  11987. return $this->text_or_binary();
  11988. }
  11989. if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
  11990. {
  11991. $official = substr($this->file->headers['content-type'], 0, $pos);
  11992. }
  11993. else
  11994. {
  11995. $official = $this->file->headers['content-type'];
  11996. }
  11997. $official = strtolower($official);
  11998. if ($official === 'unknown/unknown'
  11999. || $official === 'application/unknown')
  12000. {
  12001. return $this->unknown();
  12002. }
  12003. elseif (substr($official, -4) === '+xml'
  12004. || $official === 'text/xml'
  12005. || $official === 'application/xml')
  12006. {
  12007. return $official;
  12008. }
  12009. elseif (substr($official, 0, 6) === 'image/')
  12010. {
  12011. if ($return = $this->image())
  12012. {
  12013. return $return;
  12014. }
  12015. else
  12016. {
  12017. return $official;
  12018. }
  12019. }
  12020. elseif ($official === 'text/html')
  12021. {
  12022. return $this->feed_or_html();
  12023. }
  12024. else
  12025. {
  12026. return $official;
  12027. }
  12028. }
  12029. else
  12030. {
  12031. return $this->unknown();
  12032. }
  12033. }
  12034. /**
  12035. * Sniff text or binary
  12036. *
  12037. * @access private
  12038. * @return string Actual Content-Type
  12039. */
  12040. public function text_or_binary()
  12041. {
  12042. if (substr($this->file->body, 0, 2) === "\xFE\xFF"
  12043. || substr($this->file->body, 0, 2) === "\xFF\xFE"
  12044. || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
  12045. || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
  12046. {
  12047. return 'text/plain';
  12048. }
  12049. elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
  12050. {
  12051. return 'application/octect-stream';
  12052. }
  12053. else
  12054. {
  12055. return 'text/plain';
  12056. }
  12057. }
  12058. /**
  12059. * Sniff unknown
  12060. *
  12061. * @access private
  12062. * @return string Actual Content-Type
  12063. */
  12064. public function unknown()
  12065. {
  12066. $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
  12067. if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
  12068. || strtolower(substr($this->file->body, $ws, 5)) === '<html'
  12069. || strtolower(substr($this->file->body, $ws, 7)) === '<script')
  12070. {
  12071. return 'text/html';
  12072. }
  12073. elseif (substr($this->file->body, 0, 5) === '%PDF-')
  12074. {
  12075. return 'application/pdf';
  12076. }
  12077. elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
  12078. {
  12079. return 'application/postscript';
  12080. }
  12081. elseif (substr($this->file->body, 0, 6) === 'GIF87a'
  12082. || substr($this->file->body, 0, 6) === 'GIF89a')
  12083. {
  12084. return 'image/gif';
  12085. }
  12086. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  12087. {
  12088. return 'image/png';
  12089. }
  12090. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  12091. {
  12092. return 'image/jpeg';
  12093. }
  12094. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  12095. {
  12096. return 'image/bmp';
  12097. }
  12098. else
  12099. {
  12100. return $this->text_or_binary();
  12101. }
  12102. }
  12103. /**
  12104. * Sniff images
  12105. *
  12106. * @access private
  12107. * @return string Actual Content-Type
  12108. */
  12109. public function image()
  12110. {
  12111. if (substr($this->file->body, 0, 6) === 'GIF87a'
  12112. || substr($this->file->body, 0, 6) === 'GIF89a')
  12113. {
  12114. return 'image/gif';
  12115. }
  12116. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  12117. {
  12118. return 'image/png';
  12119. }
  12120. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  12121. {
  12122. return 'image/jpeg';
  12123. }
  12124. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  12125. {
  12126. return 'image/bmp';
  12127. }
  12128. else
  12129. {
  12130. return false;
  12131. }
  12132. }
  12133. /**
  12134. * Sniff HTML
  12135. *
  12136. * @access private
  12137. * @return string Actual Content-Type
  12138. */
  12139. public function feed_or_html()
  12140. {
  12141. $len = strlen($this->file->body);
  12142. $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
  12143. while ($pos < $len)
  12144. {
  12145. switch ($this->file->body[$pos])
  12146. {
  12147. case "\x09":
  12148. case "\x0A":
  12149. case "\x0D":
  12150. case "\x20":
  12151. $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
  12152. continue 2;
  12153. case '<':
  12154. $pos++;
  12155. break;
  12156. default:
  12157. return 'text/html';
  12158. }
  12159. if (substr($this->file->body, $pos, 3) === '!--')
  12160. {
  12161. $pos += 3;
  12162. if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
  12163. {
  12164. $pos += 3;
  12165. }
  12166. else
  12167. {
  12168. return 'text/html';
  12169. }
  12170. }
  12171. elseif (substr($this->file->body, $pos, 1) === '!')
  12172. {
  12173. if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
  12174. {
  12175. $pos++;
  12176. }
  12177. else
  12178. {
  12179. return 'text/html';
  12180. }
  12181. }
  12182. elseif (substr($this->file->body, $pos, 1) === '?')
  12183. {
  12184. if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
  12185. {
  12186. $pos += 2;
  12187. }
  12188. else
  12189. {
  12190. return 'text/html';
  12191. }
  12192. }
  12193. elseif (substr($this->file->body, $pos, 3) === 'rss'
  12194. || substr($this->file->body, $pos, 7) === 'rdf:RDF')
  12195. {
  12196. return 'application/rss+xml';
  12197. }
  12198. elseif (substr($this->file->body, $pos, 4) === 'feed')
  12199. {
  12200. return 'application/atom+xml';
  12201. }
  12202. else
  12203. {
  12204. return 'text/html';
  12205. }
  12206. }
  12207. return 'text/html';
  12208. }
  12209. }
  12210. /**
  12211. * Parses the XML Declaration
  12212. *
  12213. * @package SimplePie
  12214. */
  12215. class SimplePie_XML_Declaration_Parser
  12216. {
  12217. /**
  12218. * XML Version
  12219. *
  12220. * @access public
  12221. * @var string
  12222. */
  12223. var $version = '1.0';
  12224. /**
  12225. * Encoding
  12226. *
  12227. * @access public
  12228. * @var string
  12229. */
  12230. var $encoding = 'UTF-8';
  12231. /**
  12232. * Standalone
  12233. *
  12234. * @access public
  12235. * @var bool
  12236. */
  12237. var $standalone = false;
  12238. /**
  12239. * Current state of the state machine
  12240. *
  12241. * @access private
  12242. * @var string
  12243. */
  12244. var $state = 'before_version_name';
  12245. /**
  12246. * Input data
  12247. *
  12248. * @access private
  12249. * @var string
  12250. */
  12251. var $data = '';
  12252. /**
  12253. * Input data length (to avoid calling strlen() everytime this is needed)
  12254. *
  12255. * @access private
  12256. * @var int
  12257. */
  12258. var $data_length = 0;
  12259. /**
  12260. * Current position of the pointer
  12261. *
  12262. * @var int
  12263. * @access private
  12264. */
  12265. var $position = 0;
  12266. /**
  12267. * Create an instance of the class with the input data
  12268. *
  12269. * @access public
  12270. * @param string $data Input data
  12271. */
  12272. public function __construct($data)
  12273. {
  12274. $this->data = $data;
  12275. $this->data_length = strlen($this->data);
  12276. }
  12277. /**
  12278. * Parse the input data
  12279. *
  12280. * @access public
  12281. * @return bool true on success, false on failure
  12282. */
  12283. public function parse()
  12284. {
  12285. while ($this->state && $this->state !== 'emit' && $this->has_data())
  12286. {
  12287. $state = $this->state;
  12288. $this->$state();
  12289. }
  12290. $this->data = '';
  12291. if ($this->state === 'emit')
  12292. {
  12293. return true;
  12294. }
  12295. else
  12296. {
  12297. $this->version = '';
  12298. $this->encoding = '';
  12299. $this->standalone = '';
  12300. return false;
  12301. }
  12302. }
  12303. /**
  12304. * Check whether there is data beyond the pointer
  12305. *
  12306. * @access private
  12307. * @return bool true if there is further data, false if not
  12308. */
  12309. public function has_data()
  12310. {
  12311. return (bool) ($this->position < $this->data_length);
  12312. }
  12313. /**
  12314. * Advance past any whitespace
  12315. *
  12316. * @return int Number of whitespace characters passed
  12317. */
  12318. public function skip_whitespace()
  12319. {
  12320. $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
  12321. $this->position += $whitespace;
  12322. return $whitespace;
  12323. }
  12324. /**
  12325. * Read value
  12326. */
  12327. public function get_value()
  12328. {
  12329. $quote = substr($this->data, $this->position, 1);
  12330. if ($quote === '"' || $quote === "'")
  12331. {
  12332. $this->position++;
  12333. $len = strcspn($this->data, $quote, $this->position);
  12334. if ($this->has_data())
  12335. {
  12336. $value = substr($this->data, $this->position, $len);
  12337. $this->position += $len + 1;
  12338. return $value;
  12339. }
  12340. }
  12341. return false;
  12342. }
  12343. public function before_version_name()
  12344. {
  12345. if ($this->skip_whitespace())
  12346. {
  12347. $this->state = 'version_name';
  12348. }
  12349. else
  12350. {
  12351. $this->state = false;
  12352. }
  12353. }
  12354. public function version_name()
  12355. {
  12356. if (substr($this->data, $this->position, 7) === 'version')
  12357. {
  12358. $this->position += 7;
  12359. $this->skip_whitespace();
  12360. $this->state = 'version_equals';
  12361. }
  12362. else
  12363. {
  12364. $this->state = false;
  12365. }
  12366. }
  12367. public function version_equals()
  12368. {
  12369. if (substr($this->data, $this->position, 1) === '=')
  12370. {
  12371. $this->position++;
  12372. $this->skip_whitespace();
  12373. $this->state = 'version_value';
  12374. }
  12375. else
  12376. {
  12377. $this->state = false;
  12378. }
  12379. }
  12380. public function version_value()
  12381. {
  12382. if ($this->version = $this->get_value())
  12383. {
  12384. $this->skip_whitespace();
  12385. if ($this->has_data())
  12386. {
  12387. $this->state = 'encoding_name';
  12388. }
  12389. else
  12390. {
  12391. $this->state = 'emit';
  12392. }
  12393. }
  12394. else
  12395. {
  12396. $this->state = false;
  12397. }
  12398. }
  12399. public function encoding_name()
  12400. {
  12401. if (substr($this->data, $this->position, 8) === 'encoding')
  12402. {
  12403. $this->position += 8;
  12404. $this->skip_whitespace();
  12405. $this->state = 'encoding_equals';
  12406. }
  12407. else
  12408. {
  12409. $this->state = 'standalone_name';
  12410. }
  12411. }
  12412. public function encoding_equals()
  12413. {
  12414. if (substr($this->data, $this->position, 1) === '=')
  12415. {
  12416. $this->position++;
  12417. $this->skip_whitespace();
  12418. $this->state = 'encoding_value';
  12419. }
  12420. else
  12421. {
  12422. $this->state = false;
  12423. }
  12424. }
  12425. public function encoding_value()
  12426. {
  12427. if ($this->encoding = $this->get_value())
  12428. {
  12429. $this->skip_whitespace();
  12430. if ($this->has_data())
  12431. {
  12432. $this->state = 'standalone_name';
  12433. }
  12434. else
  12435. {
  12436. $this->state = 'emit';
  12437. }
  12438. }
  12439. else
  12440. {
  12441. $this->state = false;
  12442. }
  12443. }
  12444. public function standalone_name()
  12445. {
  12446. if (substr($this->data, $this->position, 10) === 'standalone')
  12447. {
  12448. $this->position += 10;
  12449. $this->skip_whitespace();
  12450. $this->state = 'standalone_equals';
  12451. }
  12452. else
  12453. {
  12454. $this->state = false;
  12455. }
  12456. }
  12457. public function standalone_equals()
  12458. {
  12459. if (substr($this->data, $this->position, 1) === '=')
  12460. {
  12461. $this->position++;
  12462. $this->skip_whitespace();
  12463. $this->state = 'standalone_value';
  12464. }
  12465. else
  12466. {
  12467. $this->state = false;
  12468. }
  12469. }
  12470. public function standalone_value()
  12471. {
  12472. if ($standalone = $this->get_value())
  12473. {
  12474. switch ($standalone)
  12475. {
  12476. case 'yes':
  12477. $this->standalone = true;
  12478. break;
  12479. case 'no':
  12480. $this->standalone = false;
  12481. break;
  12482. default:
  12483. $this->state = false;
  12484. return;
  12485. }
  12486. $this->skip_whitespace();
  12487. if ($this->has_data())
  12488. {
  12489. $this->state = false;
  12490. }
  12491. else
  12492. {
  12493. $this->state = 'emit';
  12494. }
  12495. }
  12496. else
  12497. {
  12498. $this->state = false;
  12499. }
  12500. }
  12501. }
  12502. class SimplePie_Locator
  12503. {
  12504. var $useragent;
  12505. var $timeout;
  12506. var $file;
  12507. var $local = array();
  12508. var $elsewhere = array();
  12509. var $file_class = 'SimplePie_File';
  12510. var $cached_entities = array();
  12511. var $http_base;
  12512. var $base;
  12513. var $base_location = 0;
  12514. var $checked_feeds = 0;
  12515. var $max_checked_feeds = 10;
  12516. var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  12517. public function __construct(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
  12518. {
  12519. $this->file =& $file;
  12520. $this->file_class = $file_class;
  12521. $this->useragent = $useragent;
  12522. $this->timeout = $timeout;
  12523. $this->max_checked_feeds = $max_checked_feeds;
  12524. $this->content_type_sniffer_class = $content_type_sniffer_class;
  12525. }
  12526. public function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
  12527. {
  12528. if ($this->is_feed($this->file))
  12529. {
  12530. return $this->file;
  12531. }
  12532. if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  12533. {
  12534. $sniffer = new $this->content_type_sniffer_class($this->file);
  12535. if ($sniffer->get_type() !== 'text/html')
  12536. {
  12537. return null;
  12538. }
  12539. }
  12540. if ($type & ~SIMPLEPIE_LOCATOR_NONE)
  12541. {
  12542. $this->get_base();
  12543. }
  12544. if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
  12545. {
  12546. return $working[0];
  12547. }
  12548. if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
  12549. {
  12550. if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
  12551. {
  12552. return $working;
  12553. }
  12554. if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
  12555. {
  12556. return $working;
  12557. }
  12558. if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
  12559. {
  12560. return $working;
  12561. }
  12562. if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
  12563. {
  12564. return $working;
  12565. }
  12566. }
  12567. return null;
  12568. }
  12569. public function is_feed(&$file)
  12570. {
  12571. if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  12572. {
  12573. $sniffer = new $this->content_type_sniffer_class($file);
  12574. $sniffed = $sniffer->get_type();
  12575. if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
  12576. {
  12577. return true;
  12578. }
  12579. else
  12580. {
  12581. return false;
  12582. }
  12583. }
  12584. elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
  12585. {
  12586. return true;
  12587. }
  12588. else
  12589. {
  12590. return false;
  12591. }
  12592. }
  12593. public function get_base()
  12594. {
  12595. $this->http_base = $this->file->url;
  12596. $this->base = $this->http_base;
  12597. $elements = SimplePie_Misc::get_element('base', $this->file->body);
  12598. foreach ($elements as $element)
  12599. {
  12600. if ($element['attribs']['href']['data'] !== '')
  12601. {
  12602. $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
  12603. $this->base_location = $element['offset'];
  12604. break;
  12605. }
  12606. }
  12607. }
  12608. public function autodiscovery()
  12609. {
  12610. $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));
  12611. $done = array();
  12612. $feeds = array();
  12613. foreach ($links as $link)
  12614. {
  12615. if ($this->checked_feeds === $this->max_checked_feeds)
  12616. {
  12617. break;
  12618. }
  12619. if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
  12620. {
  12621. $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
  12622. if ($this->base_location < $link['offset'])
  12623. {
  12624. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  12625. }
  12626. else
  12627. {
  12628. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  12629. }
  12630. if (!in_array($href, $done) && in_array('feed', $rel) || (in_array('alternate', $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]))
  12631. {
  12632. $this->checked_feeds++;
  12633. $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
  12634. 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))
  12635. {
  12636. $feeds[$href] = $feed;
  12637. }
  12638. }
  12639. $done[] = $href;
  12640. }
  12641. }
  12642. if (!empty($feeds))
  12643. {
  12644. return array_values($feeds);
  12645. }
  12646. else {
  12647. return null;
  12648. }
  12649. }
  12650. public function get_links()
  12651. {
  12652. $links = SimplePie_Misc::get_element('a', $this->file->body);
  12653. foreach ($links as $link)
  12654. {
  12655. if (isset($link['attribs']['href']['data']))
  12656. {
  12657. $href = trim($link['attribs']['href']['data']);
  12658. $parsed = SimplePie_Misc::parse_url($href);
  12659. if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
  12660. {
  12661. if ($this->base_location < $link['offset'])
  12662. {
  12663. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  12664. }
  12665. else
  12666. {
  12667. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  12668. }
  12669. $current = SimplePie_Misc::parse_url($this->file->url);
  12670. if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
  12671. {
  12672. $this->local[] = $href;
  12673. }
  12674. else
  12675. {
  12676. $this->elsewhere[] = $href;
  12677. }
  12678. }
  12679. }
  12680. }
  12681. $this->local = array_unique($this->local);
  12682. $this->elsewhere = array_unique($this->elsewhere);
  12683. if (!empty($this->local) || !empty($this->elsewhere))
  12684. {
  12685. return true;
  12686. }
  12687. return null;
  12688. }
  12689. public function extension(&$array)
  12690. {
  12691. foreach ($array as $key => $value)
  12692. {
  12693. if ($this->checked_feeds === $this->max_checked_feeds)
  12694. {
  12695. break;
  12696. }
  12697. if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
  12698. {
  12699. $this->checked_feeds++;
  12700. $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
  12701. 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))
  12702. {
  12703. return $feed;
  12704. }
  12705. else
  12706. {
  12707. unset($array[$key]);
  12708. }
  12709. }
  12710. }
  12711. return null;
  12712. }
  12713. public function body(&$array)
  12714. {
  12715. foreach ($array as $key => $value)
  12716. {
  12717. if ($this->checked_feeds === $this->max_checked_feeds)
  12718. {
  12719. break;
  12720. }
  12721. if (preg_match('/(rss|rdf|atom|xml)/i', $value))
  12722. {
  12723. $this->checked_feeds++;
  12724. $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
  12725. 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))
  12726. {
  12727. return $feed;
  12728. }
  12729. else
  12730. {
  12731. unset($array[$key]);
  12732. }
  12733. }
  12734. }
  12735. return null;
  12736. }
  12737. }
  12738. class SimplePie_Parser
  12739. {
  12740. var $error_code;
  12741. var $error_string;
  12742. var $current_line;
  12743. var $current_column;
  12744. var $current_byte;
  12745. var $separator = ' ';
  12746. var $namespace = array('');
  12747. var $element = array('');
  12748. var $xml_base = array('');
  12749. var $xml_base_explicit = array(false);
  12750. var $xml_lang = array('');
  12751. var $data = array();
  12752. var $datas = array(array());
  12753. var $current_xhtml_construct = -1;
  12754. var $encoding;
  12755. public function parse(&$data, $encoding)
  12756. {
  12757. // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
  12758. if (strtoupper($encoding) === 'US-ASCII')
  12759. {
  12760. $this->encoding = 'UTF-8';
  12761. }
  12762. else
  12763. {
  12764. $this->encoding = $encoding;
  12765. }
  12766. // Strip BOM:
  12767. // UTF-32 Big Endian BOM
  12768. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  12769. {
  12770. $data = substr($data, 4);
  12771. }
  12772. // UTF-32 Little Endian BOM
  12773. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  12774. {
  12775. $data = substr($data, 4);
  12776. }
  12777. // UTF-16 Big Endian BOM
  12778. elseif (substr($data, 0, 2) === "\xFE\xFF")
  12779. {
  12780. $data = substr($data, 2);
  12781. }
  12782. // UTF-16 Little Endian BOM
  12783. elseif (substr($data, 0, 2) === "\xFF\xFE")
  12784. {
  12785. $data = substr($data, 2);
  12786. }
  12787. // UTF-8 BOM
  12788. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  12789. {
  12790. $data = substr($data, 3);
  12791. }
  12792. if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
  12793. {
  12794. $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  12795. if ($declaration->parse())
  12796. {
  12797. $data = substr($data, $pos + 2);
  12798. $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
  12799. }
  12800. else
  12801. {
  12802. $this->error_string = 'SimplePie bug! Please report this!';
  12803. return false;
  12804. }
  12805. }
  12806. $return = true;
  12807. static $xml_is_sane = null;
  12808. if ($xml_is_sane === null)
  12809. {
  12810. $parser_check = xml_parser_create();
  12811. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  12812. xml_parser_free($parser_check);
  12813. $xml_is_sane = isset($values[0]['value']);
  12814. }
  12815. // Create the parser
  12816. if ($xml_is_sane)
  12817. {
  12818. $xml = xml_parser_create_ns($this->encoding, $this->separator);
  12819. xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
  12820. xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
  12821. xml_set_object($xml, $this);
  12822. xml_set_character_data_handler($xml, 'cdata');
  12823. xml_set_element_handler($xml, 'tag_open', 'tag_close');
  12824. // Parse!
  12825. if (!xml_parse($xml, $data, true))
  12826. {
  12827. $this->error_code = xml_get_error_code($xml);
  12828. $this->error_string = xml_error_string($this->error_code);
  12829. $return = false;
  12830. }
  12831. $this->current_line = xml_get_current_line_number($xml);
  12832. $this->current_column = xml_get_current_column_number($xml);
  12833. $this->current_byte = xml_get_current_byte_index($xml);
  12834. xml_parser_free($xml);
  12835. return $return;
  12836. }
  12837. else
  12838. {
  12839. libxml_clear_errors();
  12840. $xml = new XMLReader();
  12841. $xml->xml($data);
  12842. while (@$xml->read())
  12843. {
  12844. switch ($xml->nodeType)
  12845. {
  12846. case constant('XMLReader::END_ELEMENT'):
  12847. if ($xml->namespaceURI !== '')
  12848. {
  12849. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  12850. }
  12851. else
  12852. {
  12853. $tagName = $xml->localName;
  12854. }
  12855. $this->tag_close(null, $tagName);
  12856. break;
  12857. case constant('XMLReader::ELEMENT'):
  12858. $empty = $xml->isEmptyElement;
  12859. if ($xml->namespaceURI !== '')
  12860. {
  12861. $tagName = $xml->namespaceURI . $this->separator . $xml->localName;
  12862. }
  12863. else
  12864. {
  12865. $tagName = $xml->localName;
  12866. }
  12867. $attributes = array();
  12868. while ($xml->moveToNextAttribute())
  12869. {
  12870. if ($xml->namespaceURI !== '')
  12871. {
  12872. $attrName = $xml->namespaceURI . $this->separator . $xml->localName;
  12873. }
  12874. else
  12875. {
  12876. $attrName = $xml->localName;
  12877. }
  12878. $attributes[$attrName] = $xml->value;
  12879. }
  12880. $this->tag_open(null, $tagName, $attributes);
  12881. if ($empty)
  12882. {
  12883. $this->tag_close(null, $tagName);
  12884. }
  12885. break;
  12886. case constant('XMLReader::TEXT'):
  12887. case constant('XMLReader::CDATA'):
  12888. $this->cdata(null, $xml->value);
  12889. break;
  12890. }
  12891. }
  12892. if ($error = libxml_get_last_error())
  12893. {
  12894. $this->error_code = $error->code;
  12895. $this->error_string = $error->message;
  12896. $this->current_line = $error->line;
  12897. $this->current_column = $error->column;
  12898. return false;
  12899. }
  12900. else
  12901. {
  12902. return true;
  12903. }
  12904. }
  12905. }
  12906. public function get_error_code()
  12907. {
  12908. return $this->error_code;
  12909. }
  12910. public function get_error_string()
  12911. {
  12912. return $this->error_string;
  12913. }
  12914. public function get_current_line()
  12915. {
  12916. return $this->current_line;
  12917. }
  12918. public function get_current_column()
  12919. {
  12920. return $this->current_column;
  12921. }
  12922. public function get_current_byte()
  12923. {
  12924. return $this->current_byte;
  12925. }
  12926. public function get_data()
  12927. {
  12928. return $this->data;
  12929. }
  12930. public function tag_open($parser, $tag, $attributes)
  12931. {
  12932. list($this->namespace[], $this->element[]) = $this->split_ns($tag);
  12933. $attribs = array();
  12934. foreach ($attributes as $name => $value)
  12935. {
  12936. list($attrib_namespace, $attribute) = $this->split_ns($name);
  12937. $attribs[$attrib_namespace][$attribute] = $value;
  12938. }
  12939. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
  12940. {
  12941. $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
  12942. $this->xml_base_explicit[] = true;
  12943. }
  12944. else
  12945. {
  12946. $this->xml_base[] = end($this->xml_base);
  12947. $this->xml_base_explicit[] = end($this->xml_base_explicit);
  12948. }
  12949. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
  12950. {
  12951. $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
  12952. }
  12953. else
  12954. {
  12955. $this->xml_lang[] = end($this->xml_lang);
  12956. }
  12957. if ($this->current_xhtml_construct >= 0)
  12958. {
  12959. $this->current_xhtml_construct++;
  12960. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
  12961. {
  12962. $this->data['data'] .= '<' . end($this->element);
  12963. if (isset($attribs['']))
  12964. {
  12965. foreach ($attribs[''] as $name => $value)
  12966. {
  12967. $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
  12968. }
  12969. }
  12970. $this->data['data'] .= '>';
  12971. }
  12972. }
  12973. else
  12974. {
  12975. $this->datas[] =& $this->data;
  12976. $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
  12977. $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));
  12978. 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')
  12979. || (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'))
  12980. {
  12981. $this->current_xhtml_construct = 0;
  12982. }
  12983. }
  12984. }
  12985. public function cdata($parser, $cdata)
  12986. {
  12987. if ($this->current_xhtml_construct >= 0)
  12988. {
  12989. $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
  12990. }
  12991. else
  12992. {
  12993. $this->data['data'] .= $cdata;
  12994. }
  12995. }
  12996. public function tag_close($parser, $tag)
  12997. {
  12998. if ($this->current_xhtml_construct >= 0)
  12999. {
  13000. $this->current_xhtml_construct--;
  13001. 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')))
  13002. {
  13003. $this->data['data'] .= '</' . end($this->element) . '>';
  13004. }
  13005. }
  13006. if ($this->current_xhtml_construct === -1)
  13007. {
  13008. $this->data =& $this->datas[count($this->datas) - 1];
  13009. array_pop($this->datas);
  13010. }
  13011. array_pop($this->element);
  13012. array_pop($this->namespace);
  13013. array_pop($this->xml_base);
  13014. array_pop($this->xml_base_explicit);
  13015. array_pop($this->xml_lang);
  13016. }
  13017. public function split_ns($string)
  13018. {
  13019. static $cache = array();
  13020. if (!isset($cache[$string]))
  13021. {
  13022. if ($pos = strpos($string, $this->separator))
  13023. {
  13024. static $separator_length;
  13025. if (!$separator_length)
  13026. {
  13027. $separator_length = strlen($this->separator);
  13028. }
  13029. $namespace = substr($string, 0, $pos);
  13030. $local_name = substr($string, $pos + $separator_length);
  13031. if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
  13032. {
  13033. $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
  13034. }
  13035. // Normalize the Media RSS namespaces
  13036. if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG ||
  13037. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG2 ||
  13038. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG3 ||
  13039. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG4 ||
  13040. $namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG5 )
  13041. {
  13042. $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
  13043. }
  13044. $cache[$string] = array($namespace, $local_name);
  13045. }
  13046. else
  13047. {
  13048. $cache[$string] = array('', $string);
  13049. }
  13050. }
  13051. return $cache[$string];
  13052. }
  13053. }
  13054. /**
  13055. * @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
  13056. */
  13057. class SimplePie_Sanitize
  13058. {
  13059. // Private vars
  13060. var $base;
  13061. // Options
  13062. var $remove_div = true;
  13063. var $image_handler = '';
  13064. var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  13065. var $encode_instead_of_strip = false;
  13066. var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  13067. var $strip_comments = false;
  13068. var $output_encoding = 'UTF-8';
  13069. var $enable_cache = true;
  13070. var $cache_location = './cache';
  13071. var $cache_name_function = 'md5';
  13072. var $cache_class = 'SimplePie_Cache';
  13073. var $file_class = 'SimplePie_File';
  13074. var $timeout = 10;
  13075. var $useragent = '';
  13076. var $force_fsockopen = false;
  13077. var $replace_url_attributes = array(
  13078. 'a' => 'href',
  13079. 'area' => 'href',
  13080. 'blockquote' => 'cite',
  13081. 'del' => 'cite',
  13082. 'form' => 'action',
  13083. 'img' => array('longdesc', 'src'),
  13084. 'input' => 'src',
  13085. 'ins' => 'cite',
  13086. 'q' => 'cite'
  13087. );
  13088. public function remove_div($enable = true)
  13089. {
  13090. $this->remove_div = (bool) $enable;
  13091. }
  13092. public function set_image_handler($page = false)
  13093. {
  13094. if ($page)
  13095. {
  13096. $this->image_handler = (string) $page;
  13097. }
  13098. else
  13099. {
  13100. $this->image_handler = false;
  13101. }
  13102. }
  13103. public function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
  13104. {
  13105. if (isset($enable_cache))
  13106. {
  13107. $this->enable_cache = (bool) $enable_cache;
  13108. }
  13109. if ($cache_location)
  13110. {
  13111. $this->cache_location = (string) $cache_location;
  13112. }
  13113. if ($cache_name_function)
  13114. {
  13115. $this->cache_name_function = (string) $cache_name_function;
  13116. }
  13117. if ($cache_class)
  13118. {
  13119. $this->cache_class = (string) $cache_class;
  13120. }
  13121. }
  13122. public function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
  13123. {
  13124. if ($file_class)
  13125. {
  13126. $this->file_class = (string) $file_class;
  13127. }
  13128. if ($timeout)
  13129. {
  13130. $this->timeout = (string) $timeout;
  13131. }
  13132. if ($useragent)
  13133. {
  13134. $this->useragent = (string) $useragent;
  13135. }
  13136. if ($force_fsockopen)
  13137. {
  13138. $this->force_fsockopen = (string) $force_fsockopen;
  13139. }
  13140. }
  13141. 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'))
  13142. {
  13143. if ($tags)
  13144. {
  13145. if (is_array($tags))
  13146. {
  13147. $this->strip_htmltags = $tags;
  13148. }
  13149. else
  13150. {
  13151. $this->strip_htmltags = explode(',', $tags);
  13152. }
  13153. }
  13154. else
  13155. {
  13156. $this->strip_htmltags = false;
  13157. }
  13158. }
  13159. public function encode_instead_of_strip($encode = false)
  13160. {
  13161. $this->encode_instead_of_strip = (bool) $encode;
  13162. }
  13163. public function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
  13164. {
  13165. if ($attribs)
  13166. {
  13167. if (is_array($attribs))
  13168. {
  13169. $this->strip_attributes = $attribs;
  13170. }
  13171. else
  13172. {
  13173. $this->strip_attributes = explode(',', $attribs);
  13174. }
  13175. }
  13176. else
  13177. {
  13178. $this->strip_attributes = false;
  13179. }
  13180. }
  13181. public function strip_comments($strip = false)
  13182. {
  13183. $this->strip_comments = (bool) $strip;
  13184. }
  13185. public function set_output_encoding($encoding = 'UTF-8')
  13186. {
  13187. $this->output_encoding = (string) $encoding;
  13188. }
  13189. /**
  13190. * Set element/attribute key/value pairs of HTML attributes
  13191. * containing URLs that need to be resolved relative to the feed
  13192. *
  13193. * @access public
  13194. * @since 1.0
  13195. * @param array $element_attribute Element/attribute key/value pairs
  13196. */
  13197. 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'))
  13198. {
  13199. $this->replace_url_attributes = (array) $element_attribute;
  13200. }
  13201. public function sanitize($data, $type, $base = '')
  13202. {
  13203. $data = trim($data);
  13204. if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
  13205. {
  13206. if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
  13207. {
  13208. 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))
  13209. {
  13210. $type |= SIMPLEPIE_CONSTRUCT_HTML;
  13211. }
  13212. else
  13213. {
  13214. $type |= SIMPLEPIE_CONSTRUCT_TEXT;
  13215. }
  13216. }
  13217. if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
  13218. {
  13219. $data = base64_decode($data);
  13220. }
  13221. if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
  13222. {
  13223. if ($this->remove_div)
  13224. {
  13225. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
  13226. $data = preg_replace('/<\/div>$/', '', $data);
  13227. }
  13228. else
  13229. {
  13230. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
  13231. }
  13232. }
  13233. if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
  13234. {
  13235. // Strip comments
  13236. if ($this->strip_comments)
  13237. {
  13238. $data = SimplePie_Misc::strip_comments($data);
  13239. }
  13240. // Strip out HTML tags and attributes that might cause various security problems.
  13241. // Based on recommendations by Mark Pilgrim at:
  13242. // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
  13243. if ($this->strip_htmltags)
  13244. {
  13245. foreach ($this->strip_htmltags as $tag)
  13246. {
  13247. $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
  13248. while (preg_match($pcre, $data))
  13249. {
  13250. $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
  13251. }
  13252. }
  13253. }
  13254. if ($this->strip_attributes)
  13255. {
  13256. foreach ($this->strip_attributes as $attrib)
  13257. {
  13258. $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);
  13259. }
  13260. }
  13261. // Replace relative URLs
  13262. $this->base = $base;
  13263. foreach ($this->replace_url_attributes as $element => $attributes)
  13264. {
  13265. $data = $this->replace_urls($data, $element, $attributes);
  13266. }
  13267. // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
  13268. if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
  13269. {
  13270. $images = SimplePie_Misc::get_element('img', $data);
  13271. foreach ($images as $img)
  13272. {
  13273. if (isset($img['attribs']['src']['data']))
  13274. {
  13275. $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
  13276. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
  13277. if ($cache->load())
  13278. {
  13279. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  13280. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  13281. }
  13282. else
  13283. {
  13284. $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
  13285. $headers = $file->headers;
  13286. if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  13287. {
  13288. if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
  13289. {
  13290. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  13291. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  13292. }
  13293. else
  13294. {
  13295. 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);
  13296. }
  13297. }
  13298. }
  13299. }
  13300. }
  13301. }
  13302. // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
  13303. $data = trim($data);
  13304. }
  13305. if ($type & SIMPLEPIE_CONSTRUCT_IRI)
  13306. {
  13307. $data = SimplePie_Misc::absolutize_url($data, $base);
  13308. }
  13309. if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
  13310. {
  13311. $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
  13312. }
  13313. if ($this->output_encoding !== 'UTF-8')
  13314. {
  13315. $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
  13316. }
  13317. }
  13318. return $data;
  13319. }
  13320. public function replace_urls($data, $tag, $attributes)
  13321. {
  13322. if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
  13323. {
  13324. $elements = SimplePie_Misc::get_element($tag, $data);
  13325. foreach ($elements as $element)
  13326. {
  13327. if (is_array($attributes))
  13328. {
  13329. foreach ($attributes as $attribute)
  13330. {
  13331. if (isset($element['attribs'][$attribute]['data']))
  13332. {
  13333. $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
  13334. $new_element = SimplePie_Misc::element_implode($element);
  13335. $data = str_replace($element['full'], $new_element, $data);
  13336. $element['full'] = $new_element;
  13337. }
  13338. }
  13339. }
  13340. elseif (isset($element['attribs'][$attributes]['data']))
  13341. {
  13342. $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
  13343. $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
  13344. }
  13345. }
  13346. }
  13347. return $data;
  13348. }
  13349. public function do_strip_htmltags($match)
  13350. {
  13351. if ($this->encode_instead_of_strip)
  13352. {
  13353. if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13354. {
  13355. $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
  13356. $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
  13357. return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
  13358. }
  13359. else
  13360. {
  13361. return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
  13362. }
  13363. }
  13364. elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13365. {
  13366. return $match[4];
  13367. }
  13368. else
  13369. {
  13370. return '';
  13371. }
  13372. }
  13373. }