PageRenderTime 66ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 2ms

/libraries/simplepie/simplepie.php

https://bitbucket.org/biojazzard/joomla-eboracast
PHP | 15007 lines | 11793 code | 1089 blank | 2125 comment | 1153 complexity | 49b81064bcec2659085fdcee46215a23 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-2.0, MIT, BSD-3-Clause
  1. <?php
  2. /**
  3. * This file will be removed in Joomla! CMS version 3.2. Developers should either supply their own copy
  4. * in their installation packages or switch to JFeed.
  5. */
  6. /**
  7. * SimplePie
  8. *
  9. * A PHP-Based RSS and Atom Feed Framework.
  10. * Takes the hard work out of managing a complete RSS/Atom solution.
  11. *
  12. * Copyright (c) 2004-2009, Ryan Parman and Geoffrey Sneddon
  13. * All rights reserved.
  14. *
  15. * Redistribution and use in source and binary forms, with or without modification, are
  16. * permitted provided that the following conditions are met:
  17. *
  18. * * Redistributions of source code must retain the above copyright notice, this list of
  19. * conditions and the following disclaimer.
  20. *
  21. * * Redistributions in binary form must reproduce the above copyright notice, this list
  22. * of conditions and the following disclaimer in the documentation and/or other materials
  23. * provided with the distribution.
  24. *
  25. * * Neither the name of the SimplePie Team nor the names of its contributors may be used
  26. * to endorse or promote products derived from this software without specific prior
  27. * written permission.
  28. *
  29. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
  30. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  31. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS
  32. * AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  34. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  35. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  36. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  37. * POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. * @package SimplePie
  40. * @version 1.2
  41. * @copyright 2004-2009 Ryan Parman, Geoffrey Sneddon
  42. * @author Ryan Parman
  43. * @author Geoffrey Sneddon
  44. * @link http://simplepie.org/ SimplePie
  45. * @link http://simplepie.org/support/ Please submit all bug reports and feature requests to the SimplePie forums
  46. * @license http://www.opensource.org/licenses/bsd-license.php BSD License
  47. * @todo phpDoc comments
  48. */
  49. /**
  50. * SimplePie Name
  51. */
  52. define('SIMPLEPIE_NAME', 'SimplePie');
  53. /**
  54. * SimplePie Version
  55. */
  56. define('SIMPLEPIE_VERSION', '1.2');
  57. /**
  58. * SimplePie Build
  59. */
  60. define('SIMPLEPIE_BUILD', '20090627192103');
  61. /**
  62. * SimplePie Website URL
  63. */
  64. define('SIMPLEPIE_URL', 'http://simplepie.org');
  65. /**
  66. * SimplePie Useragent
  67. * @see SimplePie::set_useragent()
  68. */
  69. define('SIMPLEPIE_USERAGENT', SIMPLEPIE_NAME . '/' . SIMPLEPIE_VERSION . ' (Feed Parser; ' . SIMPLEPIE_URL . '; Allow like Gecko) Build/' . SIMPLEPIE_BUILD);
  70. /**
  71. * SimplePie Linkback
  72. */
  73. define('SIMPLEPIE_LINKBACK', '<a href="' . SIMPLEPIE_URL . '" title="' . SIMPLEPIE_NAME . ' ' . SIMPLEPIE_VERSION . '">' . SIMPLEPIE_NAME . '</a>');
  74. /**
  75. * No Autodiscovery
  76. * @see SimplePie::set_autodiscovery_level()
  77. */
  78. define('SIMPLEPIE_LOCATOR_NONE', 0);
  79. /**
  80. * Feed Link Element Autodiscovery
  81. * @see SimplePie::set_autodiscovery_level()
  82. */
  83. define('SIMPLEPIE_LOCATOR_AUTODISCOVERY', 1);
  84. /**
  85. * Local Feed Extension Autodiscovery
  86. * @see SimplePie::set_autodiscovery_level()
  87. */
  88. define('SIMPLEPIE_LOCATOR_LOCAL_EXTENSION', 2);
  89. /**
  90. * Local Feed Body Autodiscovery
  91. * @see SimplePie::set_autodiscovery_level()
  92. */
  93. define('SIMPLEPIE_LOCATOR_LOCAL_BODY', 4);
  94. /**
  95. * Remote Feed Extension Autodiscovery
  96. * @see SimplePie::set_autodiscovery_level()
  97. */
  98. define('SIMPLEPIE_LOCATOR_REMOTE_EXTENSION', 8);
  99. /**
  100. * Remote Feed Body Autodiscovery
  101. * @see SimplePie::set_autodiscovery_level()
  102. */
  103. define('SIMPLEPIE_LOCATOR_REMOTE_BODY', 16);
  104. /**
  105. * All Feed Autodiscovery
  106. * @see SimplePie::set_autodiscovery_level()
  107. */
  108. define('SIMPLEPIE_LOCATOR_ALL', 31);
  109. /**
  110. * No known feed type
  111. */
  112. define('SIMPLEPIE_TYPE_NONE', 0);
  113. /**
  114. * RSS 0.90
  115. */
  116. define('SIMPLEPIE_TYPE_RSS_090', 1);
  117. /**
  118. * RSS 0.91 (Netscape)
  119. */
  120. define('SIMPLEPIE_TYPE_RSS_091_NETSCAPE', 2);
  121. /**
  122. * RSS 0.91 (Userland)
  123. */
  124. define('SIMPLEPIE_TYPE_RSS_091_USERLAND', 4);
  125. /**
  126. * RSS 0.91 (both Netscape and Userland)
  127. */
  128. define('SIMPLEPIE_TYPE_RSS_091', 6);
  129. /**
  130. * RSS 0.92
  131. */
  132. define('SIMPLEPIE_TYPE_RSS_092', 8);
  133. /**
  134. * RSS 0.93
  135. */
  136. define('SIMPLEPIE_TYPE_RSS_093', 16);
  137. /**
  138. * RSS 0.94
  139. */
  140. define('SIMPLEPIE_TYPE_RSS_094', 32);
  141. /**
  142. * RSS 1.0
  143. */
  144. define('SIMPLEPIE_TYPE_RSS_10', 64);
  145. /**
  146. * RSS 2.0
  147. */
  148. define('SIMPLEPIE_TYPE_RSS_20', 128);
  149. /**
  150. * RDF-based RSS
  151. */
  152. define('SIMPLEPIE_TYPE_RSS_RDF', 65);
  153. /**
  154. * Non-RDF-based RSS (truly intended as syndication format)
  155. */
  156. define('SIMPLEPIE_TYPE_RSS_SYNDICATION', 190);
  157. /**
  158. * All RSS
  159. */
  160. define('SIMPLEPIE_TYPE_RSS_ALL', 255);
  161. /**
  162. * Atom 0.3
  163. */
  164. define('SIMPLEPIE_TYPE_ATOM_03', 256);
  165. /**
  166. * Atom 1.0
  167. */
  168. define('SIMPLEPIE_TYPE_ATOM_10', 512);
  169. /**
  170. * All Atom
  171. */
  172. define('SIMPLEPIE_TYPE_ATOM_ALL', 768);
  173. /**
  174. * All feed types
  175. */
  176. define('SIMPLEPIE_TYPE_ALL', 1023);
  177. /**
  178. * No construct
  179. */
  180. define('SIMPLEPIE_CONSTRUCT_NONE', 0);
  181. /**
  182. * Text construct
  183. */
  184. define('SIMPLEPIE_CONSTRUCT_TEXT', 1);
  185. /**
  186. * HTML construct
  187. */
  188. define('SIMPLEPIE_CONSTRUCT_HTML', 2);
  189. /**
  190. * XHTML construct
  191. */
  192. define('SIMPLEPIE_CONSTRUCT_XHTML', 4);
  193. /**
  194. * base64-encoded construct
  195. */
  196. define('SIMPLEPIE_CONSTRUCT_BASE64', 8);
  197. /**
  198. * IRI construct
  199. */
  200. define('SIMPLEPIE_CONSTRUCT_IRI', 16);
  201. /**
  202. * A construct that might be HTML
  203. */
  204. define('SIMPLEPIE_CONSTRUCT_MAYBE_HTML', 32);
  205. /**
  206. * All constructs
  207. */
  208. define('SIMPLEPIE_CONSTRUCT_ALL', 63);
  209. /**
  210. * Don't change case
  211. */
  212. define('SIMPLEPIE_SAME_CASE', 1);
  213. /**
  214. * Change to lowercase
  215. */
  216. define('SIMPLEPIE_LOWERCASE', 2);
  217. /**
  218. * Change to uppercase
  219. */
  220. define('SIMPLEPIE_UPPERCASE', 4);
  221. /**
  222. * PCRE for HTML attributes
  223. */
  224. 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]*');
  225. /**
  226. * PCRE for XML attributes
  227. */
  228. define('SIMPLEPIE_PCRE_XML_ATTRIBUTE', '((?:\s+(?:(?:[^\s:]+:)?[^\s:]+)\s*=\s*(?:"(?:[^"]*)"|\'(?:[^\']*)\'))*)\s*');
  229. /**
  230. * XML Namespace
  231. */
  232. define('SIMPLEPIE_NAMESPACE_XML', 'http://www.w3.org/XML/1998/namespace');
  233. /**
  234. * Atom 1.0 Namespace
  235. */
  236. define('SIMPLEPIE_NAMESPACE_ATOM_10', 'http://www.w3.org/2005/Atom');
  237. /**
  238. * Atom 0.3 Namespace
  239. */
  240. define('SIMPLEPIE_NAMESPACE_ATOM_03', 'http://purl.org/atom/ns#');
  241. /**
  242. * RDF Namespace
  243. */
  244. define('SIMPLEPIE_NAMESPACE_RDF', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#');
  245. /**
  246. * RSS 0.90 Namespace
  247. */
  248. define('SIMPLEPIE_NAMESPACE_RSS_090', 'http://my.netscape.com/rdf/simple/0.9/');
  249. /**
  250. * RSS 1.0 Namespace
  251. */
  252. define('SIMPLEPIE_NAMESPACE_RSS_10', 'http://purl.org/rss/1.0/');
  253. /**
  254. * RSS 1.0 Content Module Namespace
  255. */
  256. define('SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT', 'http://purl.org/rss/1.0/modules/content/');
  257. /**
  258. * RSS 2.0 Namespace
  259. * (Stupid, I know, but I'm certain it will confuse people less with support.)
  260. */
  261. define('SIMPLEPIE_NAMESPACE_RSS_20', '');
  262. /**
  263. * DC 1.0 Namespace
  264. */
  265. define('SIMPLEPIE_NAMESPACE_DC_10', 'http://purl.org/dc/elements/1.0/');
  266. /**
  267. * DC 1.1 Namespace
  268. */
  269. define('SIMPLEPIE_NAMESPACE_DC_11', 'http://purl.org/dc/elements/1.1/');
  270. /**
  271. * W3C Basic Geo (WGS84 lat/long) Vocabulary Namespace
  272. */
  273. define('SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO', 'http://www.w3.org/2003/01/geo/wgs84_pos#');
  274. /**
  275. * GeoRSS Namespace
  276. */
  277. define('SIMPLEPIE_NAMESPACE_GEORSS', 'http://www.georss.org/georss');
  278. /**
  279. * Media RSS Namespace
  280. */
  281. define('SIMPLEPIE_NAMESPACE_MEDIARSS', 'http://search.yahoo.com/mrss/');
  282. /**
  283. * Wrong Media RSS Namespace
  284. */
  285. define('SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG', 'http://search.yahoo.com/mrss');
  286. /**
  287. * iTunes RSS Namespace
  288. */
  289. define('SIMPLEPIE_NAMESPACE_ITUNES', 'http://www.itunes.com/dtds/podcast-1.0.dtd');
  290. /**
  291. * XHTML Namespace
  292. */
  293. define('SIMPLEPIE_NAMESPACE_XHTML', 'http://www.w3.org/1999/xhtml');
  294. /**
  295. * IANA Link Relations Registry
  296. */
  297. define('SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY', 'http://www.iana.org/assignments/relation/');
  298. /**
  299. * Whether we're running on PHP5
  300. */
  301. define('SIMPLEPIE_PHP5', version_compare(PHP_VERSION, '5.0.0', '>='));
  302. /**
  303. * No file source
  304. */
  305. define('SIMPLEPIE_FILE_SOURCE_NONE', 0);
  306. /**
  307. * Remote file source
  308. */
  309. define('SIMPLEPIE_FILE_SOURCE_REMOTE', 1);
  310. /**
  311. * Local file source
  312. */
  313. define('SIMPLEPIE_FILE_SOURCE_LOCAL', 2);
  314. /**
  315. * fsockopen() file source
  316. */
  317. define('SIMPLEPIE_FILE_SOURCE_FSOCKOPEN', 4);
  318. /**
  319. * cURL file source
  320. */
  321. define('SIMPLEPIE_FILE_SOURCE_CURL', 8);
  322. /**
  323. * file_get_contents() file source
  324. */
  325. define('SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS', 16);
  326. /**
  327. * SimplePie
  328. *
  329. * @package SimplePie
  330. */
  331. class SimplePie
  332. {
  333. /**
  334. * @var array Raw data
  335. * @access private
  336. */
  337. var $data = array();
  338. /**
  339. * @var mixed Error string
  340. * @access private
  341. */
  342. var $error;
  343. /**
  344. * @var object Instance of SimplePie_Sanitize (or other class)
  345. * @see SimplePie::set_sanitize_class()
  346. * @access private
  347. */
  348. var $sanitize;
  349. /**
  350. * @var string SimplePie Useragent
  351. * @see SimplePie::set_useragent()
  352. * @access private
  353. */
  354. var $useragent = SIMPLEPIE_USERAGENT;
  355. /**
  356. * @var string Feed URL
  357. * @see SimplePie::set_feed_url()
  358. * @access private
  359. */
  360. var $feed_url;
  361. /**
  362. * @var object Instance of SimplePie_File to use as a feed
  363. * @see SimplePie::set_file()
  364. * @access private
  365. */
  366. var $file;
  367. /**
  368. * @var string Raw feed data
  369. * @see SimplePie::set_raw_data()
  370. * @access private
  371. */
  372. var $raw_data;
  373. /**
  374. * @var int Timeout for fetching remote files
  375. * @see SimplePie::set_timeout()
  376. * @access private
  377. */
  378. var $timeout = 10;
  379. /**
  380. * @var bool Forces fsockopen() to be used for remote files instead
  381. * of cURL, even if a new enough version is installed
  382. * @see SimplePie::force_fsockopen()
  383. * @access private
  384. */
  385. var $force_fsockopen = false;
  386. /**
  387. * @var bool Force the given data/URL to be treated as a feed no matter what
  388. * it appears like
  389. * @see SimplePie::force_feed()
  390. * @access private
  391. */
  392. var $force_feed = false;
  393. /**
  394. * @var bool Enable/Disable XML dump
  395. * @see SimplePie::enable_xml_dump()
  396. * @access private
  397. */
  398. var $xml_dump = false;
  399. /**
  400. * @var bool Enable/Disable Caching
  401. * @see SimplePie::enable_cache()
  402. * @access private
  403. */
  404. var $cache = true;
  405. /**
  406. * @var int Cache duration (in seconds)
  407. * @see SimplePie::set_cache_duration()
  408. * @access private
  409. */
  410. var $cache_duration = 3600;
  411. /**
  412. * @var int Auto-discovery cache duration (in seconds)
  413. * @see SimplePie::set_autodiscovery_cache_duration()
  414. * @access private
  415. */
  416. var $autodiscovery_cache_duration = 604800; // 7 Days.
  417. /**
  418. * @var string Cache location (relative to executing script)
  419. * @see SimplePie::set_cache_location()
  420. * @access private
  421. */
  422. var $cache_location = './cache';
  423. /**
  424. * @var string Function that creates the cache filename
  425. * @see SimplePie::set_cache_name_function()
  426. * @access private
  427. */
  428. var $cache_name_function = 'md5';
  429. /**
  430. * @var bool Reorder feed by date descending
  431. * @see SimplePie::enable_order_by_date()
  432. * @access private
  433. */
  434. var $order_by_date = true;
  435. /**
  436. * @var mixed Force input encoding to be set to the follow value
  437. * (false, or anything type-cast to false, disables this feature)
  438. * @see SimplePie::set_input_encoding()
  439. * @access private
  440. */
  441. var $input_encoding = false;
  442. /**
  443. * @var int Feed Autodiscovery Level
  444. * @see SimplePie::set_autodiscovery_level()
  445. * @access private
  446. */
  447. var $autodiscovery = SIMPLEPIE_LOCATOR_ALL;
  448. /**
  449. * @var string Class used for caching feeds
  450. * @see SimplePie::set_cache_class()
  451. * @access private
  452. */
  453. var $cache_class = 'SimplePie_Cache';
  454. /**
  455. * @var string Class used for locating feeds
  456. * @see SimplePie::set_locator_class()
  457. * @access private
  458. */
  459. var $locator_class = 'SimplePie_Locator';
  460. /**
  461. * @var string Class used for parsing feeds
  462. * @see SimplePie::set_parser_class()
  463. * @access private
  464. */
  465. var $parser_class = 'SimplePie_Parser';
  466. /**
  467. * @var string Class used for fetching feeds
  468. * @see SimplePie::set_file_class()
  469. * @access private
  470. */
  471. var $file_class = 'SimplePie_File';
  472. /**
  473. * @var string Class used for items
  474. * @see SimplePie::set_item_class()
  475. * @access private
  476. */
  477. var $item_class = 'SimplePie_Item';
  478. /**
  479. * @var string Class used for authors
  480. * @see SimplePie::set_author_class()
  481. * @access private
  482. */
  483. var $author_class = 'SimplePie_Author';
  484. /**
  485. * @var string Class used for categories
  486. * @see SimplePie::set_category_class()
  487. * @access private
  488. */
  489. var $category_class = 'SimplePie_Category';
  490. /**
  491. * @var string Class used for enclosures
  492. * @see SimplePie::set_enclosures_class()
  493. * @access private
  494. */
  495. var $enclosure_class = 'SimplePie_Enclosure';
  496. /**
  497. * @var string Class used for Media RSS <media:text> captions
  498. * @see SimplePie::set_caption_class()
  499. * @access private
  500. */
  501. var $caption_class = 'SimplePie_Caption';
  502. /**
  503. * @var string Class used for Media RSS <media:copyright>
  504. * @see SimplePie::set_copyright_class()
  505. * @access private
  506. */
  507. var $copyright_class = 'SimplePie_Copyright';
  508. /**
  509. * @var string Class used for Media RSS <media:credit>
  510. * @see SimplePie::set_credit_class()
  511. * @access private
  512. */
  513. var $credit_class = 'SimplePie_Credit';
  514. /**
  515. * @var string Class used for Media RSS <media:rating>
  516. * @see SimplePie::set_rating_class()
  517. * @access private
  518. */
  519. var $rating_class = 'SimplePie_Rating';
  520. /**
  521. * @var string Class used for Media RSS <media:restriction>
  522. * @see SimplePie::set_restriction_class()
  523. * @access private
  524. */
  525. var $restriction_class = 'SimplePie_Restriction';
  526. /**
  527. * @var string Class used for content-type sniffing
  528. * @see SimplePie::set_content_type_sniffer_class()
  529. * @access private
  530. */
  531. var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  532. /**
  533. * @var string Class used for item sources.
  534. * @see SimplePie::set_source_class()
  535. * @access private
  536. */
  537. var $source_class = 'SimplePie_Source';
  538. /**
  539. * @var mixed Set javascript query string parameter (false, or
  540. * anything type-cast to false, disables this feature)
  541. * @see SimplePie::set_javascript()
  542. * @access private
  543. */
  544. var $javascript = 'js';
  545. /**
  546. * @var int Maximum number of feeds to check with autodiscovery
  547. * @see SimplePie::set_max_checked_feeds()
  548. * @access private
  549. */
  550. var $max_checked_feeds = 10;
  551. /**
  552. * @var array All the feeds found during the autodiscovery process
  553. * @see SimplePie::get_all_discovered_feeds()
  554. * @access private
  555. */
  556. var $all_discovered_feeds = array();
  557. /**
  558. * @var string Web-accessible path to the handler_favicon.php file.
  559. * @see SimplePie::set_favicon_handler()
  560. * @access private
  561. */
  562. var $favicon_handler = '';
  563. /**
  564. * @var string Web-accessible path to the handler_image.php file.
  565. * @see SimplePie::set_image_handler()
  566. * @access private
  567. */
  568. var $image_handler = '';
  569. /**
  570. * @var array Stores the URLs when multiple feeds are being initialized.
  571. * @see SimplePie::set_feed_url()
  572. * @access private
  573. */
  574. var $multifeed_url = array();
  575. /**
  576. * @var array Stores SimplePie objects when multiple feeds initialized.
  577. * @access private
  578. */
  579. var $multifeed_objects = array();
  580. /**
  581. * @var array Stores the get_object_vars() array for use with multifeeds.
  582. * @see SimplePie::set_feed_url()
  583. * @access private
  584. */
  585. var $config_settings = null;
  586. /**
  587. * @var integer Stores the number of items to return per-feed with multifeeds.
  588. * @see SimplePie::set_item_limit()
  589. * @access private
  590. */
  591. var $item_limit = 0;
  592. /**
  593. * @var array Stores the default attributes to be stripped by strip_attributes().
  594. * @see SimplePie::strip_attributes()
  595. * @access private
  596. */
  597. var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  598. /**
  599. * @var array Stores the default tags to be stripped by strip_htmltags().
  600. * @see SimplePie::strip_htmltags()
  601. * @access private
  602. */
  603. var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  604. /**
  605. * The SimplePie class contains feed level data and options
  606. *
  607. * There are two ways that you can create a new SimplePie object. The first
  608. * is by passing a feed URL as a parameter to the SimplePie constructor
  609. * (as well as optionally setting the cache location and cache expiry). This
  610. * will initialise the whole feed with all of the default settings, and you
  611. * can begin accessing methods and properties immediately.
  612. *
  613. * The second way is to create the SimplePie object with no parameters
  614. * at all. This will enable you to set configuration options. After setting
  615. * them, you must initialise the feed using $feed->init(). At that point the
  616. * object's methods and properties will be available to you. This format is
  617. * what is used throughout this documentation.
  618. *
  619. * @access public
  620. * @since 1.0 Preview Release
  621. * @param string $feed_url This is the URL you want to parse.
  622. * @param string $cache_location This is where you want the cache to be stored.
  623. * @param int $cache_duration This is the number of seconds that you want to store the cache file for.
  624. */
  625. function SimplePie($feed_url = null, $cache_location = null, $cache_duration = null)
  626. {
  627. // Other objects, instances created here so we can set options on them
  628. $this->sanitize = new SimplePie_Sanitize;
  629. // Set options if they're passed to the constructor
  630. if ($cache_location !== null)
  631. {
  632. $this->set_cache_location($cache_location);
  633. }
  634. if ($cache_duration !== null)
  635. {
  636. $this->set_cache_duration($cache_duration);
  637. }
  638. // Only init the script if we're passed a feed URL
  639. if ($feed_url !== null)
  640. {
  641. $this->set_feed_url($feed_url);
  642. $this->init();
  643. }
  644. }
  645. /**
  646. * Used for converting object to a string
  647. */
  648. function __toString()
  649. {
  650. return md5(serialize($this->data));
  651. }
  652. /**
  653. * Remove items that link back to this before destroying this object
  654. */
  655. function __destruct()
  656. {
  657. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  658. {
  659. if (!empty($this->data['items']))
  660. {
  661. foreach ($this->data['items'] as $item)
  662. {
  663. $item->__destruct();
  664. }
  665. unset($item, $this->data['items']);
  666. }
  667. if (!empty($this->data['ordered_items']))
  668. {
  669. foreach ($this->data['ordered_items'] as $item)
  670. {
  671. $item->__destruct();
  672. }
  673. unset($item, $this->data['ordered_items']);
  674. }
  675. }
  676. }
  677. /**
  678. * Force the given data/URL to be treated as a feed no matter what it
  679. * appears like
  680. *
  681. * @access public
  682. * @since 1.1
  683. * @param bool $enable Force the given data/URL to be treated as a feed
  684. */
  685. function force_feed($enable = false)
  686. {
  687. $this->force_feed = (bool) $enable;
  688. }
  689. /**
  690. * This is the URL of the feed you want to parse.
  691. *
  692. * This allows you to enter the URL of the feed you want to parse, or the
  693. * website you want to try to use auto-discovery on. This takes priority
  694. * over any set raw data.
  695. *
  696. * You can set multiple feeds to mash together by passing an array instead
  697. * of a string for the $url. Remember that with each additional feed comes
  698. * additional processing and resources.
  699. *
  700. * @access public
  701. * @since 1.0 Preview Release
  702. * @param mixed $url This is the URL (or array of URLs) that you want to parse.
  703. * @see SimplePie::set_raw_data()
  704. */
  705. function set_feed_url($url)
  706. {
  707. if (is_array($url))
  708. {
  709. $this->multifeed_url = array();
  710. foreach ($url as $value)
  711. {
  712. $this->multifeed_url[] = SimplePie_Misc::fix_protocol($value, 1);
  713. }
  714. }
  715. else
  716. {
  717. $this->feed_url = SimplePie_Misc::fix_protocol($url, 1);
  718. }
  719. }
  720. /**
  721. * Provides an instance of SimplePie_File to use as a feed
  722. *
  723. * @access public
  724. * @param object &$file Instance of SimplePie_File (or subclass)
  725. * @return bool True on success, false on failure
  726. */
  727. function set_file(&$file)
  728. {
  729. if (is_a($file, 'SimplePie_File'))
  730. {
  731. $this->feed_url = $file->url;
  732. $this->file =& $file;
  733. return true;
  734. }
  735. return false;
  736. }
  737. /**
  738. * Allows you to use a string of RSS/Atom data instead of a remote feed.
  739. *
  740. * If you have a feed available as a string in PHP, you can tell SimplePie
  741. * to parse that data string instead of a remote feed. Any set feed URL
  742. * takes precedence.
  743. *
  744. * @access public
  745. * @since 1.0 Beta 3
  746. * @param string $data RSS or Atom data as a string.
  747. * @see SimplePie::set_feed_url()
  748. */
  749. function set_raw_data($data)
  750. {
  751. $this->raw_data = $data;
  752. }
  753. /**
  754. * Allows you to override the default timeout for fetching remote feeds.
  755. *
  756. * This allows you to change the maximum time the feed's server to respond
  757. * and send the feed back.
  758. *
  759. * @access public
  760. * @since 1.0 Beta 3
  761. * @param int $timeout The maximum number of seconds to spend waiting to retrieve a feed.
  762. */
  763. function set_timeout($timeout = 10)
  764. {
  765. $this->timeout = (int) $timeout;
  766. }
  767. /**
  768. * Forces SimplePie to use fsockopen() instead of the preferred cURL
  769. * functions.
  770. *
  771. * @access public
  772. * @since 1.0 Beta 3
  773. * @param bool $enable Force fsockopen() to be used
  774. */
  775. function force_fsockopen($enable = false)
  776. {
  777. $this->force_fsockopen = (bool) $enable;
  778. }
  779. /**
  780. * Outputs the raw XML content of the feed, after it has gone through
  781. * SimplePie's filters.
  782. *
  783. * Used only for debugging, this function will output the XML content as
  784. * text/xml. When SimplePie reads in a feed, it does a bit of cleaning up
  785. * before trying to parse it. Many parts of the feed are re-written in
  786. * memory, and in the end, you have a parsable feed. XML dump shows you the
  787. * actual XML that SimplePie tries to parse, which may or may not be very
  788. * different from the original feed.
  789. *
  790. * @access public
  791. * @since 1.0 Preview Release
  792. * @param bool $enable Enable XML dump
  793. */
  794. function enable_xml_dump($enable = false)
  795. {
  796. $this->xml_dump = (bool) $enable;
  797. }
  798. /**
  799. * Enables/disables caching in SimplePie.
  800. *
  801. * This option allows you to disable caching all-together in SimplePie.
  802. * However, disabling the cache can lead to longer load times.
  803. *
  804. * @access public
  805. * @since 1.0 Preview Release
  806. * @param bool $enable Enable caching
  807. */
  808. function enable_cache($enable = true)
  809. {
  810. $this->cache = (bool) $enable;
  811. }
  812. /**
  813. * Set the length of time (in seconds) that the contents of a feed
  814. * will be cached.
  815. *
  816. * @access public
  817. * @param int $seconds The feed content cache duration.
  818. */
  819. function set_cache_duration($seconds = 3600)
  820. {
  821. $this->cache_duration = (int) $seconds;
  822. }
  823. /**
  824. * Set the length of time (in seconds) that the autodiscovered feed
  825. * URL will be cached.
  826. *
  827. * @access public
  828. * @param int $seconds The autodiscovered feed URL cache duration.
  829. */
  830. function set_autodiscovery_cache_duration($seconds = 604800)
  831. {
  832. $this->autodiscovery_cache_duration = (int) $seconds;
  833. }
  834. /**
  835. * Set the file system location where the cached files should be stored.
  836. *
  837. * @access public
  838. * @param string $location The file system location.
  839. */
  840. function set_cache_location($location = './cache')
  841. {
  842. $this->cache_location = (string) $location;
  843. }
  844. /**
  845. * Determines whether feed items should be sorted into reverse chronological order.
  846. *
  847. * @access public
  848. * @param bool $enable Sort as reverse chronological order.
  849. */
  850. function enable_order_by_date($enable = true)
  851. {
  852. $this->order_by_date = (bool) $enable;
  853. }
  854. /**
  855. * Allows you to override the character encoding reported by the feed.
  856. *
  857. * @access public
  858. * @param string $encoding Character encoding.
  859. */
  860. function set_input_encoding($encoding = false)
  861. {
  862. if ($encoding)
  863. {
  864. $this->input_encoding = (string) $encoding;
  865. }
  866. else
  867. {
  868. $this->input_encoding = false;
  869. }
  870. }
  871. /**
  872. * Set how much feed autodiscovery to do
  873. *
  874. * @access public
  875. * @see SIMPLEPIE_LOCATOR_NONE
  876. * @see SIMPLEPIE_LOCATOR_AUTODISCOVERY
  877. * @see SIMPLEPIE_LOCATOR_LOCAL_EXTENSION
  878. * @see SIMPLEPIE_LOCATOR_LOCAL_BODY
  879. * @see SIMPLEPIE_LOCATOR_REMOTE_EXTENSION
  880. * @see SIMPLEPIE_LOCATOR_REMOTE_BODY
  881. * @see SIMPLEPIE_LOCATOR_ALL
  882. * @param int $level Feed Autodiscovery Level (level can be a
  883. * combination of the above constants, see bitwise OR operator)
  884. */
  885. function set_autodiscovery_level($level = SIMPLEPIE_LOCATOR_ALL)
  886. {
  887. $this->autodiscovery = (int) $level;
  888. }
  889. /**
  890. * Allows you to change which class SimplePie uses for caching.
  891. * Useful when you are overloading or extending SimplePie's default classes.
  892. *
  893. * @access public
  894. * @param string $class Name of custom class.
  895. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  896. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  897. */
  898. function set_cache_class($class = 'SimplePie_Cache')
  899. {
  900. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Cache'))
  901. {
  902. $this->cache_class = $class;
  903. return true;
  904. }
  905. return false;
  906. }
  907. /**
  908. * Allows you to change which class SimplePie uses for auto-discovery.
  909. * Useful when you are overloading or extending SimplePie's default classes.
  910. *
  911. * @access public
  912. * @param string $class Name of custom class.
  913. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  914. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  915. */
  916. function set_locator_class($class = 'SimplePie_Locator')
  917. {
  918. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Locator'))
  919. {
  920. $this->locator_class = $class;
  921. return true;
  922. }
  923. return false;
  924. }
  925. /**
  926. * Allows you to change which class SimplePie uses for XML parsing.
  927. * Useful when you are overloading or extending SimplePie's default classes.
  928. *
  929. * @access public
  930. * @param string $class Name of custom class.
  931. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  932. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  933. */
  934. function set_parser_class($class = 'SimplePie_Parser')
  935. {
  936. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Parser'))
  937. {
  938. $this->parser_class = $class;
  939. return true;
  940. }
  941. return false;
  942. }
  943. /**
  944. * Allows you to change which class SimplePie uses for remote file fetching.
  945. * Useful when you are overloading or extending SimplePie's default classes.
  946. *
  947. * @access public
  948. * @param string $class Name of custom class.
  949. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  950. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  951. */
  952. function set_file_class($class = 'SimplePie_File')
  953. {
  954. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_File'))
  955. {
  956. $this->file_class = $class;
  957. return true;
  958. }
  959. return false;
  960. }
  961. /**
  962. * Allows you to change which class SimplePie uses for data sanitization.
  963. * Useful when you are overloading or extending SimplePie's default classes.
  964. *
  965. * @access public
  966. * @param string $class Name of custom class.
  967. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  968. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  969. */
  970. function set_sanitize_class($class = 'SimplePie_Sanitize')
  971. {
  972. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Sanitize'))
  973. {
  974. $this->sanitize = new $class;
  975. return true;
  976. }
  977. return false;
  978. }
  979. /**
  980. * Allows you to change which class SimplePie uses for handling feed items.
  981. * Useful when you are overloading or extending SimplePie's default classes.
  982. *
  983. * @access public
  984. * @param string $class Name of custom class.
  985. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  986. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  987. */
  988. function set_item_class($class = 'SimplePie_Item')
  989. {
  990. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Item'))
  991. {
  992. $this->item_class = $class;
  993. return true;
  994. }
  995. return false;
  996. }
  997. /**
  998. * Allows you to change which class SimplePie uses for handling author data.
  999. * Useful when you are overloading or extending SimplePie's default classes.
  1000. *
  1001. * @access public
  1002. * @param string $class Name of custom class.
  1003. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1004. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1005. */
  1006. function set_author_class($class = 'SimplePie_Author')
  1007. {
  1008. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Author'))
  1009. {
  1010. $this->author_class = $class;
  1011. return true;
  1012. }
  1013. return false;
  1014. }
  1015. /**
  1016. * Allows you to change which class SimplePie uses for handling category data.
  1017. * Useful when you are overloading or extending SimplePie's default classes.
  1018. *
  1019. * @access public
  1020. * @param string $class Name of custom class.
  1021. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1022. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1023. */
  1024. function set_category_class($class = 'SimplePie_Category')
  1025. {
  1026. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Category'))
  1027. {
  1028. $this->category_class = $class;
  1029. return true;
  1030. }
  1031. return false;
  1032. }
  1033. /**
  1034. * Allows you to change which class SimplePie uses for feed enclosures.
  1035. * Useful when you are overloading or extending SimplePie's default classes.
  1036. *
  1037. * @access public
  1038. * @param string $class Name of custom class.
  1039. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1040. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1041. */
  1042. function set_enclosure_class($class = 'SimplePie_Enclosure')
  1043. {
  1044. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Enclosure'))
  1045. {
  1046. $this->enclosure_class = $class;
  1047. return true;
  1048. }
  1049. return false;
  1050. }
  1051. /**
  1052. * Allows you to change which class SimplePie uses for <media:text> captions
  1053. * Useful when you are overloading or extending SimplePie's default classes.
  1054. *
  1055. * @access public
  1056. * @param string $class Name of custom class.
  1057. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1058. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1059. */
  1060. function set_caption_class($class = 'SimplePie_Caption')
  1061. {
  1062. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Caption'))
  1063. {
  1064. $this->caption_class = $class;
  1065. return true;
  1066. }
  1067. return false;
  1068. }
  1069. /**
  1070. * Allows you to change which class SimplePie uses for <media:copyright>
  1071. * Useful when you are overloading or extending SimplePie's default classes.
  1072. *
  1073. * @access public
  1074. * @param string $class Name of custom class.
  1075. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1076. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1077. */
  1078. function set_copyright_class($class = 'SimplePie_Copyright')
  1079. {
  1080. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Copyright'))
  1081. {
  1082. $this->copyright_class = $class;
  1083. return true;
  1084. }
  1085. return false;
  1086. }
  1087. /**
  1088. * Allows you to change which class SimplePie uses for <media:credit>
  1089. * Useful when you are overloading or extending SimplePie's default classes.
  1090. *
  1091. * @access public
  1092. * @param string $class Name of custom class.
  1093. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1094. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1095. */
  1096. function set_credit_class($class = 'SimplePie_Credit')
  1097. {
  1098. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Credit'))
  1099. {
  1100. $this->credit_class = $class;
  1101. return true;
  1102. }
  1103. return false;
  1104. }
  1105. /**
  1106. * Allows you to change which class SimplePie uses for <media:rating>
  1107. * Useful when you are overloading or extending SimplePie's default classes.
  1108. *
  1109. * @access public
  1110. * @param string $class Name of custom class.
  1111. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1112. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1113. */
  1114. function set_rating_class($class = 'SimplePie_Rating')
  1115. {
  1116. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Rating'))
  1117. {
  1118. $this->rating_class = $class;
  1119. return true;
  1120. }
  1121. return false;
  1122. }
  1123. /**
  1124. * Allows you to change which class SimplePie uses for <media:restriction>
  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/keyword.extends.php PHP4 extends documentation
  1130. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1131. */
  1132. function set_restriction_class($class = 'SimplePie_Restriction')
  1133. {
  1134. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Restriction'))
  1135. {
  1136. $this->restriction_class = $class;
  1137. return true;
  1138. }
  1139. return false;
  1140. }
  1141. /**
  1142. * Allows you to change which class SimplePie uses for content-type sniffing.
  1143. * Useful when you are overloading or extending SimplePie's default classes.
  1144. *
  1145. * @access public
  1146. * @param string $class Name of custom class.
  1147. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1148. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1149. */
  1150. function set_content_type_sniffer_class($class = 'SimplePie_Content_Type_Sniffer')
  1151. {
  1152. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Content_Type_Sniffer'))
  1153. {
  1154. $this->content_type_sniffer_class = $class;
  1155. return true;
  1156. }
  1157. return false;
  1158. }
  1159. /**
  1160. * Allows you to change which class SimplePie uses item sources.
  1161. * Useful when you are overloading or extending SimplePie's default classes.
  1162. *
  1163. * @access public
  1164. * @param string $class Name of custom class.
  1165. * @link http://php.net/manual/en/keyword.extends.php PHP4 extends documentation
  1166. * @link http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.extends PHP5 extends documentation
  1167. */
  1168. function set_source_class($class = 'SimplePie_Source')
  1169. {
  1170. if (SimplePie_Misc::is_subclass_of($class, 'SimplePie_Source'))
  1171. {
  1172. $this->source_class = $class;
  1173. return true;
  1174. }
  1175. return false;
  1176. }
  1177. /**
  1178. * Allows you to override the default user agent string.
  1179. *
  1180. * @access public
  1181. * @param string $ua New user agent string.
  1182. */
  1183. function set_useragent($ua = SIMPLEPIE_USERAGENT)
  1184. {
  1185. $this->useragent = (string) $ua;
  1186. }
  1187. /**
  1188. * Set callback function to create cache filename with
  1189. *
  1190. * @access public
  1191. * @param mixed $function Callback function
  1192. */
  1193. function set_cache_name_function($function = 'md5')
  1194. {
  1195. if (is_callable($function))
  1196. {
  1197. $this->cache_name_function = $function;
  1198. }
  1199. }
  1200. /**
  1201. * Set javascript query string parameter
  1202. *
  1203. * @access public
  1204. * @param mixed $get Javascript query string parameter
  1205. */
  1206. function set_javascript($get = 'js')
  1207. {
  1208. if ($get)
  1209. {
  1210. $this->javascript = (string) $get;
  1211. }
  1212. else
  1213. {
  1214. $this->javascript = false;
  1215. }
  1216. }
  1217. /**
  1218. * Set options to make SP as fast as possible. Forgoes a
  1219. * substantial amount of data sanitization in favor of speed.
  1220. *
  1221. * @access public
  1222. * @param bool $set Whether to set them or not
  1223. */
  1224. function set_stupidly_fast($set = false)
  1225. {
  1226. if ($set)
  1227. {
  1228. $this->enable_order_by_date(false);
  1229. $this->remove_div(false);
  1230. $this->strip_comments(false);
  1231. $this->strip_htmltags(false);
  1232. $this->strip_attributes(false);
  1233. $this->set_image_handler(false);
  1234. }
  1235. }
  1236. /**
  1237. * Set maximum number of feeds to check with autodiscovery
  1238. *
  1239. * @access public
  1240. * @param int $max Maximum number of feeds to check
  1241. */
  1242. function set_max_checked_feeds($max = 10)
  1243. {
  1244. $this->max_checked_feeds = (int) $max;
  1245. }
  1246. function remove_div($enable = true)
  1247. {
  1248. $this->sanitize->remove_div($enable);
  1249. }
  1250. function strip_htmltags($tags = '', $encode = null)
  1251. {
  1252. if ($tags === '')
  1253. {
  1254. $tags = $this->strip_htmltags;
  1255. }
  1256. $this->sanitize->strip_htmltags($tags);
  1257. if ($encode !== null)
  1258. {
  1259. $this->sanitize->encode_instead_of_strip($tags);
  1260. }
  1261. }
  1262. function encode_instead_of_strip($enable = true)
  1263. {
  1264. $this->sanitize->encode_instead_of_strip($enable);
  1265. }
  1266. function strip_attributes($attribs = '')
  1267. {
  1268. if ($attribs === '')
  1269. {
  1270. $attribs = $this->strip_attributes;
  1271. }
  1272. $this->sanitize->strip_attributes($attribs);
  1273. }
  1274. function set_output_encoding($encoding = 'UTF-8')
  1275. {
  1276. $this->sanitize->set_output_encoding($encoding);
  1277. }
  1278. function strip_comments($strip = false)
  1279. {
  1280. $this->sanitize->strip_comments($strip);
  1281. }
  1282. /**
  1283. * Set element/attribute key/value pairs of HTML attributes
  1284. * containing URLs that need to be resolved relative to the feed
  1285. *
  1286. * @access public
  1287. * @since 1.0
  1288. * @param array $element_attribute Element/attribute key/value pairs
  1289. */
  1290. 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'))
  1291. {
  1292. $this->sanitize->set_url_replacements($element_attribute);
  1293. }
  1294. /**
  1295. * Set the handler to enable the display of cached favicons.
  1296. *
  1297. * @access public
  1298. * @param str $page Web-accessible path to the handler_favicon.php file.
  1299. * @param str $qs The query string that the value should be passed to.
  1300. */
  1301. function set_favicon_handler($page = false, $qs = 'i')
  1302. {
  1303. if ($page !== false)
  1304. {
  1305. $this->favicon_handler = $page . '?' . $qs . '=';
  1306. }
  1307. else
  1308. {
  1309. $this->favicon_handler = '';
  1310. }
  1311. }
  1312. /**
  1313. * Set the handler to enable the display of cached images.
  1314. *
  1315. * @access public
  1316. * @param str $page Web-accessible path to the handler_image.php file.
  1317. * @param str $qs The query string that the value should be passed to.
  1318. */
  1319. function set_image_handler($page = false, $qs = 'i')
  1320. {
  1321. if ($page !== false)
  1322. {
  1323. $this->sanitize->set_image_handler($page . '?' . $qs . '=');
  1324. }
  1325. else
  1326. {
  1327. $this->image_handler = '';
  1328. }
  1329. }
  1330. /**
  1331. * Set the limit for items returned per-feed with multifeeds.
  1332. *
  1333. * @access public
  1334. * @param integer $limit The maximum number of items to return.
  1335. */
  1336. function set_item_limit($limit = 0)
  1337. {
  1338. $this->item_limit = (int) $limit;
  1339. }
  1340. function init()
  1341. {
  1342. // Check absolute bare minimum requirements.
  1343. if ((function_exists('version_compare') && version_compare(PHP_VERSION, '4.3.0', '<')) || !extension_loaded('xml') || !extension_loaded('pcre'))
  1344. {
  1345. return false;
  1346. }
  1347. // 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.
  1348. elseif (!extension_loaded('xmlreader'))
  1349. {
  1350. static $xml_is_sane = null;
  1351. if ($xml_is_sane === null)
  1352. {
  1353. $parser_check = xml_parser_create();
  1354. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  1355. xml_parser_free($parser_check);
  1356. $xml_is_sane = isset($values[0]['value']);
  1357. }
  1358. if (!$xml_is_sane)
  1359. {
  1360. return false;
  1361. }
  1362. }
  1363. if (isset($_GET[$this->javascript]))
  1364. {
  1365. SimplePie_Misc::output_javascript();
  1366. exit;
  1367. }
  1368. // Pass whatever was set with config options over to the sanitizer.
  1369. $this->sanitize->pass_cache_data($this->cache, $this->cache_location, $this->cache_name_function, $this->cache_class);
  1370. $this->sanitize->pass_file_data($this->file_class, $this->timeout, $this->useragent, $this->force_fsockopen);
  1371. if ($this->feed_url !== null || $this->raw_data !== null)
  1372. {
  1373. $this->data = array();
  1374. $this->multifeed_objects = array();
  1375. $cache = false;
  1376. if ($this->feed_url !== null)
  1377. {
  1378. $parsed_feed_url = SimplePie_Misc::parse_url($this->feed_url);
  1379. // Decide whether to enable caching
  1380. if ($this->cache && $parsed_feed_url['scheme'] !== '')
  1381. {
  1382. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $this->feed_url), 'spc');
  1383. }
  1384. // If it's enabled and we don't want an XML dump, use the cache
  1385. if ($cache && !$this->xml_dump)
  1386. {
  1387. // Load the Cache
  1388. $this->data = $cache->load();
  1389. if (!empty($this->data))
  1390. {
  1391. // If the cache is for an outdated build of SimplePie
  1392. if (!isset($this->data['build']) || $this->data['build'] !== SIMPLEPIE_BUILD)
  1393. {
  1394. $cache->unlink();
  1395. $this->data = array();
  1396. }
  1397. // If we've hit a collision just rerun it with caching disabled
  1398. elseif (isset($this->data['url']) && $this->data['url'] !== $this->feed_url)
  1399. {
  1400. $cache = false;
  1401. $this->data = array();
  1402. }
  1403. // If we've got a non feed_url stored (if the page isn't actually a feed, or is a redirect) use that URL.
  1404. elseif (isset($this->data['feed_url']))
  1405. {
  1406. // If the autodiscovery cache is still valid use it.
  1407. if ($cache->mtime() + $this->autodiscovery_cache_duration > time())
  1408. {
  1409. // Do not need to do feed autodiscovery yet.
  1410. if ($this->data['feed_url'] === $this->data['url'])
  1411. {
  1412. $cache->unlink();
  1413. $this->data = array();
  1414. }
  1415. else
  1416. {
  1417. $this->set_feed_url($this->data['feed_url']);
  1418. return $this->init();
  1419. }
  1420. }
  1421. }
  1422. // Check if the cache has been updated
  1423. elseif ($cache->mtime() + $this->cache_duration < time())
  1424. {
  1425. // If we have last-modified and/or etag set
  1426. if (isset($this->data['headers']['last-modified']) || isset($this->data['headers']['etag']))
  1427. {
  1428. $headers = array();
  1429. if (isset($this->data['headers']['last-modified']))
  1430. {
  1431. $headers['if-modified-since'] = $this->data['headers']['last-modified'];
  1432. }
  1433. if (isset($this->data['headers']['etag']))
  1434. {
  1435. $headers['if-none-match'] = '"' . $this->data['headers']['etag'] . '"';
  1436. }
  1437. $file = new $this->file_class($this->feed_url, $this->timeout/10, 5, $headers, $this->useragent, $this->force_fsockopen);
  1438. if ($file->success)
  1439. {
  1440. if ($file->status_code === 304)
  1441. {
  1442. $cache->touch();
  1443. return true;
  1444. }
  1445. else
  1446. {
  1447. $headers = $file->headers;
  1448. }
  1449. }
  1450. else
  1451. {
  1452. unset($file);
  1453. }
  1454. }
  1455. }
  1456. // If the cache is still valid, just return true
  1457. else
  1458. {
  1459. return true;
  1460. }
  1461. }
  1462. // If the cache is empty, delete it
  1463. else
  1464. {
  1465. $cache->unlink();
  1466. $this->data = array();
  1467. }
  1468. }
  1469. // 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.
  1470. if (!isset($file))
  1471. {
  1472. if (is_a($this->file, 'SimplePie_File') && $this->file->url === $this->feed_url)
  1473. {
  1474. $file =& $this->file;
  1475. }
  1476. else
  1477. {
  1478. $file = new $this->file_class($this->feed_url, $this->timeout, 5, null, $this->useragent, $this->force_fsockopen);
  1479. }
  1480. }
  1481. // If the file connection has an error, set SimplePie::error to that and quit
  1482. if (!$file->success && !($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  1483. {
  1484. $this->error = $file->error;
  1485. if (!empty($this->data))
  1486. {
  1487. return true;
  1488. }
  1489. else
  1490. {
  1491. return false;
  1492. }
  1493. }
  1494. if (!$this->force_feed)
  1495. {
  1496. // Check if the supplied URL is a feed, if it isn't, look for it.
  1497. $locate = new $this->locator_class($file, $this->timeout, $this->useragent, $this->file_class, $this->max_checked_feeds, $this->content_type_sniffer_class);
  1498. if (!$locate->is_feed($file))
  1499. {
  1500. // We need to unset this so that if SimplePie::set_file() has been called that object is untouched
  1501. unset($file);
  1502. if ($file = $locate->find($this->autodiscovery, $this->all_discovered_feeds))
  1503. {
  1504. if ($cache)
  1505. {
  1506. $this->data = array('url' => $this->feed_url, 'feed_url' => $file->url, 'build' => SIMPLEPIE_BUILD);
  1507. if (!$cache->save($this))
  1508. {
  1509. trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
  1510. }
  1511. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, call_user_func($this->cache_name_function, $file->url), 'spc');
  1512. }
  1513. $this->feed_url = $file->url;
  1514. }
  1515. else
  1516. {
  1517. $this->error = "A feed could not be found at $this->feed_url";
  1518. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1519. return false;
  1520. }
  1521. }
  1522. $locate = null;
  1523. }
  1524. $headers = $file->headers;
  1525. $data = $file->body;
  1526. $sniffer = new $this->content_type_sniffer_class($file);
  1527. $sniffed = $sniffer->get_type();
  1528. }
  1529. else
  1530. {
  1531. $data = $this->raw_data;
  1532. }
  1533. // Set up array of possible encodings
  1534. $encodings = array();
  1535. // First check to see if input has been overridden.
  1536. if ($this->input_encoding !== false)
  1537. {
  1538. $encodings[] = $this->input_encoding;
  1539. }
  1540. $application_types = array('application/xml', 'application/xml-dtd', 'application/xml-external-parsed-entity');
  1541. $text_types = array('text/xml', 'text/xml-external-parsed-entity');
  1542. // RFC 3023 (only applies to sniffed content)
  1543. if (isset($sniffed))
  1544. {
  1545. if (in_array($sniffed, $application_types) || substr($sniffed, 0, 12) === 'application/' && substr($sniffed, -4) === '+xml')
  1546. {
  1547. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1548. {
  1549. $encodings[] = strtoupper($charset[1]);
  1550. }
  1551. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  1552. $encodings[] = 'UTF-8';
  1553. }
  1554. elseif (in_array($sniffed, $text_types) || substr($sniffed, 0, 5) === 'text/' && substr($sniffed, -4) === '+xml')
  1555. {
  1556. if (isset($headers['content-type']) && preg_match('/;\x20?charset=([^;]*)/i', $headers['content-type'], $charset))
  1557. {
  1558. $encodings[] = $charset[1];
  1559. }
  1560. $encodings[] = 'US-ASCII';
  1561. }
  1562. // Text MIME-type default
  1563. elseif (substr($sniffed, 0, 5) === 'text/')
  1564. {
  1565. $encodings[] = 'US-ASCII';
  1566. }
  1567. }
  1568. // Fallback to XML 1.0 Appendix F.1/UTF-8/ISO-8859-1
  1569. $encodings = array_merge($encodings, SimplePie_Misc::xml_encoding($data));
  1570. $encodings[] = 'UTF-8';
  1571. $encodings[] = 'ISO-8859-1';
  1572. // There's no point in trying an encoding twice
  1573. $encodings = array_unique($encodings);
  1574. // If we want the XML, just output that with the most likely encoding and quit
  1575. if ($this->xml_dump)
  1576. {
  1577. header('Content-type: text/xml; charset=' . $encodings[0]);
  1578. echo $data;
  1579. exit;
  1580. }
  1581. // Loop through each possible encoding, till we return something, or run out of possibilities
  1582. foreach ($encodings as $encoding)
  1583. {
  1584. // Change the encoding to UTF-8 (as we always use UTF-8 internally)
  1585. if ($utf8_data = SimplePie_Misc::change_encoding($data, $encoding, 'UTF-8'))
  1586. {
  1587. // Create new parser
  1588. $parser = new $this->parser_class();
  1589. // If it's parsed fine
  1590. if ($parser->parse($utf8_data, 'UTF-8'))
  1591. {
  1592. $this->data = $parser->get_data();
  1593. if ($this->get_type() & ~SIMPLEPIE_TYPE_NONE)
  1594. {
  1595. if (isset($headers))
  1596. {
  1597. $this->data['headers'] = $headers;
  1598. }
  1599. $this->data['build'] = SIMPLEPIE_BUILD;
  1600. // Cache the file if caching is enabled
  1601. if ($cache && !$cache->save($this))
  1602. {
  1603. trigger_error("$cache->name is not writeable", E_USER_WARNING);
  1604. }
  1605. return true;
  1606. }
  1607. else
  1608. {
  1609. $this->error = "A feed could not be found at $this->feed_url";
  1610. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1611. return false;
  1612. }
  1613. }
  1614. }
  1615. }
  1616. if(isset($parser))
  1617. {
  1618. // We have an error, just set SimplePie_Misc::error to it and quit
  1619. $this->error = sprintf('XML error: %s at line %d, column %d', $parser->get_error_string(), $parser->get_current_line(), $parser->get_current_column());
  1620. }
  1621. else
  1622. {
  1623. $this->error = 'The data could not be converted to UTF-8';
  1624. }
  1625. SimplePie_Misc::error($this->error, E_USER_NOTICE, __FILE__, __LINE__);
  1626. return false;
  1627. }
  1628. elseif (!empty($this->multifeed_url))
  1629. {
  1630. $i = 0;
  1631. $success = 0;
  1632. $this->multifeed_objects = array();
  1633. foreach ($this->multifeed_url as $url)
  1634. {
  1635. if (SIMPLEPIE_PHP5)
  1636. {
  1637. // This keyword needs to defy coding standards for PHP4 compatibility
  1638. $this->multifeed_objects[$i] = clone($this);
  1639. }
  1640. else
  1641. {
  1642. $this->multifeed_objects[$i] = $this;
  1643. }
  1644. $this->multifeed_objects[$i]->set_feed_url($url);
  1645. $success |= $this->multifeed_objects[$i]->init();
  1646. $i++;
  1647. }
  1648. return (bool) $success;
  1649. }
  1650. else
  1651. {
  1652. return false;
  1653. }
  1654. }
  1655. /**
  1656. * Return the error message for the occured error
  1657. *
  1658. * @access public
  1659. * @return string Error message
  1660. */
  1661. function error()
  1662. {
  1663. return $this->error;
  1664. }
  1665. function get_encoding()
  1666. {
  1667. return $this->sanitize->output_encoding;
  1668. }
  1669. function handle_content_type($mime = 'text/html')
  1670. {
  1671. if (!headers_sent())
  1672. {
  1673. $header = "Content-type: $mime;";
  1674. if ($this->get_encoding())
  1675. {
  1676. $header .= ' charset=' . $this->get_encoding();
  1677. }
  1678. else
  1679. {
  1680. $header .= ' charset=UTF-8';
  1681. }
  1682. header($header);
  1683. }
  1684. }
  1685. function get_type()
  1686. {
  1687. if (!isset($this->data['type']))
  1688. {
  1689. $this->data['type'] = SIMPLEPIE_TYPE_ALL;
  1690. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed']))
  1691. {
  1692. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_10;
  1693. }
  1694. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed']))
  1695. {
  1696. $this->data['type'] &= SIMPLEPIE_TYPE_ATOM_03;
  1697. }
  1698. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF']))
  1699. {
  1700. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['channel'])
  1701. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['image'])
  1702. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item'])
  1703. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_10]['textinput']))
  1704. {
  1705. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_10;
  1706. }
  1707. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['channel'])
  1708. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['image'])
  1709. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item'])
  1710. || isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_090]['textinput']))
  1711. {
  1712. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_090;
  1713. }
  1714. }
  1715. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss']))
  1716. {
  1717. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_ALL;
  1718. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1719. {
  1720. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['attribs']['']['version']))
  1721. {
  1722. case '0.91':
  1723. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091;
  1724. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1725. {
  1726. switch (trim($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['skiphours']['hour'][0]['data']))
  1727. {
  1728. case '0':
  1729. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_NETSCAPE;
  1730. break;
  1731. case '24':
  1732. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_091_USERLAND;
  1733. break;
  1734. }
  1735. }
  1736. break;
  1737. case '0.92':
  1738. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_092;
  1739. break;
  1740. case '0.93':
  1741. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_093;
  1742. break;
  1743. case '0.94':
  1744. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_094;
  1745. break;
  1746. case '2.0':
  1747. $this->data['type'] &= SIMPLEPIE_TYPE_RSS_20;
  1748. break;
  1749. }
  1750. }
  1751. }
  1752. else
  1753. {
  1754. $this->data['type'] = SIMPLEPIE_TYPE_NONE;
  1755. }
  1756. }
  1757. return $this->data['type'];
  1758. }
  1759. /**
  1760. * Returns the URL for the favicon of the feed's website.
  1761. *
  1762. * @todo Cache atom:icon
  1763. * @access public
  1764. * @since 1.0
  1765. */
  1766. function get_favicon()
  1767. {
  1768. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  1769. {
  1770. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  1771. }
  1772. elseif (($url = $this->get_link()) !== null && preg_match('/^http(s)?:\/\//i', $url))
  1773. {
  1774. $favicon = SimplePie_Misc::absolutize_url('/favicon.ico', $url);
  1775. if ($this->cache && $this->favicon_handler)
  1776. {
  1777. $favicon_filename = call_user_func($this->cache_name_function, $favicon);
  1778. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $favicon_filename, 'spi');
  1779. if ($cache->load())
  1780. {
  1781. return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
  1782. }
  1783. else
  1784. {
  1785. $file = new $this->file_class($favicon, $this->timeout / 10, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
  1786. if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)) && strlen($file->body) > 0)
  1787. {
  1788. $sniffer = new $this->content_type_sniffer_class($file);
  1789. if (substr($sniffer->get_type(), 0, 6) === 'image/')
  1790. {
  1791. if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
  1792. {
  1793. return $this->sanitize($this->favicon_handler . $favicon_filename, SIMPLEPIE_CONSTRUCT_IRI);
  1794. }
  1795. else
  1796. {
  1797. trigger_error("$cache->name is not writeable", E_USER_WARNING);
  1798. return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
  1799. }
  1800. }
  1801. // not an image
  1802. else
  1803. {
  1804. return false;
  1805. }
  1806. }
  1807. }
  1808. }
  1809. else
  1810. {
  1811. return $this->sanitize($favicon, SIMPLEPIE_CONSTRUCT_IRI);
  1812. }
  1813. }
  1814. return false;
  1815. }
  1816. /**
  1817. * @todo If we have a perm redirect we should return the new URL
  1818. * @todo When we make the above change, let's support <itunes:new-feed-url> as well
  1819. * @todo Also, |atom:link|@rel=self
  1820. */
  1821. function subscribe_url()
  1822. {
  1823. if ($this->feed_url !== null)
  1824. {
  1825. return $this->sanitize($this->feed_url, SIMPLEPIE_CONSTRUCT_IRI);
  1826. }
  1827. else
  1828. {
  1829. return null;
  1830. }
  1831. }
  1832. function subscribe_feed()
  1833. {
  1834. if ($this->feed_url !== null)
  1835. {
  1836. return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
  1837. }
  1838. else
  1839. {
  1840. return null;
  1841. }
  1842. }
  1843. function subscribe_outlook()
  1844. {
  1845. if ($this->feed_url !== null)
  1846. {
  1847. return $this->sanitize('outlook' . SimplePie_Misc::fix_protocol($this->feed_url, 2), SIMPLEPIE_CONSTRUCT_IRI);
  1848. }
  1849. else
  1850. {
  1851. return null;
  1852. }
  1853. }
  1854. function subscribe_podcast()
  1855. {
  1856. if ($this->feed_url !== null)
  1857. {
  1858. return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 3), SIMPLEPIE_CONSTRUCT_IRI);
  1859. }
  1860. else
  1861. {
  1862. return null;
  1863. }
  1864. }
  1865. function subscribe_itunes()
  1866. {
  1867. if ($this->feed_url !== null)
  1868. {
  1869. return $this->sanitize(SimplePie_Misc::fix_protocol($this->feed_url, 4), SIMPLEPIE_CONSTRUCT_IRI);
  1870. }
  1871. else
  1872. {
  1873. return null;
  1874. }
  1875. }
  1876. /**
  1877. * Creates the subscribe_* methods' return data
  1878. *
  1879. * @access private
  1880. * @param string $feed_url String to prefix to the feed URL
  1881. * @param string $site_url String to prefix to the site URL (and
  1882. * suffix to the feed URL)
  1883. * @return mixed URL if feed exists, false otherwise
  1884. */
  1885. function subscribe_service($feed_url, $site_url = null)
  1886. {
  1887. if ($this->subscribe_url())
  1888. {
  1889. $return = $feed_url . rawurlencode($this->feed_url);
  1890. if ($site_url !== null && $this->get_link() !== null)
  1891. {
  1892. $return .= $site_url . rawurlencode($this->get_link());
  1893. }
  1894. return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
  1895. }
  1896. else
  1897. {
  1898. return null;
  1899. }
  1900. }
  1901. function subscribe_aol()
  1902. {
  1903. return $this->subscribe_service('http://feeds.my.aol.com/add.jsp?url=');
  1904. }
  1905. function subscribe_bloglines()
  1906. {
  1907. return $this->subscribe_service('http://www.bloglines.com/sub/');
  1908. }
  1909. function subscribe_eskobo()
  1910. {
  1911. return $this->subscribe_service('http://www.eskobo.com/?AddToMyPage=');
  1912. }
  1913. function subscribe_feedfeeds()
  1914. {
  1915. return $this->subscribe_service('http://www.feedfeeds.com/add?feed=');
  1916. }
  1917. function subscribe_feedster()
  1918. {
  1919. return $this->subscribe_service('http://www.feedster.com/myfeedster.php?action=addrss&confirm=no&rssurl=');
  1920. }
  1921. function subscribe_google()
  1922. {
  1923. return $this->subscribe_service('http://fusion.google.com/add?feedurl=');
  1924. }
  1925. function subscribe_gritwire()
  1926. {
  1927. return $this->subscribe_service('http://my.gritwire.com/feeds/addExternalFeed.aspx?FeedUrl=');
  1928. }
  1929. function subscribe_msn()
  1930. {
  1931. return $this->subscribe_service('http://my.msn.com/addtomymsn.armx?id=rss&ut=', '&ru=');
  1932. }
  1933. function subscribe_netvibes()
  1934. {
  1935. return $this->subscribe_service('http://www.netvibes.com/subscribe.php?url=');
  1936. }
  1937. function subscribe_newsburst()
  1938. {
  1939. return $this->subscribe_service('http://www.newsburst.com/Source/?add=');
  1940. }
  1941. function subscribe_newsgator()
  1942. {
  1943. return $this->subscribe_service('http://www.newsgator.com/ngs/subscriber/subext.aspx?url=');
  1944. }
  1945. function subscribe_odeo()
  1946. {
  1947. return $this->subscribe_service('http://www.odeo.com/listen/subscribe?feed=');
  1948. }
  1949. function subscribe_podnova()
  1950. {
  1951. return $this->subscribe_service('http://www.podnova.com/index_your_podcasts.srf?action=add&url=');
  1952. }
  1953. function subscribe_rojo()
  1954. {
  1955. return $this->subscribe_service('http://www.rojo.com/add-subscription?resource=');
  1956. }
  1957. function subscribe_yahoo()
  1958. {
  1959. return $this->subscribe_service('http://add.my.yahoo.com/rss?url=');
  1960. }
  1961. function get_feed_tags($namespace, $tag)
  1962. {
  1963. $type = $this->get_type();
  1964. if ($type & SIMPLEPIE_TYPE_ATOM_10)
  1965. {
  1966. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag]))
  1967. {
  1968. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['child'][$namespace][$tag];
  1969. }
  1970. }
  1971. if ($type & SIMPLEPIE_TYPE_ATOM_03)
  1972. {
  1973. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag]))
  1974. {
  1975. return $this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['child'][$namespace][$tag];
  1976. }
  1977. }
  1978. if ($type & SIMPLEPIE_TYPE_RSS_RDF)
  1979. {
  1980. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag]))
  1981. {
  1982. return $this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['child'][$namespace][$tag];
  1983. }
  1984. }
  1985. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  1986. {
  1987. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag]))
  1988. {
  1989. return $this->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][$namespace][$tag];
  1990. }
  1991. }
  1992. return null;
  1993. }
  1994. function get_channel_tags($namespace, $tag)
  1995. {
  1996. $type = $this->get_type();
  1997. if ($type & SIMPLEPIE_TYPE_ATOM_ALL)
  1998. {
  1999. if ($return = $this->get_feed_tags($namespace, $tag))
  2000. {
  2001. return $return;
  2002. }
  2003. }
  2004. if ($type & SIMPLEPIE_TYPE_RSS_10)
  2005. {
  2006. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'channel'))
  2007. {
  2008. if (isset($channel[0]['child'][$namespace][$tag]))
  2009. {
  2010. return $channel[0]['child'][$namespace][$tag];
  2011. }
  2012. }
  2013. }
  2014. if ($type & SIMPLEPIE_TYPE_RSS_090)
  2015. {
  2016. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'channel'))
  2017. {
  2018. if (isset($channel[0]['child'][$namespace][$tag]))
  2019. {
  2020. return $channel[0]['child'][$namespace][$tag];
  2021. }
  2022. }
  2023. }
  2024. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  2025. {
  2026. if ($channel = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'channel'))
  2027. {
  2028. if (isset($channel[0]['child'][$namespace][$tag]))
  2029. {
  2030. return $channel[0]['child'][$namespace][$tag];
  2031. }
  2032. }
  2033. }
  2034. return null;
  2035. }
  2036. function get_image_tags($namespace, $tag)
  2037. {
  2038. $type = $this->get_type();
  2039. if ($type & SIMPLEPIE_TYPE_RSS_10)
  2040. {
  2041. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'image'))
  2042. {
  2043. if (isset($image[0]['child'][$namespace][$tag]))
  2044. {
  2045. return $image[0]['child'][$namespace][$tag];
  2046. }
  2047. }
  2048. }
  2049. if ($type & SIMPLEPIE_TYPE_RSS_090)
  2050. {
  2051. if ($image = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'image'))
  2052. {
  2053. if (isset($image[0]['child'][$namespace][$tag]))
  2054. {
  2055. return $image[0]['child'][$namespace][$tag];
  2056. }
  2057. }
  2058. }
  2059. if ($type & SIMPLEPIE_TYPE_RSS_SYNDICATION)
  2060. {
  2061. if ($image = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'image'))
  2062. {
  2063. if (isset($image[0]['child'][$namespace][$tag]))
  2064. {
  2065. return $image[0]['child'][$namespace][$tag];
  2066. }
  2067. }
  2068. }
  2069. return null;
  2070. }
  2071. function get_base($element = array())
  2072. {
  2073. if (!($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION) && !empty($element['xml_base_explicit']) && isset($element['xml_base']))
  2074. {
  2075. return $element['xml_base'];
  2076. }
  2077. elseif ($this->get_link() !== null)
  2078. {
  2079. return $this->get_link();
  2080. }
  2081. else
  2082. {
  2083. return $this->subscribe_url();
  2084. }
  2085. }
  2086. function sanitize($data, $type, $base = '')
  2087. {
  2088. return $this->sanitize->sanitize($data, $type, $base);
  2089. }
  2090. function get_title()
  2091. {
  2092. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  2093. {
  2094. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2095. }
  2096. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  2097. {
  2098. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2099. }
  2100. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2101. {
  2102. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2103. }
  2104. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2105. {
  2106. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2107. }
  2108. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2109. {
  2110. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2111. }
  2112. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2113. {
  2114. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2115. }
  2116. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2117. {
  2118. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2119. }
  2120. else
  2121. {
  2122. return null;
  2123. }
  2124. }
  2125. function get_category($key = 0)
  2126. {
  2127. $categories = $this->get_categories();
  2128. if (isset($categories[$key]))
  2129. {
  2130. return $categories[$key];
  2131. }
  2132. else
  2133. {
  2134. return null;
  2135. }
  2136. }
  2137. function get_categories()
  2138. {
  2139. $categories = array();
  2140. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  2141. {
  2142. $term = null;
  2143. $scheme = null;
  2144. $label = null;
  2145. if (isset($category['attribs']['']['term']))
  2146. {
  2147. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  2148. }
  2149. if (isset($category['attribs']['']['scheme']))
  2150. {
  2151. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  2152. }
  2153. if (isset($category['attribs']['']['label']))
  2154. {
  2155. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  2156. }
  2157. $categories[] = new $this->category_class($term, $scheme, $label);
  2158. }
  2159. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  2160. {
  2161. // This is really the label, but keep this as the term also for BC.
  2162. // Label will also work on retrieving because that falls back to term.
  2163. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2164. if (isset($category['attribs']['']['domain']))
  2165. {
  2166. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  2167. }
  2168. else
  2169. {
  2170. $scheme = null;
  2171. }
  2172. $categories[] = new $this->category_class($term, $scheme, null);
  2173. }
  2174. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  2175. {
  2176. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2177. }
  2178. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  2179. {
  2180. $categories[] = new $this->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2181. }
  2182. if (!empty($categories))
  2183. {
  2184. return SimplePie_Misc::array_unique($categories);
  2185. }
  2186. else
  2187. {
  2188. return null;
  2189. }
  2190. }
  2191. function get_author($key = 0)
  2192. {
  2193. $authors = $this->get_authors();
  2194. if (isset($authors[$key]))
  2195. {
  2196. return $authors[$key];
  2197. }
  2198. else
  2199. {
  2200. return null;
  2201. }
  2202. }
  2203. function get_authors()
  2204. {
  2205. $authors = array();
  2206. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  2207. {
  2208. $name = null;
  2209. $uri = null;
  2210. $email = null;
  2211. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2212. {
  2213. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2214. }
  2215. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2216. {
  2217. $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]));
  2218. }
  2219. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2220. {
  2221. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2222. }
  2223. if ($name !== null || $email !== null || $uri !== null)
  2224. {
  2225. $authors[] = new $this->author_class($name, $uri, $email);
  2226. }
  2227. }
  2228. if ($author = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  2229. {
  2230. $name = null;
  2231. $url = null;
  2232. $email = null;
  2233. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2234. {
  2235. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2236. }
  2237. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2238. {
  2239. $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]));
  2240. }
  2241. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2242. {
  2243. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2244. }
  2245. if ($name !== null || $email !== null || $url !== null)
  2246. {
  2247. $authors[] = new $this->author_class($name, $url, $email);
  2248. }
  2249. }
  2250. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  2251. {
  2252. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2253. }
  2254. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  2255. {
  2256. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2257. }
  2258. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  2259. {
  2260. $authors[] = new $this->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  2261. }
  2262. if (!empty($authors))
  2263. {
  2264. return SimplePie_Misc::array_unique($authors);
  2265. }
  2266. else
  2267. {
  2268. return null;
  2269. }
  2270. }
  2271. function get_contributor($key = 0)
  2272. {
  2273. $contributors = $this->get_contributors();
  2274. if (isset($contributors[$key]))
  2275. {
  2276. return $contributors[$key];
  2277. }
  2278. else
  2279. {
  2280. return null;
  2281. }
  2282. }
  2283. function get_contributors()
  2284. {
  2285. $contributors = array();
  2286. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  2287. {
  2288. $name = null;
  2289. $uri = null;
  2290. $email = null;
  2291. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  2292. {
  2293. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2294. }
  2295. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  2296. {
  2297. $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]));
  2298. }
  2299. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  2300. {
  2301. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2302. }
  2303. if ($name !== null || $email !== null || $uri !== null)
  2304. {
  2305. $contributors[] = new $this->author_class($name, $uri, $email);
  2306. }
  2307. }
  2308. foreach ((array) $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  2309. {
  2310. $name = null;
  2311. $url = null;
  2312. $email = null;
  2313. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  2314. {
  2315. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2316. }
  2317. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  2318. {
  2319. $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]));
  2320. }
  2321. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  2322. {
  2323. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2324. }
  2325. if ($name !== null || $email !== null || $url !== null)
  2326. {
  2327. $contributors[] = new $this->author_class($name, $url, $email);
  2328. }
  2329. }
  2330. if (!empty($contributors))
  2331. {
  2332. return SimplePie_Misc::array_unique($contributors);
  2333. }
  2334. else
  2335. {
  2336. return null;
  2337. }
  2338. }
  2339. function get_link($key = 0, $rel = 'alternate')
  2340. {
  2341. $links = $this->get_links($rel);
  2342. if (isset($links[$key]))
  2343. {
  2344. return $links[$key];
  2345. }
  2346. else
  2347. {
  2348. return null;
  2349. }
  2350. }
  2351. /**
  2352. * Added for parity between the parent-level and the item/entry-level.
  2353. */
  2354. function get_permalink()
  2355. {
  2356. return $this->get_link(0);
  2357. }
  2358. function get_links($rel = 'alternate')
  2359. {
  2360. if (!isset($this->data['links']))
  2361. {
  2362. $this->data['links'] = array();
  2363. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  2364. {
  2365. foreach ($links as $link)
  2366. {
  2367. if (isset($link['attribs']['']['href']))
  2368. {
  2369. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2370. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2371. }
  2372. }
  2373. }
  2374. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  2375. {
  2376. foreach ($links as $link)
  2377. {
  2378. if (isset($link['attribs']['']['href']))
  2379. {
  2380. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  2381. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  2382. }
  2383. }
  2384. }
  2385. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2386. {
  2387. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2388. }
  2389. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2390. {
  2391. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2392. }
  2393. if ($links = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2394. {
  2395. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  2396. }
  2397. $keys = array_keys($this->data['links']);
  2398. foreach ($keys as $key)
  2399. {
  2400. if (SimplePie_Misc::is_isegment_nz_nc($key))
  2401. {
  2402. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  2403. {
  2404. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  2405. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  2406. }
  2407. else
  2408. {
  2409. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  2410. }
  2411. }
  2412. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  2413. {
  2414. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  2415. }
  2416. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  2417. }
  2418. }
  2419. if (isset($this->data['links'][$rel]))
  2420. {
  2421. return $this->data['links'][$rel];
  2422. }
  2423. else
  2424. {
  2425. return null;
  2426. }
  2427. }
  2428. function get_all_discovered_feeds()
  2429. {
  2430. return $this->all_discovered_feeds;
  2431. }
  2432. function get_description()
  2433. {
  2434. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  2435. {
  2436. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2437. }
  2438. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  2439. {
  2440. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2441. }
  2442. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2443. {
  2444. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2445. }
  2446. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  2447. {
  2448. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2449. }
  2450. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2451. {
  2452. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2453. }
  2454. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  2455. {
  2456. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2457. }
  2458. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  2459. {
  2460. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2461. }
  2462. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  2463. {
  2464. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2465. }
  2466. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  2467. {
  2468. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  2469. }
  2470. else
  2471. {
  2472. return null;
  2473. }
  2474. }
  2475. function get_copyright()
  2476. {
  2477. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  2478. {
  2479. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2480. }
  2481. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  2482. {
  2483. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2484. }
  2485. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  2486. {
  2487. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2488. }
  2489. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  2490. {
  2491. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2492. }
  2493. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  2494. {
  2495. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2496. }
  2497. else
  2498. {
  2499. return null;
  2500. }
  2501. }
  2502. function get_language()
  2503. {
  2504. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  2505. {
  2506. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2507. }
  2508. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  2509. {
  2510. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2511. }
  2512. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  2513. {
  2514. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2515. }
  2516. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang']))
  2517. {
  2518. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2519. }
  2520. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang']))
  2521. {
  2522. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2523. }
  2524. elseif (isset($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang']))
  2525. {
  2526. return $this->sanitize($this->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  2527. }
  2528. elseif (isset($this->data['headers']['content-language']))
  2529. {
  2530. return $this->sanitize($this->data['headers']['content-language'], SIMPLEPIE_CONSTRUCT_TEXT);
  2531. }
  2532. else
  2533. {
  2534. return null;
  2535. }
  2536. }
  2537. function get_latitude()
  2538. {
  2539. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  2540. {
  2541. return (float) $return[0]['data'];
  2542. }
  2543. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  2544. {
  2545. return (float) $match[1];
  2546. }
  2547. else
  2548. {
  2549. return null;
  2550. }
  2551. }
  2552. function get_longitude()
  2553. {
  2554. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  2555. {
  2556. return (float) $return[0]['data'];
  2557. }
  2558. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  2559. {
  2560. return (float) $return[0]['data'];
  2561. }
  2562. elseif (($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  2563. {
  2564. return (float) $match[2];
  2565. }
  2566. else
  2567. {
  2568. return null;
  2569. }
  2570. }
  2571. function get_image_title()
  2572. {
  2573. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2574. {
  2575. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2576. }
  2577. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2578. {
  2579. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2580. }
  2581. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2582. {
  2583. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2584. }
  2585. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2586. {
  2587. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2588. }
  2589. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2590. {
  2591. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2592. }
  2593. else
  2594. {
  2595. return null;
  2596. }
  2597. }
  2598. function get_image_url()
  2599. {
  2600. if ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  2601. {
  2602. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  2603. }
  2604. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  2605. {
  2606. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2607. }
  2608. elseif ($return = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  2609. {
  2610. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2611. }
  2612. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'url'))
  2613. {
  2614. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2615. }
  2616. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'url'))
  2617. {
  2618. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2619. }
  2620. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2621. {
  2622. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2623. }
  2624. else
  2625. {
  2626. return null;
  2627. }
  2628. }
  2629. function get_image_link()
  2630. {
  2631. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  2632. {
  2633. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2634. }
  2635. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  2636. {
  2637. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2638. }
  2639. elseif ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  2640. {
  2641. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  2642. }
  2643. else
  2644. {
  2645. return null;
  2646. }
  2647. }
  2648. function get_image_width()
  2649. {
  2650. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'width'))
  2651. {
  2652. return round($return[0]['data']);
  2653. }
  2654. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2655. {
  2656. return 88.0;
  2657. }
  2658. else
  2659. {
  2660. return null;
  2661. }
  2662. }
  2663. function get_image_height()
  2664. {
  2665. if ($return = $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'height'))
  2666. {
  2667. return round($return[0]['data']);
  2668. }
  2669. elseif ($this->get_type() & SIMPLEPIE_TYPE_RSS_SYNDICATION && $this->get_image_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'url'))
  2670. {
  2671. return 31.0;
  2672. }
  2673. else
  2674. {
  2675. return null;
  2676. }
  2677. }
  2678. function get_item_quantity($max = 0)
  2679. {
  2680. $max = (int) $max;
  2681. $qty = count($this->get_items());
  2682. if ($max === 0)
  2683. {
  2684. return $qty;
  2685. }
  2686. else
  2687. {
  2688. return ($qty > $max) ? $max : $qty;
  2689. }
  2690. }
  2691. function get_item($key = 0)
  2692. {
  2693. $items = $this->get_items();
  2694. if (isset($items[$key]))
  2695. {
  2696. return $items[$key];
  2697. }
  2698. else
  2699. {
  2700. return null;
  2701. }
  2702. }
  2703. function get_items($start = 0, $end = 0)
  2704. {
  2705. if (!isset($this->data['items']))
  2706. {
  2707. if (!empty($this->multifeed_objects))
  2708. {
  2709. $this->data['items'] = SimplePie::merge_items($this->multifeed_objects, $start, $end, $this->item_limit);
  2710. }
  2711. else
  2712. {
  2713. $this->data['items'] = array();
  2714. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'entry'))
  2715. {
  2716. $keys = array_keys($items);
  2717. foreach ($keys as $key)
  2718. {
  2719. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2720. }
  2721. }
  2722. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'entry'))
  2723. {
  2724. $keys = array_keys($items);
  2725. foreach ($keys as $key)
  2726. {
  2727. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2728. }
  2729. }
  2730. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'item'))
  2731. {
  2732. $keys = array_keys($items);
  2733. foreach ($keys as $key)
  2734. {
  2735. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2736. }
  2737. }
  2738. if ($items = $this->get_feed_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'item'))
  2739. {
  2740. $keys = array_keys($items);
  2741. foreach ($keys as $key)
  2742. {
  2743. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2744. }
  2745. }
  2746. if ($items = $this->get_channel_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'item'))
  2747. {
  2748. $keys = array_keys($items);
  2749. foreach ($keys as $key)
  2750. {
  2751. $this->data['items'][] = new $this->item_class($this, $items[$key]);
  2752. }
  2753. }
  2754. }
  2755. }
  2756. if (!empty($this->data['items']))
  2757. {
  2758. // If we want to order it by date, check if all items have a date, and then sort it
  2759. if ($this->order_by_date && empty($this->multifeed_objects))
  2760. {
  2761. if (!isset($this->data['ordered_items']))
  2762. {
  2763. $do_sort = true;
  2764. foreach ($this->data['items'] as $item)
  2765. {
  2766. if (!$item->get_date('U'))
  2767. {
  2768. $do_sort = false;
  2769. break;
  2770. }
  2771. }
  2772. $item = null;
  2773. $this->data['ordered_items'] = $this->data['items'];
  2774. if ($do_sort)
  2775. {
  2776. usort($this->data['ordered_items'], array(&$this, 'sort_items'));
  2777. }
  2778. }
  2779. $items = $this->data['ordered_items'];
  2780. }
  2781. else
  2782. {
  2783. $items = $this->data['items'];
  2784. }
  2785. // Slice the data as desired
  2786. if ($end === 0)
  2787. {
  2788. return array_slice($items, $start);
  2789. }
  2790. else
  2791. {
  2792. return array_slice($items, $start, $end);
  2793. }
  2794. }
  2795. else
  2796. {
  2797. return array();
  2798. }
  2799. }
  2800. /**
  2801. * @static
  2802. */
  2803. function sort_items($a, $b)
  2804. {
  2805. return $a->get_date('U') <= $b->get_date('U');
  2806. }
  2807. /**
  2808. * @static
  2809. */
  2810. function merge_items($urls, $start = 0, $end = 0, $limit = 0)
  2811. {
  2812. if (is_array($urls) && sizeof($urls) > 0)
  2813. {
  2814. $items = array();
  2815. foreach ($urls as $arg)
  2816. {
  2817. if (is_a($arg, 'SimplePie'))
  2818. {
  2819. $items = array_merge($items, $arg->get_items(0, $limit));
  2820. }
  2821. else
  2822. {
  2823. trigger_error('Arguments must be SimplePie objects', E_USER_WARNING);
  2824. }
  2825. }
  2826. $do_sort = true;
  2827. foreach ($items as $item)
  2828. {
  2829. if (!$item->get_date('U'))
  2830. {
  2831. $do_sort = false;
  2832. break;
  2833. }
  2834. }
  2835. $item = null;
  2836. if ($do_sort)
  2837. {
  2838. usort($items, array('SimplePie', 'sort_items'));
  2839. }
  2840. if ($end === 0)
  2841. {
  2842. return array_slice($items, $start);
  2843. }
  2844. else
  2845. {
  2846. return array_slice($items, $start, $end);
  2847. }
  2848. }
  2849. else
  2850. {
  2851. trigger_error('Cannot merge zero SimplePie objects', E_USER_WARNING);
  2852. return array();
  2853. }
  2854. }
  2855. }
  2856. class SimplePie_Item
  2857. {
  2858. var $feed;
  2859. var $data = array();
  2860. function SimplePie_Item($feed, $data)
  2861. {
  2862. $this->feed = $feed;
  2863. $this->data = $data;
  2864. }
  2865. function __toString()
  2866. {
  2867. return md5(serialize($this->data));
  2868. }
  2869. /**
  2870. * Remove items that link back to this before destroying this object
  2871. */
  2872. function __destruct()
  2873. {
  2874. if ((version_compare(PHP_VERSION, '5.3', '<') || !gc_enabled()) && !ini_get('zend.ze1_compatibility_mode'))
  2875. {
  2876. unset($this->feed);
  2877. }
  2878. }
  2879. function get_item_tags($namespace, $tag)
  2880. {
  2881. if (isset($this->data['child'][$namespace][$tag]))
  2882. {
  2883. return $this->data['child'][$namespace][$tag];
  2884. }
  2885. else
  2886. {
  2887. return null;
  2888. }
  2889. }
  2890. function get_base($element = array())
  2891. {
  2892. return $this->feed->get_base($element);
  2893. }
  2894. function sanitize($data, $type, $base = '')
  2895. {
  2896. return $this->feed->sanitize($data, $type, $base);
  2897. }
  2898. function get_feed()
  2899. {
  2900. return $this->feed;
  2901. }
  2902. function get_id($hash = false)
  2903. {
  2904. if (!$hash)
  2905. {
  2906. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'id'))
  2907. {
  2908. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2909. }
  2910. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'id'))
  2911. {
  2912. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2913. }
  2914. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  2915. {
  2916. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2917. }
  2918. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'identifier'))
  2919. {
  2920. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2921. }
  2922. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'identifier'))
  2923. {
  2924. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2925. }
  2926. elseif (($return = $this->get_permalink()) !== null)
  2927. {
  2928. return $return;
  2929. }
  2930. elseif (($return = $this->get_title()) !== null)
  2931. {
  2932. return $return;
  2933. }
  2934. }
  2935. if ($this->get_permalink() !== null || $this->get_title() !== null)
  2936. {
  2937. return md5($this->get_permalink() . $this->get_title());
  2938. }
  2939. else
  2940. {
  2941. return md5(serialize($this->data));
  2942. }
  2943. }
  2944. function get_title()
  2945. {
  2946. if (!isset($this->data['title']))
  2947. {
  2948. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  2949. {
  2950. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2951. }
  2952. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  2953. {
  2954. $this->data['title'] = $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2955. }
  2956. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  2957. {
  2958. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2959. }
  2960. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  2961. {
  2962. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2963. }
  2964. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  2965. {
  2966. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2967. }
  2968. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  2969. {
  2970. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2971. }
  2972. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  2973. {
  2974. $this->data['title'] = $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  2975. }
  2976. else
  2977. {
  2978. $this->data['title'] = null;
  2979. }
  2980. }
  2981. return $this->data['title'];
  2982. }
  2983. function get_description($description_only = false)
  2984. {
  2985. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'summary'))
  2986. {
  2987. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2988. }
  2989. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'summary'))
  2990. {
  2991. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  2992. }
  2993. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  2994. {
  2995. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  2996. }
  2997. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  2998. {
  2999. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3000. }
  3001. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  3002. {
  3003. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3004. }
  3005. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  3006. {
  3007. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3008. }
  3009. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  3010. {
  3011. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3012. }
  3013. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  3014. {
  3015. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3016. }
  3017. elseif (!$description_only)
  3018. {
  3019. return $this->get_content(true);
  3020. }
  3021. else
  3022. {
  3023. return null;
  3024. }
  3025. }
  3026. function get_content($content_only = false)
  3027. {
  3028. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'content'))
  3029. {
  3030. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_content_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3031. }
  3032. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'content'))
  3033. {
  3034. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3035. }
  3036. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10_MODULES_CONTENT, 'encoded'))
  3037. {
  3038. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  3039. }
  3040. elseif (!$content_only)
  3041. {
  3042. return $this->get_description(true);
  3043. }
  3044. else
  3045. {
  3046. return null;
  3047. }
  3048. }
  3049. function get_category($key = 0)
  3050. {
  3051. $categories = $this->get_categories();
  3052. if (isset($categories[$key]))
  3053. {
  3054. return $categories[$key];
  3055. }
  3056. else
  3057. {
  3058. return null;
  3059. }
  3060. }
  3061. function get_categories()
  3062. {
  3063. $categories = array();
  3064. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  3065. {
  3066. $term = null;
  3067. $scheme = null;
  3068. $label = null;
  3069. if (isset($category['attribs']['']['term']))
  3070. {
  3071. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  3072. }
  3073. if (isset($category['attribs']['']['scheme']))
  3074. {
  3075. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3076. }
  3077. if (isset($category['attribs']['']['label']))
  3078. {
  3079. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  3080. }
  3081. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  3082. }
  3083. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  3084. {
  3085. // This is really the label, but keep this as the term also for BC.
  3086. // Label will also work on retrieving because that falls back to term.
  3087. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3088. if (isset($category['attribs']['']['domain']))
  3089. {
  3090. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  3091. }
  3092. else
  3093. {
  3094. $scheme = null;
  3095. }
  3096. $categories[] = new $this->feed->category_class($term, $scheme, null);
  3097. }
  3098. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  3099. {
  3100. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3101. }
  3102. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  3103. {
  3104. $categories[] = new $this->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3105. }
  3106. if (!empty($categories))
  3107. {
  3108. return SimplePie_Misc::array_unique($categories);
  3109. }
  3110. else
  3111. {
  3112. return null;
  3113. }
  3114. }
  3115. function get_author($key = 0)
  3116. {
  3117. $authors = $this->get_authors();
  3118. if (isset($authors[$key]))
  3119. {
  3120. return $authors[$key];
  3121. }
  3122. else
  3123. {
  3124. return null;
  3125. }
  3126. }
  3127. function get_contributor($key = 0)
  3128. {
  3129. $contributors = $this->get_contributors();
  3130. if (isset($contributors[$key]))
  3131. {
  3132. return $contributors[$key];
  3133. }
  3134. else
  3135. {
  3136. return null;
  3137. }
  3138. }
  3139. function get_contributors()
  3140. {
  3141. $contributors = array();
  3142. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  3143. {
  3144. $name = null;
  3145. $uri = null;
  3146. $email = null;
  3147. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  3148. {
  3149. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3150. }
  3151. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  3152. {
  3153. $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]));
  3154. }
  3155. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  3156. {
  3157. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3158. }
  3159. if ($name !== null || $email !== null || $uri !== null)
  3160. {
  3161. $contributors[] = new $this->feed->author_class($name, $uri, $email);
  3162. }
  3163. }
  3164. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  3165. {
  3166. $name = null;
  3167. $url = null;
  3168. $email = null;
  3169. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  3170. {
  3171. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3172. }
  3173. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  3174. {
  3175. $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]));
  3176. }
  3177. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  3178. {
  3179. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3180. }
  3181. if ($name !== null || $email !== null || $url !== null)
  3182. {
  3183. $contributors[] = new $this->feed->author_class($name, $url, $email);
  3184. }
  3185. }
  3186. if (!empty($contributors))
  3187. {
  3188. return SimplePie_Misc::array_unique($contributors);
  3189. }
  3190. else
  3191. {
  3192. return null;
  3193. }
  3194. }
  3195. function get_authors()
  3196. {
  3197. $authors = array();
  3198. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  3199. {
  3200. $name = null;
  3201. $uri = null;
  3202. $email = null;
  3203. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  3204. {
  3205. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3206. }
  3207. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  3208. {
  3209. $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]));
  3210. }
  3211. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  3212. {
  3213. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3214. }
  3215. if ($name !== null || $email !== null || $uri !== null)
  3216. {
  3217. $authors[] = new $this->feed->author_class($name, $uri, $email);
  3218. }
  3219. }
  3220. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  3221. {
  3222. $name = null;
  3223. $url = null;
  3224. $email = null;
  3225. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  3226. {
  3227. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3228. }
  3229. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  3230. {
  3231. $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]));
  3232. }
  3233. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  3234. {
  3235. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3236. }
  3237. if ($name !== null || $email !== null || $url !== null)
  3238. {
  3239. $authors[] = new $this->feed->author_class($name, $url, $email);
  3240. }
  3241. }
  3242. if ($author = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'author'))
  3243. {
  3244. $authors[] = new $this->feed->author_class(null, null, $this->sanitize($author[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3245. }
  3246. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  3247. {
  3248. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3249. }
  3250. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  3251. {
  3252. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3253. }
  3254. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  3255. {
  3256. $authors[] = new $this->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  3257. }
  3258. if (!empty($authors))
  3259. {
  3260. return SimplePie_Misc::array_unique($authors);
  3261. }
  3262. elseif (($source = $this->get_source()) && ($authors = $source->get_authors()))
  3263. {
  3264. return $authors;
  3265. }
  3266. elseif ($authors = $this->feed->get_authors())
  3267. {
  3268. return $authors;
  3269. }
  3270. else
  3271. {
  3272. return null;
  3273. }
  3274. }
  3275. function get_copyright()
  3276. {
  3277. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  3278. {
  3279. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  3280. }
  3281. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  3282. {
  3283. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3284. }
  3285. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  3286. {
  3287. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3288. }
  3289. else
  3290. {
  3291. return null;
  3292. }
  3293. }
  3294. function get_date($date_format = 'j F Y, g:i a')
  3295. {
  3296. if (!isset($this->data['date']))
  3297. {
  3298. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'published'))
  3299. {
  3300. $this->data['date']['raw'] = $return[0]['data'];
  3301. }
  3302. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'updated'))
  3303. {
  3304. $this->data['date']['raw'] = $return[0]['data'];
  3305. }
  3306. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'issued'))
  3307. {
  3308. $this->data['date']['raw'] = $return[0]['data'];
  3309. }
  3310. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'created'))
  3311. {
  3312. $this->data['date']['raw'] = $return[0]['data'];
  3313. }
  3314. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'modified'))
  3315. {
  3316. $this->data['date']['raw'] = $return[0]['data'];
  3317. }
  3318. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'pubDate'))
  3319. {
  3320. $this->data['date']['raw'] = $return[0]['data'];
  3321. }
  3322. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_11, 'date'))
  3323. {
  3324. $this->data['date']['raw'] = $return[0]['data'];
  3325. }
  3326. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_DC_10, 'date'))
  3327. {
  3328. $this->data['date']['raw'] = $return[0]['data'];
  3329. }
  3330. if (!empty($this->data['date']['raw']))
  3331. {
  3332. $parser = SimplePie_Parse_Date::get();
  3333. $this->data['date']['parsed'] = $parser->parse($this->data['date']['raw']);
  3334. }
  3335. else
  3336. {
  3337. $this->data['date'] = null;
  3338. }
  3339. }
  3340. if ($this->data['date'])
  3341. {
  3342. $date_format = (string) $date_format;
  3343. switch ($date_format)
  3344. {
  3345. case '':
  3346. return $this->sanitize($this->data['date']['raw'], SIMPLEPIE_CONSTRUCT_TEXT);
  3347. case 'U':
  3348. return $this->data['date']['parsed'];
  3349. default:
  3350. return date($date_format, $this->data['date']['parsed']);
  3351. }
  3352. }
  3353. else
  3354. {
  3355. return null;
  3356. }
  3357. }
  3358. function get_local_date($date_format = '%c')
  3359. {
  3360. if (!$date_format)
  3361. {
  3362. return $this->sanitize($this->get_date(''), SIMPLEPIE_CONSTRUCT_TEXT);
  3363. }
  3364. elseif (($date = $this->get_date('U')) !== null)
  3365. {
  3366. return strftime($date_format, $date);
  3367. }
  3368. else
  3369. {
  3370. return null;
  3371. }
  3372. }
  3373. function get_permalink()
  3374. {
  3375. $link = $this->get_link();
  3376. $enclosure = $this->get_enclosure(0);
  3377. if ($link !== null)
  3378. {
  3379. return $link;
  3380. }
  3381. elseif ($enclosure !== null)
  3382. {
  3383. return $enclosure->get_link();
  3384. }
  3385. else
  3386. {
  3387. return null;
  3388. }
  3389. }
  3390. function get_link($key = 0, $rel = 'alternate')
  3391. {
  3392. $links = $this->get_links($rel);
  3393. if ($links[$key] !== null)
  3394. {
  3395. return $links[$key];
  3396. }
  3397. else
  3398. {
  3399. return null;
  3400. }
  3401. }
  3402. function get_links($rel = 'alternate')
  3403. {
  3404. if (!isset($this->data['links']))
  3405. {
  3406. $this->data['links'] = array();
  3407. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  3408. {
  3409. if (isset($link['attribs']['']['href']))
  3410. {
  3411. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3412. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3413. }
  3414. }
  3415. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  3416. {
  3417. if (isset($link['attribs']['']['href']))
  3418. {
  3419. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  3420. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  3421. }
  3422. }
  3423. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  3424. {
  3425. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3426. }
  3427. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  3428. {
  3429. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3430. }
  3431. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  3432. {
  3433. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3434. }
  3435. if ($links = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'guid'))
  3436. {
  3437. if (!isset($links[0]['attribs']['']['isPermaLink']) || strtolower(trim($links[0]['attribs']['']['isPermaLink'])) === 'true')
  3438. {
  3439. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  3440. }
  3441. }
  3442. $keys = array_keys($this->data['links']);
  3443. foreach ($keys as $key)
  3444. {
  3445. if (SimplePie_Misc::is_isegment_nz_nc($key))
  3446. {
  3447. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  3448. {
  3449. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  3450. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  3451. }
  3452. else
  3453. {
  3454. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  3455. }
  3456. }
  3457. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  3458. {
  3459. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  3460. }
  3461. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  3462. }
  3463. }
  3464. if (isset($this->data['links'][$rel]))
  3465. {
  3466. return $this->data['links'][$rel];
  3467. }
  3468. else
  3469. {
  3470. return null;
  3471. }
  3472. }
  3473. /**
  3474. * @todo Add ability to prefer one type of content over another (in a media group).
  3475. */
  3476. function get_enclosure($key = 0, $prefer = null)
  3477. {
  3478. $enclosures = $this->get_enclosures();
  3479. if (isset($enclosures[$key]))
  3480. {
  3481. return $enclosures[$key];
  3482. }
  3483. else
  3484. {
  3485. return null;
  3486. }
  3487. }
  3488. /**
  3489. * Grabs all available enclosures (podcasts, etc.)
  3490. *
  3491. * Supports the <enclosure> RSS tag, as well as Media RSS and iTunes RSS.
  3492. *
  3493. * 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.
  3494. *
  3495. * @todo Add support for end-user defined sorting of enclosures by type/handler (so we can prefer the faster-loading FLV over MP4).
  3496. * @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).
  3497. */
  3498. function get_enclosures()
  3499. {
  3500. if (!isset($this->data['enclosures']))
  3501. {
  3502. $this->data['enclosures'] = array();
  3503. // Elements
  3504. $captions_parent = null;
  3505. $categories_parent = null;
  3506. $copyrights_parent = null;
  3507. $credits_parent = null;
  3508. $description_parent = null;
  3509. $duration_parent = null;
  3510. $hashes_parent = null;
  3511. $keywords_parent = null;
  3512. $player_parent = null;
  3513. $ratings_parent = null;
  3514. $restrictions_parent = null;
  3515. $thumbnails_parent = null;
  3516. $title_parent = null;
  3517. // Let's do the channel and item-level ones first, and just re-use them if we need to.
  3518. $parent = $this->get_feed();
  3519. // CAPTIONS
  3520. if ($captions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  3521. {
  3522. foreach ($captions as $caption)
  3523. {
  3524. $caption_type = null;
  3525. $caption_lang = null;
  3526. $caption_startTime = null;
  3527. $caption_endTime = null;
  3528. $caption_text = null;
  3529. if (isset($caption['attribs']['']['type']))
  3530. {
  3531. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3532. }
  3533. if (isset($caption['attribs']['']['lang']))
  3534. {
  3535. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3536. }
  3537. if (isset($caption['attribs']['']['start']))
  3538. {
  3539. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  3540. }
  3541. if (isset($caption['attribs']['']['end']))
  3542. {
  3543. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  3544. }
  3545. if (isset($caption['data']))
  3546. {
  3547. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3548. }
  3549. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  3550. }
  3551. }
  3552. elseif ($captions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'text'))
  3553. {
  3554. foreach ($captions as $caption)
  3555. {
  3556. $caption_type = null;
  3557. $caption_lang = null;
  3558. $caption_startTime = null;
  3559. $caption_endTime = null;
  3560. $caption_text = null;
  3561. if (isset($caption['attribs']['']['type']))
  3562. {
  3563. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3564. }
  3565. if (isset($caption['attribs']['']['lang']))
  3566. {
  3567. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  3568. }
  3569. if (isset($caption['attribs']['']['start']))
  3570. {
  3571. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  3572. }
  3573. if (isset($caption['attribs']['']['end']))
  3574. {
  3575. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  3576. }
  3577. if (isset($caption['data']))
  3578. {
  3579. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3580. }
  3581. $captions_parent[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  3582. }
  3583. }
  3584. if (is_array($captions_parent))
  3585. {
  3586. $captions_parent = array_values(SimplePie_Misc::array_unique($captions_parent));
  3587. }
  3588. // CATEGORIES
  3589. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  3590. {
  3591. $term = null;
  3592. $scheme = null;
  3593. $label = null;
  3594. if (isset($category['data']))
  3595. {
  3596. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3597. }
  3598. if (isset($category['attribs']['']['scheme']))
  3599. {
  3600. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3601. }
  3602. else
  3603. {
  3604. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  3605. }
  3606. if (isset($category['attribs']['']['label']))
  3607. {
  3608. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  3609. }
  3610. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3611. }
  3612. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'category') as $category)
  3613. {
  3614. $term = null;
  3615. $scheme = null;
  3616. $label = null;
  3617. if (isset($category['data']))
  3618. {
  3619. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3620. }
  3621. if (isset($category['attribs']['']['scheme']))
  3622. {
  3623. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3624. }
  3625. else
  3626. {
  3627. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  3628. }
  3629. if (isset($category['attribs']['']['label']))
  3630. {
  3631. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  3632. }
  3633. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3634. }
  3635. foreach ((array) $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'category') as $category)
  3636. {
  3637. $term = null;
  3638. $scheme = 'http://www.itunes.com/dtds/podcast-1.0.dtd';
  3639. $label = null;
  3640. if (isset($category['attribs']['']['text']))
  3641. {
  3642. $label = $this->sanitize($category['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  3643. }
  3644. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3645. if (isset($category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category']))
  3646. {
  3647. foreach ((array) $category['child'][SIMPLEPIE_NAMESPACE_ITUNES]['category'] as $subcategory)
  3648. {
  3649. if (isset($subcategory['attribs']['']['text']))
  3650. {
  3651. $label = $this->sanitize($subcategory['attribs']['']['text'], SIMPLEPIE_CONSTRUCT_TEXT);
  3652. }
  3653. $categories_parent[] = new $this->feed->category_class($term, $scheme, $label);
  3654. }
  3655. }
  3656. }
  3657. if (is_array($categories_parent))
  3658. {
  3659. $categories_parent = array_values(SimplePie_Misc::array_unique($categories_parent));
  3660. }
  3661. // COPYRIGHT
  3662. if ($copyright = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  3663. {
  3664. $copyright_url = null;
  3665. $copyright_label = null;
  3666. if (isset($copyright[0]['attribs']['']['url']))
  3667. {
  3668. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  3669. }
  3670. if (isset($copyright[0]['data']))
  3671. {
  3672. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3673. }
  3674. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  3675. }
  3676. elseif ($copyright = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'copyright'))
  3677. {
  3678. $copyright_url = null;
  3679. $copyright_label = null;
  3680. if (isset($copyright[0]['attribs']['']['url']))
  3681. {
  3682. $copyright_url = $this->sanitize($copyright[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  3683. }
  3684. if (isset($copyright[0]['data']))
  3685. {
  3686. $copyright_label = $this->sanitize($copyright[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3687. }
  3688. $copyrights_parent = new $this->feed->copyright_class($copyright_url, $copyright_label);
  3689. }
  3690. // CREDITS
  3691. if ($credits = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  3692. {
  3693. foreach ($credits as $credit)
  3694. {
  3695. $credit_role = null;
  3696. $credit_scheme = null;
  3697. $credit_name = null;
  3698. if (isset($credit['attribs']['']['role']))
  3699. {
  3700. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  3701. }
  3702. if (isset($credit['attribs']['']['scheme']))
  3703. {
  3704. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3705. }
  3706. else
  3707. {
  3708. $credit_scheme = 'urn:ebu';
  3709. }
  3710. if (isset($credit['data']))
  3711. {
  3712. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3713. }
  3714. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  3715. }
  3716. }
  3717. elseif ($credits = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'credit'))
  3718. {
  3719. foreach ($credits as $credit)
  3720. {
  3721. $credit_role = null;
  3722. $credit_scheme = null;
  3723. $credit_name = null;
  3724. if (isset($credit['attribs']['']['role']))
  3725. {
  3726. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  3727. }
  3728. if (isset($credit['attribs']['']['scheme']))
  3729. {
  3730. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3731. }
  3732. else
  3733. {
  3734. $credit_scheme = 'urn:ebu';
  3735. }
  3736. if (isset($credit['data']))
  3737. {
  3738. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3739. }
  3740. $credits_parent[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  3741. }
  3742. }
  3743. if (is_array($credits_parent))
  3744. {
  3745. $credits_parent = array_values(SimplePie_Misc::array_unique($credits_parent));
  3746. }
  3747. // DESCRIPTION
  3748. if ($description_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  3749. {
  3750. if (isset($description_parent[0]['data']))
  3751. {
  3752. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3753. }
  3754. }
  3755. elseif ($description_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'description'))
  3756. {
  3757. if (isset($description_parent[0]['data']))
  3758. {
  3759. $description_parent = $this->sanitize($description_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3760. }
  3761. }
  3762. // DURATION
  3763. if ($duration_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'duration'))
  3764. {
  3765. $seconds = null;
  3766. $minutes = null;
  3767. $hours = null;
  3768. if (isset($duration_parent[0]['data']))
  3769. {
  3770. $temp = explode(':', $this->sanitize($duration_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3771. if (sizeof($temp) > 0)
  3772. {
  3773. (int) $seconds = array_pop($temp);
  3774. }
  3775. if (sizeof($temp) > 0)
  3776. {
  3777. (int) $minutes = array_pop($temp);
  3778. $seconds += $minutes * 60;
  3779. }
  3780. if (sizeof($temp) > 0)
  3781. {
  3782. (int) $hours = array_pop($temp);
  3783. $seconds += $hours * 3600;
  3784. }
  3785. unset($temp);
  3786. $duration_parent = $seconds;
  3787. }
  3788. }
  3789. // HASHES
  3790. if ($hashes_iterator = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  3791. {
  3792. foreach ($hashes_iterator as $hash)
  3793. {
  3794. $value = null;
  3795. $algo = null;
  3796. if (isset($hash['data']))
  3797. {
  3798. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3799. }
  3800. if (isset($hash['attribs']['']['algo']))
  3801. {
  3802. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  3803. }
  3804. else
  3805. {
  3806. $algo = 'md5';
  3807. }
  3808. $hashes_parent[] = $algo.':'.$value;
  3809. }
  3810. }
  3811. elseif ($hashes_iterator = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'hash'))
  3812. {
  3813. foreach ($hashes_iterator as $hash)
  3814. {
  3815. $value = null;
  3816. $algo = null;
  3817. if (isset($hash['data']))
  3818. {
  3819. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3820. }
  3821. if (isset($hash['attribs']['']['algo']))
  3822. {
  3823. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  3824. }
  3825. else
  3826. {
  3827. $algo = 'md5';
  3828. }
  3829. $hashes_parent[] = $algo.':'.$value;
  3830. }
  3831. }
  3832. if (is_array($hashes_parent))
  3833. {
  3834. $hashes_parent = array_values(SimplePie_Misc::array_unique($hashes_parent));
  3835. }
  3836. // KEYWORDS
  3837. if ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  3838. {
  3839. if (isset($keywords[0]['data']))
  3840. {
  3841. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3842. foreach ($temp as $word)
  3843. {
  3844. $keywords_parent[] = trim($word);
  3845. }
  3846. }
  3847. unset($temp);
  3848. }
  3849. elseif ($keywords = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  3850. {
  3851. if (isset($keywords[0]['data']))
  3852. {
  3853. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3854. foreach ($temp as $word)
  3855. {
  3856. $keywords_parent[] = trim($word);
  3857. }
  3858. }
  3859. unset($temp);
  3860. }
  3861. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'keywords'))
  3862. {
  3863. if (isset($keywords[0]['data']))
  3864. {
  3865. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3866. foreach ($temp as $word)
  3867. {
  3868. $keywords_parent[] = trim($word);
  3869. }
  3870. }
  3871. unset($temp);
  3872. }
  3873. elseif ($keywords = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'keywords'))
  3874. {
  3875. if (isset($keywords[0]['data']))
  3876. {
  3877. $temp = explode(',', $this->sanitize($keywords[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  3878. foreach ($temp as $word)
  3879. {
  3880. $keywords_parent[] = trim($word);
  3881. }
  3882. }
  3883. unset($temp);
  3884. }
  3885. if (is_array($keywords_parent))
  3886. {
  3887. $keywords_parent = array_values(SimplePie_Misc::array_unique($keywords_parent));
  3888. }
  3889. // PLAYER
  3890. if ($player_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  3891. {
  3892. if (isset($player_parent[0]['attribs']['']['url']))
  3893. {
  3894. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3895. }
  3896. }
  3897. elseif ($player_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'player'))
  3898. {
  3899. if (isset($player_parent[0]['attribs']['']['url']))
  3900. {
  3901. $player_parent = $this->sanitize($player_parent[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  3902. }
  3903. }
  3904. // RATINGS
  3905. if ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  3906. {
  3907. foreach ($ratings as $rating)
  3908. {
  3909. $rating_scheme = null;
  3910. $rating_value = null;
  3911. if (isset($rating['attribs']['']['scheme']))
  3912. {
  3913. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3914. }
  3915. else
  3916. {
  3917. $rating_scheme = 'urn:simple';
  3918. }
  3919. if (isset($rating['data']))
  3920. {
  3921. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3922. }
  3923. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3924. }
  3925. }
  3926. elseif ($ratings = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  3927. {
  3928. foreach ($ratings as $rating)
  3929. {
  3930. $rating_scheme = 'urn:itunes';
  3931. $rating_value = null;
  3932. if (isset($rating['data']))
  3933. {
  3934. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3935. }
  3936. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3937. }
  3938. }
  3939. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'rating'))
  3940. {
  3941. foreach ($ratings as $rating)
  3942. {
  3943. $rating_scheme = null;
  3944. $rating_value = null;
  3945. if (isset($rating['attribs']['']['scheme']))
  3946. {
  3947. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  3948. }
  3949. else
  3950. {
  3951. $rating_scheme = 'urn:simple';
  3952. }
  3953. if (isset($rating['data']))
  3954. {
  3955. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3956. }
  3957. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3958. }
  3959. }
  3960. elseif ($ratings = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'explicit'))
  3961. {
  3962. foreach ($ratings as $rating)
  3963. {
  3964. $rating_scheme = 'urn:itunes';
  3965. $rating_value = null;
  3966. if (isset($rating['data']))
  3967. {
  3968. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3969. }
  3970. $ratings_parent[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  3971. }
  3972. }
  3973. if (is_array($ratings_parent))
  3974. {
  3975. $ratings_parent = array_values(SimplePie_Misc::array_unique($ratings_parent));
  3976. }
  3977. // RESTRICTIONS
  3978. if ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  3979. {
  3980. foreach ($restrictions as $restriction)
  3981. {
  3982. $restriction_relationship = null;
  3983. $restriction_type = null;
  3984. $restriction_value = null;
  3985. if (isset($restriction['attribs']['']['relationship']))
  3986. {
  3987. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  3988. }
  3989. if (isset($restriction['attribs']['']['type']))
  3990. {
  3991. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  3992. }
  3993. if (isset($restriction['data']))
  3994. {
  3995. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  3996. }
  3997. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  3998. }
  3999. }
  4000. elseif ($restrictions = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  4001. {
  4002. foreach ($restrictions as $restriction)
  4003. {
  4004. $restriction_relationship = 'allow';
  4005. $restriction_type = null;
  4006. $restriction_value = 'itunes';
  4007. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  4008. {
  4009. $restriction_relationship = 'deny';
  4010. }
  4011. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4012. }
  4013. }
  4014. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'restriction'))
  4015. {
  4016. foreach ($restrictions as $restriction)
  4017. {
  4018. $restriction_relationship = null;
  4019. $restriction_type = null;
  4020. $restriction_value = null;
  4021. if (isset($restriction['attribs']['']['relationship']))
  4022. {
  4023. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4024. }
  4025. if (isset($restriction['attribs']['']['type']))
  4026. {
  4027. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4028. }
  4029. if (isset($restriction['data']))
  4030. {
  4031. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4032. }
  4033. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4034. }
  4035. }
  4036. elseif ($restrictions = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'block'))
  4037. {
  4038. foreach ($restrictions as $restriction)
  4039. {
  4040. $restriction_relationship = 'allow';
  4041. $restriction_type = null;
  4042. $restriction_value = 'itunes';
  4043. if (isset($restriction['data']) && strtolower($restriction['data']) === 'yes')
  4044. {
  4045. $restriction_relationship = 'deny';
  4046. }
  4047. $restrictions_parent[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4048. }
  4049. }
  4050. if (is_array($restrictions_parent))
  4051. {
  4052. $restrictions_parent = array_values(SimplePie_Misc::array_unique($restrictions_parent));
  4053. }
  4054. // THUMBNAILS
  4055. if ($thumbnails = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  4056. {
  4057. foreach ($thumbnails as $thumbnail)
  4058. {
  4059. if (isset($thumbnail['attribs']['']['url']))
  4060. {
  4061. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4062. }
  4063. }
  4064. }
  4065. elseif ($thumbnails = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'thumbnail'))
  4066. {
  4067. foreach ($thumbnails as $thumbnail)
  4068. {
  4069. if (isset($thumbnail['attribs']['']['url']))
  4070. {
  4071. $thumbnails_parent[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4072. }
  4073. }
  4074. }
  4075. // TITLES
  4076. if ($title_parent = $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  4077. {
  4078. if (isset($title_parent[0]['data']))
  4079. {
  4080. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4081. }
  4082. }
  4083. elseif ($title_parent = $parent->get_channel_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'title'))
  4084. {
  4085. if (isset($title_parent[0]['data']))
  4086. {
  4087. $title_parent = $this->sanitize($title_parent[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4088. }
  4089. }
  4090. // Clear the memory
  4091. unset($parent);
  4092. // Attributes
  4093. $bitrate = null;
  4094. $channels = null;
  4095. $duration = null;
  4096. $expression = null;
  4097. $framerate = null;
  4098. $height = null;
  4099. $javascript = null;
  4100. $lang = null;
  4101. $length = null;
  4102. $medium = null;
  4103. $samplingrate = null;
  4104. $type = null;
  4105. $url = null;
  4106. $width = null;
  4107. // Elements
  4108. $captions = null;
  4109. $categories = null;
  4110. $copyrights = null;
  4111. $credits = null;
  4112. $description = null;
  4113. $hashes = null;
  4114. $keywords = null;
  4115. $player = null;
  4116. $ratings = null;
  4117. $restrictions = null;
  4118. $thumbnails = null;
  4119. $title = null;
  4120. // If we have media:group tags, loop through them.
  4121. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_MEDIARSS, 'group') as $group)
  4122. {
  4123. // If we have media:content tags, loop through them.
  4124. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  4125. {
  4126. if (isset($content['attribs']['']['url']))
  4127. {
  4128. // Attributes
  4129. $bitrate = null;
  4130. $channels = null;
  4131. $duration = null;
  4132. $expression = null;
  4133. $framerate = null;
  4134. $height = null;
  4135. $javascript = null;
  4136. $lang = null;
  4137. $length = null;
  4138. $medium = null;
  4139. $samplingrate = null;
  4140. $type = null;
  4141. $url = null;
  4142. $width = null;
  4143. // Elements
  4144. $captions = null;
  4145. $categories = null;
  4146. $copyrights = null;
  4147. $credits = null;
  4148. $description = null;
  4149. $hashes = null;
  4150. $keywords = null;
  4151. $player = null;
  4152. $ratings = null;
  4153. $restrictions = null;
  4154. $thumbnails = null;
  4155. $title = null;
  4156. // Start checking the attributes of media:content
  4157. if (isset($content['attribs']['']['bitrate']))
  4158. {
  4159. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4160. }
  4161. if (isset($content['attribs']['']['channels']))
  4162. {
  4163. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  4164. }
  4165. if (isset($content['attribs']['']['duration']))
  4166. {
  4167. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  4168. }
  4169. else
  4170. {
  4171. $duration = $duration_parent;
  4172. }
  4173. if (isset($content['attribs']['']['expression']))
  4174. {
  4175. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  4176. }
  4177. if (isset($content['attribs']['']['framerate']))
  4178. {
  4179. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4180. }
  4181. if (isset($content['attribs']['']['height']))
  4182. {
  4183. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  4184. }
  4185. if (isset($content['attribs']['']['lang']))
  4186. {
  4187. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4188. }
  4189. if (isset($content['attribs']['']['fileSize']))
  4190. {
  4191. $length = ceil($content['attribs']['']['fileSize']);
  4192. }
  4193. if (isset($content['attribs']['']['medium']))
  4194. {
  4195. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  4196. }
  4197. if (isset($content['attribs']['']['samplingrate']))
  4198. {
  4199. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4200. }
  4201. if (isset($content['attribs']['']['type']))
  4202. {
  4203. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4204. }
  4205. if (isset($content['attribs']['']['width']))
  4206. {
  4207. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  4208. }
  4209. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4210. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  4211. // CAPTIONS
  4212. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  4213. {
  4214. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  4215. {
  4216. $caption_type = null;
  4217. $caption_lang = null;
  4218. $caption_startTime = null;
  4219. $caption_endTime = null;
  4220. $caption_text = null;
  4221. if (isset($caption['attribs']['']['type']))
  4222. {
  4223. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4224. }
  4225. if (isset($caption['attribs']['']['lang']))
  4226. {
  4227. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4228. }
  4229. if (isset($caption['attribs']['']['start']))
  4230. {
  4231. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  4232. }
  4233. if (isset($caption['attribs']['']['end']))
  4234. {
  4235. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  4236. }
  4237. if (isset($caption['data']))
  4238. {
  4239. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4240. }
  4241. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4242. }
  4243. if (is_array($captions))
  4244. {
  4245. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4246. }
  4247. }
  4248. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  4249. {
  4250. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  4251. {
  4252. $caption_type = null;
  4253. $caption_lang = null;
  4254. $caption_startTime = null;
  4255. $caption_endTime = null;
  4256. $caption_text = null;
  4257. if (isset($caption['attribs']['']['type']))
  4258. {
  4259. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4260. }
  4261. if (isset($caption['attribs']['']['lang']))
  4262. {
  4263. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4264. }
  4265. if (isset($caption['attribs']['']['start']))
  4266. {
  4267. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  4268. }
  4269. if (isset($caption['attribs']['']['end']))
  4270. {
  4271. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  4272. }
  4273. if (isset($caption['data']))
  4274. {
  4275. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4276. }
  4277. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4278. }
  4279. if (is_array($captions))
  4280. {
  4281. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4282. }
  4283. }
  4284. else
  4285. {
  4286. $captions = $captions_parent;
  4287. }
  4288. // CATEGORIES
  4289. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4290. {
  4291. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4292. {
  4293. $term = null;
  4294. $scheme = null;
  4295. $label = null;
  4296. if (isset($category['data']))
  4297. {
  4298. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4299. }
  4300. if (isset($category['attribs']['']['scheme']))
  4301. {
  4302. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4303. }
  4304. else
  4305. {
  4306. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4307. }
  4308. if (isset($category['attribs']['']['label']))
  4309. {
  4310. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4311. }
  4312. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4313. }
  4314. }
  4315. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4316. {
  4317. foreach ((array) $group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4318. {
  4319. $term = null;
  4320. $scheme = null;
  4321. $label = null;
  4322. if (isset($category['data']))
  4323. {
  4324. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4325. }
  4326. if (isset($category['attribs']['']['scheme']))
  4327. {
  4328. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4329. }
  4330. else
  4331. {
  4332. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4333. }
  4334. if (isset($category['attribs']['']['label']))
  4335. {
  4336. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4337. }
  4338. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4339. }
  4340. }
  4341. if (is_array($categories) && is_array($categories_parent))
  4342. {
  4343. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  4344. }
  4345. elseif (is_array($categories))
  4346. {
  4347. $categories = array_values(SimplePie_Misc::array_unique($categories));
  4348. }
  4349. elseif (is_array($categories_parent))
  4350. {
  4351. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  4352. }
  4353. // COPYRIGHTS
  4354. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4355. {
  4356. $copyright_url = null;
  4357. $copyright_label = null;
  4358. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4359. {
  4360. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4361. }
  4362. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4363. {
  4364. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4365. }
  4366. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4367. }
  4368. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4369. {
  4370. $copyright_url = null;
  4371. $copyright_label = null;
  4372. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4373. {
  4374. $copyright_url = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4375. }
  4376. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4377. {
  4378. $copyright_label = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4379. }
  4380. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4381. }
  4382. else
  4383. {
  4384. $copyrights = $copyrights_parent;
  4385. }
  4386. // CREDITS
  4387. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4388. {
  4389. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4390. {
  4391. $credit_role = null;
  4392. $credit_scheme = null;
  4393. $credit_name = null;
  4394. if (isset($credit['attribs']['']['role']))
  4395. {
  4396. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4397. }
  4398. if (isset($credit['attribs']['']['scheme']))
  4399. {
  4400. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4401. }
  4402. else
  4403. {
  4404. $credit_scheme = 'urn:ebu';
  4405. }
  4406. if (isset($credit['data']))
  4407. {
  4408. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4409. }
  4410. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4411. }
  4412. if (is_array($credits))
  4413. {
  4414. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4415. }
  4416. }
  4417. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4418. {
  4419. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4420. {
  4421. $credit_role = null;
  4422. $credit_scheme = null;
  4423. $credit_name = null;
  4424. if (isset($credit['attribs']['']['role']))
  4425. {
  4426. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4427. }
  4428. if (isset($credit['attribs']['']['scheme']))
  4429. {
  4430. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4431. }
  4432. else
  4433. {
  4434. $credit_scheme = 'urn:ebu';
  4435. }
  4436. if (isset($credit['data']))
  4437. {
  4438. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4439. }
  4440. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4441. }
  4442. if (is_array($credits))
  4443. {
  4444. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4445. }
  4446. }
  4447. else
  4448. {
  4449. $credits = $credits_parent;
  4450. }
  4451. // DESCRIPTION
  4452. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4453. {
  4454. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4455. }
  4456. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4457. {
  4458. $description = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4459. }
  4460. else
  4461. {
  4462. $description = $description_parent;
  4463. }
  4464. // HASHES
  4465. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4466. {
  4467. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4468. {
  4469. $value = null;
  4470. $algo = null;
  4471. if (isset($hash['data']))
  4472. {
  4473. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4474. }
  4475. if (isset($hash['attribs']['']['algo']))
  4476. {
  4477. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4478. }
  4479. else
  4480. {
  4481. $algo = 'md5';
  4482. }
  4483. $hashes[] = $algo.':'.$value;
  4484. }
  4485. if (is_array($hashes))
  4486. {
  4487. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4488. }
  4489. }
  4490. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4491. {
  4492. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4493. {
  4494. $value = null;
  4495. $algo = null;
  4496. if (isset($hash['data']))
  4497. {
  4498. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4499. }
  4500. if (isset($hash['attribs']['']['algo']))
  4501. {
  4502. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4503. }
  4504. else
  4505. {
  4506. $algo = 'md5';
  4507. }
  4508. $hashes[] = $algo.':'.$value;
  4509. }
  4510. if (is_array($hashes))
  4511. {
  4512. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4513. }
  4514. }
  4515. else
  4516. {
  4517. $hashes = $hashes_parent;
  4518. }
  4519. // KEYWORDS
  4520. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4521. {
  4522. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4523. {
  4524. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4525. foreach ($temp as $word)
  4526. {
  4527. $keywords[] = trim($word);
  4528. }
  4529. unset($temp);
  4530. }
  4531. if (is_array($keywords))
  4532. {
  4533. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  4534. }
  4535. }
  4536. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4537. {
  4538. if (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4539. {
  4540. $temp = explode(',', $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4541. foreach ($temp as $word)
  4542. {
  4543. $keywords[] = trim($word);
  4544. }
  4545. unset($temp);
  4546. }
  4547. if (is_array($keywords))
  4548. {
  4549. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  4550. }
  4551. }
  4552. else
  4553. {
  4554. $keywords = $keywords_parent;
  4555. }
  4556. // PLAYER
  4557. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4558. {
  4559. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4560. }
  4561. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  4562. {
  4563. $player = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4564. }
  4565. else
  4566. {
  4567. $player = $player_parent;
  4568. }
  4569. // RATINGS
  4570. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  4571. {
  4572. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  4573. {
  4574. $rating_scheme = null;
  4575. $rating_value = null;
  4576. if (isset($rating['attribs']['']['scheme']))
  4577. {
  4578. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4579. }
  4580. else
  4581. {
  4582. $rating_scheme = 'urn:simple';
  4583. }
  4584. if (isset($rating['data']))
  4585. {
  4586. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4587. }
  4588. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  4589. }
  4590. if (is_array($ratings))
  4591. {
  4592. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  4593. }
  4594. }
  4595. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  4596. {
  4597. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  4598. {
  4599. $rating_scheme = null;
  4600. $rating_value = null;
  4601. if (isset($rating['attribs']['']['scheme']))
  4602. {
  4603. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4604. }
  4605. else
  4606. {
  4607. $rating_scheme = 'urn:simple';
  4608. }
  4609. if (isset($rating['data']))
  4610. {
  4611. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4612. }
  4613. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  4614. }
  4615. if (is_array($ratings))
  4616. {
  4617. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  4618. }
  4619. }
  4620. else
  4621. {
  4622. $ratings = $ratings_parent;
  4623. }
  4624. // RESTRICTIONS
  4625. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  4626. {
  4627. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  4628. {
  4629. $restriction_relationship = null;
  4630. $restriction_type = null;
  4631. $restriction_value = null;
  4632. if (isset($restriction['attribs']['']['relationship']))
  4633. {
  4634. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4635. }
  4636. if (isset($restriction['attribs']['']['type']))
  4637. {
  4638. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4639. }
  4640. if (isset($restriction['data']))
  4641. {
  4642. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4643. }
  4644. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4645. }
  4646. if (is_array($restrictions))
  4647. {
  4648. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  4649. }
  4650. }
  4651. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  4652. {
  4653. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  4654. {
  4655. $restriction_relationship = null;
  4656. $restriction_type = null;
  4657. $restriction_value = null;
  4658. if (isset($restriction['attribs']['']['relationship']))
  4659. {
  4660. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  4661. }
  4662. if (isset($restriction['attribs']['']['type']))
  4663. {
  4664. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4665. }
  4666. if (isset($restriction['data']))
  4667. {
  4668. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4669. }
  4670. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  4671. }
  4672. if (is_array($restrictions))
  4673. {
  4674. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  4675. }
  4676. }
  4677. else
  4678. {
  4679. $restrictions = $restrictions_parent;
  4680. }
  4681. // THUMBNAILS
  4682. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  4683. {
  4684. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  4685. {
  4686. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4687. }
  4688. if (is_array($thumbnails))
  4689. {
  4690. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  4691. }
  4692. }
  4693. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  4694. {
  4695. foreach ($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  4696. {
  4697. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4698. }
  4699. if (is_array($thumbnails))
  4700. {
  4701. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  4702. }
  4703. }
  4704. else
  4705. {
  4706. $thumbnails = $thumbnails_parent;
  4707. }
  4708. // TITLES
  4709. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  4710. {
  4711. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4712. }
  4713. elseif (isset($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  4714. {
  4715. $title = $this->sanitize($group['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4716. }
  4717. else
  4718. {
  4719. $title = $title_parent;
  4720. }
  4721. $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);
  4722. }
  4723. }
  4724. }
  4725. // If we have standalone media:content tags, loop through them.
  4726. if (isset($this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content']))
  4727. {
  4728. foreach ((array) $this->data['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['content'] as $content)
  4729. {
  4730. if (isset($content['attribs']['']['url']))
  4731. {
  4732. // Attributes
  4733. $bitrate = null;
  4734. $channels = null;
  4735. $duration = null;
  4736. $expression = null;
  4737. $framerate = null;
  4738. $height = null;
  4739. $javascript = null;
  4740. $lang = null;
  4741. $length = null;
  4742. $medium = null;
  4743. $samplingrate = null;
  4744. $type = null;
  4745. $url = null;
  4746. $width = null;
  4747. // Elements
  4748. $captions = null;
  4749. $categories = null;
  4750. $copyrights = null;
  4751. $credits = null;
  4752. $description = null;
  4753. $hashes = null;
  4754. $keywords = null;
  4755. $player = null;
  4756. $ratings = null;
  4757. $restrictions = null;
  4758. $thumbnails = null;
  4759. $title = null;
  4760. // Start checking the attributes of media:content
  4761. if (isset($content['attribs']['']['bitrate']))
  4762. {
  4763. $bitrate = $this->sanitize($content['attribs']['']['bitrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4764. }
  4765. if (isset($content['attribs']['']['channels']))
  4766. {
  4767. $channels = $this->sanitize($content['attribs']['']['channels'], SIMPLEPIE_CONSTRUCT_TEXT);
  4768. }
  4769. if (isset($content['attribs']['']['duration']))
  4770. {
  4771. $duration = $this->sanitize($content['attribs']['']['duration'], SIMPLEPIE_CONSTRUCT_TEXT);
  4772. }
  4773. else
  4774. {
  4775. $duration = $duration_parent;
  4776. }
  4777. if (isset($content['attribs']['']['expression']))
  4778. {
  4779. $expression = $this->sanitize($content['attribs']['']['expression'], SIMPLEPIE_CONSTRUCT_TEXT);
  4780. }
  4781. if (isset($content['attribs']['']['framerate']))
  4782. {
  4783. $framerate = $this->sanitize($content['attribs']['']['framerate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4784. }
  4785. if (isset($content['attribs']['']['height']))
  4786. {
  4787. $height = $this->sanitize($content['attribs']['']['height'], SIMPLEPIE_CONSTRUCT_TEXT);
  4788. }
  4789. if (isset($content['attribs']['']['lang']))
  4790. {
  4791. $lang = $this->sanitize($content['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4792. }
  4793. if (isset($content['attribs']['']['fileSize']))
  4794. {
  4795. $length = ceil($content['attribs']['']['fileSize']);
  4796. }
  4797. if (isset($content['attribs']['']['medium']))
  4798. {
  4799. $medium = $this->sanitize($content['attribs']['']['medium'], SIMPLEPIE_CONSTRUCT_TEXT);
  4800. }
  4801. if (isset($content['attribs']['']['samplingrate']))
  4802. {
  4803. $samplingrate = $this->sanitize($content['attribs']['']['samplingrate'], SIMPLEPIE_CONSTRUCT_TEXT);
  4804. }
  4805. if (isset($content['attribs']['']['type']))
  4806. {
  4807. $type = $this->sanitize($content['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4808. }
  4809. if (isset($content['attribs']['']['width']))
  4810. {
  4811. $width = $this->sanitize($content['attribs']['']['width'], SIMPLEPIE_CONSTRUCT_TEXT);
  4812. }
  4813. $url = $this->sanitize($content['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  4814. // Checking the other optional media: elements. Priority: media:content, media:group, item, channel
  4815. // CAPTIONS
  4816. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text']))
  4817. {
  4818. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['text'] as $caption)
  4819. {
  4820. $caption_type = null;
  4821. $caption_lang = null;
  4822. $caption_startTime = null;
  4823. $caption_endTime = null;
  4824. $caption_text = null;
  4825. if (isset($caption['attribs']['']['type']))
  4826. {
  4827. $caption_type = $this->sanitize($caption['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  4828. }
  4829. if (isset($caption['attribs']['']['lang']))
  4830. {
  4831. $caption_lang = $this->sanitize($caption['attribs']['']['lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  4832. }
  4833. if (isset($caption['attribs']['']['start']))
  4834. {
  4835. $caption_startTime = $this->sanitize($caption['attribs']['']['start'], SIMPLEPIE_CONSTRUCT_TEXT);
  4836. }
  4837. if (isset($caption['attribs']['']['end']))
  4838. {
  4839. $caption_endTime = $this->sanitize($caption['attribs']['']['end'], SIMPLEPIE_CONSTRUCT_TEXT);
  4840. }
  4841. if (isset($caption['data']))
  4842. {
  4843. $caption_text = $this->sanitize($caption['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4844. }
  4845. $captions[] = new $this->feed->caption_class($caption_type, $caption_lang, $caption_startTime, $caption_endTime, $caption_text);
  4846. }
  4847. if (is_array($captions))
  4848. {
  4849. $captions = array_values(SimplePie_Misc::array_unique($captions));
  4850. }
  4851. }
  4852. else
  4853. {
  4854. $captions = $captions_parent;
  4855. }
  4856. // CATEGORIES
  4857. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category']))
  4858. {
  4859. foreach ((array) $content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['category'] as $category)
  4860. {
  4861. $term = null;
  4862. $scheme = null;
  4863. $label = null;
  4864. if (isset($category['data']))
  4865. {
  4866. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4867. }
  4868. if (isset($category['attribs']['']['scheme']))
  4869. {
  4870. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4871. }
  4872. else
  4873. {
  4874. $scheme = 'http://search.yahoo.com/mrss/category_schema';
  4875. }
  4876. if (isset($category['attribs']['']['label']))
  4877. {
  4878. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  4879. }
  4880. $categories[] = new $this->feed->category_class($term, $scheme, $label);
  4881. }
  4882. }
  4883. if (is_array($categories) && is_array($categories_parent))
  4884. {
  4885. $categories = array_values(SimplePie_Misc::array_unique(array_merge($categories, $categories_parent)));
  4886. }
  4887. elseif (is_array($categories))
  4888. {
  4889. $categories = array_values(SimplePie_Misc::array_unique($categories));
  4890. }
  4891. elseif (is_array($categories_parent))
  4892. {
  4893. $categories = array_values(SimplePie_Misc::array_unique($categories_parent));
  4894. }
  4895. else
  4896. {
  4897. $categories = null;
  4898. }
  4899. // COPYRIGHTS
  4900. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright']))
  4901. {
  4902. $copyright_url = null;
  4903. $copyright_label = null;
  4904. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url']))
  4905. {
  4906. $copyright_url = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_TEXT);
  4907. }
  4908. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data']))
  4909. {
  4910. $copyright_label = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['copyright'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4911. }
  4912. $copyrights = new $this->feed->copyright_class($copyright_url, $copyright_label);
  4913. }
  4914. else
  4915. {
  4916. $copyrights = $copyrights_parent;
  4917. }
  4918. // CREDITS
  4919. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit']))
  4920. {
  4921. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['credit'] as $credit)
  4922. {
  4923. $credit_role = null;
  4924. $credit_scheme = null;
  4925. $credit_name = null;
  4926. if (isset($credit['attribs']['']['role']))
  4927. {
  4928. $credit_role = $this->sanitize($credit['attribs']['']['role'], SIMPLEPIE_CONSTRUCT_TEXT);
  4929. }
  4930. if (isset($credit['attribs']['']['scheme']))
  4931. {
  4932. $credit_scheme = $this->sanitize($credit['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  4933. }
  4934. else
  4935. {
  4936. $credit_scheme = 'urn:ebu';
  4937. }
  4938. if (isset($credit['data']))
  4939. {
  4940. $credit_name = $this->sanitize($credit['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4941. }
  4942. $credits[] = new $this->feed->credit_class($credit_role, $credit_scheme, $credit_name);
  4943. }
  4944. if (is_array($credits))
  4945. {
  4946. $credits = array_values(SimplePie_Misc::array_unique($credits));
  4947. }
  4948. }
  4949. else
  4950. {
  4951. $credits = $credits_parent;
  4952. }
  4953. // DESCRIPTION
  4954. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description']))
  4955. {
  4956. $description = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['description'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4957. }
  4958. else
  4959. {
  4960. $description = $description_parent;
  4961. }
  4962. // HASHES
  4963. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash']))
  4964. {
  4965. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['hash'] as $hash)
  4966. {
  4967. $value = null;
  4968. $algo = null;
  4969. if (isset($hash['data']))
  4970. {
  4971. $value = $this->sanitize($hash['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  4972. }
  4973. if (isset($hash['attribs']['']['algo']))
  4974. {
  4975. $algo = $this->sanitize($hash['attribs']['']['algo'], SIMPLEPIE_CONSTRUCT_TEXT);
  4976. }
  4977. else
  4978. {
  4979. $algo = 'md5';
  4980. }
  4981. $hashes[] = $algo.':'.$value;
  4982. }
  4983. if (is_array($hashes))
  4984. {
  4985. $hashes = array_values(SimplePie_Misc::array_unique($hashes));
  4986. }
  4987. }
  4988. else
  4989. {
  4990. $hashes = $hashes_parent;
  4991. }
  4992. // KEYWORDS
  4993. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords']))
  4994. {
  4995. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data']))
  4996. {
  4997. $temp = explode(',', $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['keywords'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT));
  4998. foreach ($temp as $word)
  4999. {
  5000. $keywords[] = trim($word);
  5001. }
  5002. unset($temp);
  5003. }
  5004. if (is_array($keywords))
  5005. {
  5006. $keywords = array_values(SimplePie_Misc::array_unique($keywords));
  5007. }
  5008. }
  5009. else
  5010. {
  5011. $keywords = $keywords_parent;
  5012. }
  5013. // PLAYER
  5014. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player']))
  5015. {
  5016. $player = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['player'][0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  5017. }
  5018. else
  5019. {
  5020. $player = $player_parent;
  5021. }
  5022. // RATINGS
  5023. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating']))
  5024. {
  5025. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['rating'] as $rating)
  5026. {
  5027. $rating_scheme = null;
  5028. $rating_value = null;
  5029. if (isset($rating['attribs']['']['scheme']))
  5030. {
  5031. $rating_scheme = $this->sanitize($rating['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  5032. }
  5033. else
  5034. {
  5035. $rating_scheme = 'urn:simple';
  5036. }
  5037. if (isset($rating['data']))
  5038. {
  5039. $rating_value = $this->sanitize($rating['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5040. }
  5041. $ratings[] = new $this->feed->rating_class($rating_scheme, $rating_value);
  5042. }
  5043. if (is_array($ratings))
  5044. {
  5045. $ratings = array_values(SimplePie_Misc::array_unique($ratings));
  5046. }
  5047. }
  5048. else
  5049. {
  5050. $ratings = $ratings_parent;
  5051. }
  5052. // RESTRICTIONS
  5053. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction']))
  5054. {
  5055. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['restriction'] as $restriction)
  5056. {
  5057. $restriction_relationship = null;
  5058. $restriction_type = null;
  5059. $restriction_value = null;
  5060. if (isset($restriction['attribs']['']['relationship']))
  5061. {
  5062. $restriction_relationship = $this->sanitize($restriction['attribs']['']['relationship'], SIMPLEPIE_CONSTRUCT_TEXT);
  5063. }
  5064. if (isset($restriction['attribs']['']['type']))
  5065. {
  5066. $restriction_type = $this->sanitize($restriction['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  5067. }
  5068. if (isset($restriction['data']))
  5069. {
  5070. $restriction_value = $this->sanitize($restriction['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5071. }
  5072. $restrictions[] = new $this->feed->restriction_class($restriction_relationship, $restriction_type, $restriction_value);
  5073. }
  5074. if (is_array($restrictions))
  5075. {
  5076. $restrictions = array_values(SimplePie_Misc::array_unique($restrictions));
  5077. }
  5078. }
  5079. else
  5080. {
  5081. $restrictions = $restrictions_parent;
  5082. }
  5083. // THUMBNAILS
  5084. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail']))
  5085. {
  5086. foreach ($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['thumbnail'] as $thumbnail)
  5087. {
  5088. $thumbnails[] = $this->sanitize($thumbnail['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI);
  5089. }
  5090. if (is_array($thumbnails))
  5091. {
  5092. $thumbnails = array_values(SimplePie_Misc::array_unique($thumbnails));
  5093. }
  5094. }
  5095. else
  5096. {
  5097. $thumbnails = $thumbnails_parent;
  5098. }
  5099. // TITLES
  5100. if (isset($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title']))
  5101. {
  5102. $title = $this->sanitize($content['child'][SIMPLEPIE_NAMESPACE_MEDIARSS]['title'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5103. }
  5104. else
  5105. {
  5106. $title = $title_parent;
  5107. }
  5108. $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);
  5109. }
  5110. }
  5111. }
  5112. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link') as $link)
  5113. {
  5114. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  5115. {
  5116. // Attributes
  5117. $bitrate = null;
  5118. $channels = null;
  5119. $duration = null;
  5120. $expression = null;
  5121. $framerate = null;
  5122. $height = null;
  5123. $javascript = null;
  5124. $lang = null;
  5125. $length = null;
  5126. $medium = null;
  5127. $samplingrate = null;
  5128. $type = null;
  5129. $url = null;
  5130. $width = null;
  5131. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5132. if (isset($link['attribs']['']['type']))
  5133. {
  5134. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  5135. }
  5136. if (isset($link['attribs']['']['length']))
  5137. {
  5138. $length = ceil($link['attribs']['']['length']);
  5139. }
  5140. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  5141. $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);
  5142. }
  5143. }
  5144. foreach ((array) $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link') as $link)
  5145. {
  5146. if (isset($link['attribs']['']['href']) && !empty($link['attribs']['']['rel']) && $link['attribs']['']['rel'] === 'enclosure')
  5147. {
  5148. // Attributes
  5149. $bitrate = null;
  5150. $channels = null;
  5151. $duration = null;
  5152. $expression = null;
  5153. $framerate = null;
  5154. $height = null;
  5155. $javascript = null;
  5156. $lang = null;
  5157. $length = null;
  5158. $medium = null;
  5159. $samplingrate = null;
  5160. $type = null;
  5161. $url = null;
  5162. $width = null;
  5163. $url = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5164. if (isset($link['attribs']['']['type']))
  5165. {
  5166. $type = $this->sanitize($link['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  5167. }
  5168. if (isset($link['attribs']['']['length']))
  5169. {
  5170. $length = ceil($link['attribs']['']['length']);
  5171. }
  5172. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  5173. $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);
  5174. }
  5175. }
  5176. if ($enclosure = $this->get_item_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'enclosure'))
  5177. {
  5178. if (isset($enclosure[0]['attribs']['']['url']))
  5179. {
  5180. // Attributes
  5181. $bitrate = null;
  5182. $channels = null;
  5183. $duration = null;
  5184. $expression = null;
  5185. $framerate = null;
  5186. $height = null;
  5187. $javascript = null;
  5188. $lang = null;
  5189. $length = null;
  5190. $medium = null;
  5191. $samplingrate = null;
  5192. $type = null;
  5193. $url = null;
  5194. $width = null;
  5195. $url = $this->sanitize($enclosure[0]['attribs']['']['url'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($enclosure[0]));
  5196. if (isset($enclosure[0]['attribs']['']['type']))
  5197. {
  5198. $type = $this->sanitize($enclosure[0]['attribs']['']['type'], SIMPLEPIE_CONSTRUCT_TEXT);
  5199. }
  5200. if (isset($enclosure[0]['attribs']['']['length']))
  5201. {
  5202. $length = ceil($enclosure[0]['attribs']['']['length']);
  5203. }
  5204. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  5205. $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);
  5206. }
  5207. }
  5208. 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))
  5209. {
  5210. // Since we don't have group or content for these, we'll just pass the '*_parent' variables directly to the constructor
  5211. $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);
  5212. }
  5213. $this->data['enclosures'] = array_values(SimplePie_Misc::array_unique($this->data['enclosures']));
  5214. }
  5215. if (!empty($this->data['enclosures']))
  5216. {
  5217. return $this->data['enclosures'];
  5218. }
  5219. else
  5220. {
  5221. return null;
  5222. }
  5223. }
  5224. function get_latitude()
  5225. {
  5226. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  5227. {
  5228. return (float) $return[0]['data'];
  5229. }
  5230. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  5231. {
  5232. return (float) $match[1];
  5233. }
  5234. else
  5235. {
  5236. return null;
  5237. }
  5238. }
  5239. function get_longitude()
  5240. {
  5241. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  5242. {
  5243. return (float) $return[0]['data'];
  5244. }
  5245. elseif ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  5246. {
  5247. return (float) $return[0]['data'];
  5248. }
  5249. elseif (($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  5250. {
  5251. return (float) $match[2];
  5252. }
  5253. else
  5254. {
  5255. return null;
  5256. }
  5257. }
  5258. function get_source()
  5259. {
  5260. if ($return = $this->get_item_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'source'))
  5261. {
  5262. return new $this->feed->source_class($this, $return[0]);
  5263. }
  5264. else
  5265. {
  5266. return null;
  5267. }
  5268. }
  5269. /**
  5270. * Creates the add_to_* methods' return data
  5271. *
  5272. * @access private
  5273. * @param string $item_url String to prefix to the item permalink
  5274. * @param string $title_url String to prefix to the item title
  5275. * (and suffix to the item permalink)
  5276. * @return mixed URL if feed exists, false otherwise
  5277. */
  5278. function add_to_service($item_url, $title_url = null, $summary_url = null)
  5279. {
  5280. if ($this->get_permalink() !== null)
  5281. {
  5282. $return = $item_url . rawurlencode($this->get_permalink());
  5283. if ($title_url !== null && $this->get_title() !== null)
  5284. {
  5285. $return .= $title_url . rawurlencode($this->get_title());
  5286. }
  5287. if ($summary_url !== null && $this->get_description() !== null)
  5288. {
  5289. $return .= $summary_url . rawurlencode($this->get_description());
  5290. }
  5291. return $this->sanitize($return, SIMPLEPIE_CONSTRUCT_IRI);
  5292. }
  5293. else
  5294. {
  5295. return null;
  5296. }
  5297. }
  5298. function add_to_blinklist()
  5299. {
  5300. return $this->add_to_service('http://www.blinklist.com/index.php?Action=Blink/addblink.php&Description=&Url=', '&Title=');
  5301. }
  5302. function add_to_blogmarks()
  5303. {
  5304. return $this->add_to_service('http://blogmarks.net/my/new.php?mini=1&simple=1&url=', '&title=');
  5305. }
  5306. function add_to_delicious()
  5307. {
  5308. return $this->add_to_service('http://del.icio.us/post/?v=4&url=', '&title=');
  5309. }
  5310. function add_to_digg()
  5311. {
  5312. return $this->add_to_service('http://digg.com/submit?url=', '&title=', '&bodytext=');
  5313. }
  5314. function add_to_furl()
  5315. {
  5316. return $this->add_to_service('http://www.furl.net/storeIt.jsp?u=', '&t=');
  5317. }
  5318. function add_to_magnolia()
  5319. {
  5320. return $this->add_to_service('http://ma.gnolia.com/bookmarklet/add?url=', '&title=');
  5321. }
  5322. function add_to_myweb20()
  5323. {
  5324. return $this->add_to_service('http://myweb2.search.yahoo.com/myresults/bookmarklet?u=', '&t=');
  5325. }
  5326. function add_to_newsvine()
  5327. {
  5328. return $this->add_to_service('http://www.newsvine.com/_wine/save?u=', '&h=');
  5329. }
  5330. function add_to_reddit()
  5331. {
  5332. return $this->add_to_service('http://reddit.com/submit?url=', '&title=');
  5333. }
  5334. function add_to_segnalo()
  5335. {
  5336. return $this->add_to_service('http://segnalo.com/post.html.php?url=', '&title=');
  5337. }
  5338. function add_to_simpy()
  5339. {
  5340. return $this->add_to_service('http://www.simpy.com/simpy/LinkAdd.do?href=', '&title=');
  5341. }
  5342. function add_to_spurl()
  5343. {
  5344. return $this->add_to_service('http://www.spurl.net/spurl.php?v=3&url=', '&title=');
  5345. }
  5346. function add_to_wists()
  5347. {
  5348. return $this->add_to_service('http://wists.com/r.php?c=&r=', '&title=');
  5349. }
  5350. function search_technorati()
  5351. {
  5352. return $this->add_to_service('http://www.technorati.com/search/');
  5353. }
  5354. }
  5355. class SimplePie_Source
  5356. {
  5357. var $item;
  5358. var $data = array();
  5359. function SimplePie_Source($item, $data)
  5360. {
  5361. $this->item = $item;
  5362. $this->data = $data;
  5363. }
  5364. function __toString()
  5365. {
  5366. return md5(serialize($this->data));
  5367. }
  5368. function get_source_tags($namespace, $tag)
  5369. {
  5370. if (isset($this->data['child'][$namespace][$tag]))
  5371. {
  5372. return $this->data['child'][$namespace][$tag];
  5373. }
  5374. else
  5375. {
  5376. return null;
  5377. }
  5378. }
  5379. function get_base($element = array())
  5380. {
  5381. return $this->item->get_base($element);
  5382. }
  5383. function sanitize($data, $type, $base = '')
  5384. {
  5385. return $this->item->sanitize($data, $type, $base);
  5386. }
  5387. function get_item()
  5388. {
  5389. return $this->item;
  5390. }
  5391. function get_title()
  5392. {
  5393. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'title'))
  5394. {
  5395. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5396. }
  5397. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'title'))
  5398. {
  5399. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5400. }
  5401. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'title'))
  5402. {
  5403. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5404. }
  5405. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'title'))
  5406. {
  5407. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5408. }
  5409. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'title'))
  5410. {
  5411. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5412. }
  5413. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'title'))
  5414. {
  5415. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5416. }
  5417. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'title'))
  5418. {
  5419. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5420. }
  5421. else
  5422. {
  5423. return null;
  5424. }
  5425. }
  5426. function get_category($key = 0)
  5427. {
  5428. $categories = $this->get_categories();
  5429. if (isset($categories[$key]))
  5430. {
  5431. return $categories[$key];
  5432. }
  5433. else
  5434. {
  5435. return null;
  5436. }
  5437. }
  5438. function get_categories()
  5439. {
  5440. $categories = array();
  5441. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'category') as $category)
  5442. {
  5443. $term = null;
  5444. $scheme = null;
  5445. $label = null;
  5446. if (isset($category['attribs']['']['term']))
  5447. {
  5448. $term = $this->sanitize($category['attribs']['']['term'], SIMPLEPIE_CONSTRUCT_TEXT);
  5449. }
  5450. if (isset($category['attribs']['']['scheme']))
  5451. {
  5452. $scheme = $this->sanitize($category['attribs']['']['scheme'], SIMPLEPIE_CONSTRUCT_TEXT);
  5453. }
  5454. if (isset($category['attribs']['']['label']))
  5455. {
  5456. $label = $this->sanitize($category['attribs']['']['label'], SIMPLEPIE_CONSTRUCT_TEXT);
  5457. }
  5458. $categories[] = new $this->item->feed->category_class($term, $scheme, $label);
  5459. }
  5460. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'category') as $category)
  5461. {
  5462. // This is really the label, but keep this as the term also for BC.
  5463. // Label will also work on retrieving because that falls back to term.
  5464. $term = $this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5465. if (isset($category['attribs']['']['domain']))
  5466. {
  5467. $scheme = $this->sanitize($category['attribs']['']['domain'], SIMPLEPIE_CONSTRUCT_TEXT);
  5468. }
  5469. else
  5470. {
  5471. $scheme = null;
  5472. }
  5473. $categories[] = new $this->item->feed->category_class($term, $scheme, null);
  5474. }
  5475. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'subject') as $category)
  5476. {
  5477. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5478. }
  5479. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'subject') as $category)
  5480. {
  5481. $categories[] = new $this->item->feed->category_class($this->sanitize($category['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5482. }
  5483. if (!empty($categories))
  5484. {
  5485. return SimplePie_Misc::array_unique($categories);
  5486. }
  5487. else
  5488. {
  5489. return null;
  5490. }
  5491. }
  5492. function get_author($key = 0)
  5493. {
  5494. $authors = $this->get_authors();
  5495. if (isset($authors[$key]))
  5496. {
  5497. return $authors[$key];
  5498. }
  5499. else
  5500. {
  5501. return null;
  5502. }
  5503. }
  5504. function get_authors()
  5505. {
  5506. $authors = array();
  5507. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'author') as $author)
  5508. {
  5509. $name = null;
  5510. $uri = null;
  5511. $email = null;
  5512. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  5513. {
  5514. $name = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5515. }
  5516. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  5517. {
  5518. $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]));
  5519. }
  5520. if (isset($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  5521. {
  5522. $email = $this->sanitize($author['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5523. }
  5524. if ($name !== null || $email !== null || $uri !== null)
  5525. {
  5526. $authors[] = new $this->item->feed->author_class($name, $uri, $email);
  5527. }
  5528. }
  5529. if ($author = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'author'))
  5530. {
  5531. $name = null;
  5532. $url = null;
  5533. $email = null;
  5534. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  5535. {
  5536. $name = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5537. }
  5538. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  5539. {
  5540. $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]));
  5541. }
  5542. if (isset($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  5543. {
  5544. $email = $this->sanitize($author[0]['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5545. }
  5546. if ($name !== null || $email !== null || $url !== null)
  5547. {
  5548. $authors[] = new $this->item->feed->author_class($name, $url, $email);
  5549. }
  5550. }
  5551. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'creator') as $author)
  5552. {
  5553. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5554. }
  5555. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'creator') as $author)
  5556. {
  5557. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5558. }
  5559. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'author') as $author)
  5560. {
  5561. $authors[] = new $this->item->feed->author_class($this->sanitize($author['data'], SIMPLEPIE_CONSTRUCT_TEXT), null, null);
  5562. }
  5563. if (!empty($authors))
  5564. {
  5565. return SimplePie_Misc::array_unique($authors);
  5566. }
  5567. else
  5568. {
  5569. return null;
  5570. }
  5571. }
  5572. function get_contributor($key = 0)
  5573. {
  5574. $contributors = $this->get_contributors();
  5575. if (isset($contributors[$key]))
  5576. {
  5577. return $contributors[$key];
  5578. }
  5579. else
  5580. {
  5581. return null;
  5582. }
  5583. }
  5584. function get_contributors()
  5585. {
  5586. $contributors = array();
  5587. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'contributor') as $contributor)
  5588. {
  5589. $name = null;
  5590. $uri = null;
  5591. $email = null;
  5592. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data']))
  5593. {
  5594. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5595. }
  5596. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['uri'][0]['data']))
  5597. {
  5598. $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]));
  5599. }
  5600. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data']))
  5601. {
  5602. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5603. }
  5604. if ($name !== null || $email !== null || $uri !== null)
  5605. {
  5606. $contributors[] = new $this->item->feed->author_class($name, $uri, $email);
  5607. }
  5608. }
  5609. foreach ((array) $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'contributor') as $contributor)
  5610. {
  5611. $name = null;
  5612. $url = null;
  5613. $email = null;
  5614. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data']))
  5615. {
  5616. $name = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['name'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5617. }
  5618. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['url'][0]['data']))
  5619. {
  5620. $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]));
  5621. }
  5622. if (isset($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data']))
  5623. {
  5624. $email = $this->sanitize($contributor['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['email'][0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5625. }
  5626. if ($name !== null || $email !== null || $url !== null)
  5627. {
  5628. $contributors[] = new $this->item->feed->author_class($name, $url, $email);
  5629. }
  5630. }
  5631. if (!empty($contributors))
  5632. {
  5633. return SimplePie_Misc::array_unique($contributors);
  5634. }
  5635. else
  5636. {
  5637. return null;
  5638. }
  5639. }
  5640. function get_link($key = 0, $rel = 'alternate')
  5641. {
  5642. $links = $this->get_links($rel);
  5643. if (isset($links[$key]))
  5644. {
  5645. return $links[$key];
  5646. }
  5647. else
  5648. {
  5649. return null;
  5650. }
  5651. }
  5652. /**
  5653. * Added for parity between the parent-level and the item/entry-level.
  5654. */
  5655. function get_permalink()
  5656. {
  5657. return $this->get_link(0);
  5658. }
  5659. function get_links($rel = 'alternate')
  5660. {
  5661. if (!isset($this->data['links']))
  5662. {
  5663. $this->data['links'] = array();
  5664. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'link'))
  5665. {
  5666. foreach ($links as $link)
  5667. {
  5668. if (isset($link['attribs']['']['href']))
  5669. {
  5670. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  5671. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5672. }
  5673. }
  5674. }
  5675. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'link'))
  5676. {
  5677. foreach ($links as $link)
  5678. {
  5679. if (isset($link['attribs']['']['href']))
  5680. {
  5681. $link_rel = (isset($link['attribs']['']['rel'])) ? $link['attribs']['']['rel'] : 'alternate';
  5682. $this->data['links'][$link_rel][] = $this->sanitize($link['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($link));
  5683. }
  5684. }
  5685. }
  5686. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'link'))
  5687. {
  5688. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5689. }
  5690. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'link'))
  5691. {
  5692. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5693. }
  5694. if ($links = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'link'))
  5695. {
  5696. $this->data['links']['alternate'][] = $this->sanitize($links[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($links[0]));
  5697. }
  5698. $keys = array_keys($this->data['links']);
  5699. foreach ($keys as $key)
  5700. {
  5701. if (SimplePie_Misc::is_isegment_nz_nc($key))
  5702. {
  5703. if (isset($this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]))
  5704. {
  5705. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] = array_merge($this->data['links'][$key], $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key]);
  5706. $this->data['links'][$key] =& $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key];
  5707. }
  5708. else
  5709. {
  5710. $this->data['links'][SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY . $key] =& $this->data['links'][$key];
  5711. }
  5712. }
  5713. elseif (substr($key, 0, 41) === SIMPLEPIE_IANA_LINK_RELATIONS_REGISTRY)
  5714. {
  5715. $this->data['links'][substr($key, 41)] =& $this->data['links'][$key];
  5716. }
  5717. $this->data['links'][$key] = array_unique($this->data['links'][$key]);
  5718. }
  5719. }
  5720. if (isset($this->data['links'][$rel]))
  5721. {
  5722. return $this->data['links'][$rel];
  5723. }
  5724. else
  5725. {
  5726. return null;
  5727. }
  5728. }
  5729. function get_description()
  5730. {
  5731. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'subtitle'))
  5732. {
  5733. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5734. }
  5735. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'tagline'))
  5736. {
  5737. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5738. }
  5739. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_10, 'description'))
  5740. {
  5741. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5742. }
  5743. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_090, 'description'))
  5744. {
  5745. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5746. }
  5747. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'description'))
  5748. {
  5749. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_MAYBE_HTML, $this->get_base($return[0]));
  5750. }
  5751. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'description'))
  5752. {
  5753. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5754. }
  5755. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'description'))
  5756. {
  5757. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5758. }
  5759. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'summary'))
  5760. {
  5761. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  5762. }
  5763. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'subtitle'))
  5764. {
  5765. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_HTML, $this->get_base($return[0]));
  5766. }
  5767. else
  5768. {
  5769. return null;
  5770. }
  5771. }
  5772. function get_copyright()
  5773. {
  5774. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'rights'))
  5775. {
  5776. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_10_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5777. }
  5778. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_03, 'copyright'))
  5779. {
  5780. return $this->sanitize($return[0]['data'], SimplePie_Misc::atom_03_construct_type($return[0]['attribs']), $this->get_base($return[0]));
  5781. }
  5782. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'copyright'))
  5783. {
  5784. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5785. }
  5786. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'rights'))
  5787. {
  5788. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5789. }
  5790. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'rights'))
  5791. {
  5792. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5793. }
  5794. else
  5795. {
  5796. return null;
  5797. }
  5798. }
  5799. function get_language()
  5800. {
  5801. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_RSS_20, 'language'))
  5802. {
  5803. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5804. }
  5805. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_11, 'language'))
  5806. {
  5807. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5808. }
  5809. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_DC_10, 'language'))
  5810. {
  5811. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_TEXT);
  5812. }
  5813. elseif (isset($this->data['xml_lang']))
  5814. {
  5815. return $this->sanitize($this->data['xml_lang'], SIMPLEPIE_CONSTRUCT_TEXT);
  5816. }
  5817. else
  5818. {
  5819. return null;
  5820. }
  5821. }
  5822. function get_latitude()
  5823. {
  5824. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lat'))
  5825. {
  5826. return (float) $return[0]['data'];
  5827. }
  5828. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  5829. {
  5830. return (float) $match[1];
  5831. }
  5832. else
  5833. {
  5834. return null;
  5835. }
  5836. }
  5837. function get_longitude()
  5838. {
  5839. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'long'))
  5840. {
  5841. return (float) $return[0]['data'];
  5842. }
  5843. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_W3C_BASIC_GEO, 'lon'))
  5844. {
  5845. return (float) $return[0]['data'];
  5846. }
  5847. elseif (($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_GEORSS, 'point')) && preg_match('/^((?:-)?[0-9]+(?:\.[0-9]+)) ((?:-)?[0-9]+(?:\.[0-9]+))$/', $return[0]['data'], $match))
  5848. {
  5849. return (float) $match[2];
  5850. }
  5851. else
  5852. {
  5853. return null;
  5854. }
  5855. }
  5856. function get_image_url()
  5857. {
  5858. if ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ITUNES, 'image'))
  5859. {
  5860. return $this->sanitize($return[0]['attribs']['']['href'], SIMPLEPIE_CONSTRUCT_IRI);
  5861. }
  5862. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'logo'))
  5863. {
  5864. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  5865. }
  5866. elseif ($return = $this->get_source_tags(SIMPLEPIE_NAMESPACE_ATOM_10, 'icon'))
  5867. {
  5868. return $this->sanitize($return[0]['data'], SIMPLEPIE_CONSTRUCT_IRI, $this->get_base($return[0]));
  5869. }
  5870. else
  5871. {
  5872. return null;
  5873. }
  5874. }
  5875. }
  5876. class SimplePie_Author
  5877. {
  5878. var $name;
  5879. var $link;
  5880. var $email;
  5881. // Constructor, used to input the data
  5882. function SimplePie_Author($name = null, $link = null, $email = null)
  5883. {
  5884. $this->name = $name;
  5885. $this->link = $link;
  5886. $this->email = $email;
  5887. }
  5888. function __toString()
  5889. {
  5890. // There is no $this->data here
  5891. return md5(serialize($this));
  5892. }
  5893. function get_name()
  5894. {
  5895. if ($this->name !== null)
  5896. {
  5897. return $this->name;
  5898. }
  5899. else
  5900. {
  5901. return null;
  5902. }
  5903. }
  5904. function get_link()
  5905. {
  5906. if ($this->link !== null)
  5907. {
  5908. return $this->link;
  5909. }
  5910. else
  5911. {
  5912. return null;
  5913. }
  5914. }
  5915. function get_email()
  5916. {
  5917. if ($this->email !== null)
  5918. {
  5919. return $this->email;
  5920. }
  5921. else
  5922. {
  5923. return null;
  5924. }
  5925. }
  5926. }
  5927. class SimplePie_Category
  5928. {
  5929. var $term;
  5930. var $scheme;
  5931. var $label;
  5932. // Constructor, used to input the data
  5933. function SimplePie_Category($term = null, $scheme = null, $label = null)
  5934. {
  5935. $this->term = $term;
  5936. $this->scheme = $scheme;
  5937. $this->label = $label;
  5938. }
  5939. function __toString()
  5940. {
  5941. // There is no $this->data here
  5942. return md5(serialize($this));
  5943. }
  5944. function get_term()
  5945. {
  5946. if ($this->term !== null)
  5947. {
  5948. return $this->term;
  5949. }
  5950. else
  5951. {
  5952. return null;
  5953. }
  5954. }
  5955. function get_scheme()
  5956. {
  5957. if ($this->scheme !== null)
  5958. {
  5959. return $this->scheme;
  5960. }
  5961. else
  5962. {
  5963. return null;
  5964. }
  5965. }
  5966. function get_label()
  5967. {
  5968. if ($this->label !== null)
  5969. {
  5970. return $this->label;
  5971. }
  5972. else
  5973. {
  5974. return $this->get_term();
  5975. }
  5976. }
  5977. }
  5978. class SimplePie_Enclosure
  5979. {
  5980. var $bitrate;
  5981. var $captions;
  5982. var $categories;
  5983. var $channels;
  5984. var $copyright;
  5985. var $credits;
  5986. var $description;
  5987. var $duration;
  5988. var $expression;
  5989. var $framerate;
  5990. var $handler;
  5991. var $hashes;
  5992. var $height;
  5993. var $javascript;
  5994. var $keywords;
  5995. var $lang;
  5996. var $length;
  5997. var $link;
  5998. var $medium;
  5999. var $player;
  6000. var $ratings;
  6001. var $restrictions;
  6002. var $samplingrate;
  6003. var $thumbnails;
  6004. var $title;
  6005. var $type;
  6006. var $width;
  6007. // Constructor, used to input the data
  6008. function SimplePie_Enclosure($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)
  6009. {
  6010. $this->bitrate = $bitrate;
  6011. $this->captions = $captions;
  6012. $this->categories = $categories;
  6013. $this->channels = $channels;
  6014. $this->copyright = $copyright;
  6015. $this->credits = $credits;
  6016. $this->description = $description;
  6017. $this->duration = $duration;
  6018. $this->expression = $expression;
  6019. $this->framerate = $framerate;
  6020. $this->hashes = $hashes;
  6021. $this->height = $height;
  6022. $this->javascript = $javascript;
  6023. $this->keywords = $keywords;
  6024. $this->lang = $lang;
  6025. $this->length = $length;
  6026. $this->link = $link;
  6027. $this->medium = $medium;
  6028. $this->player = $player;
  6029. $this->ratings = $ratings;
  6030. $this->restrictions = $restrictions;
  6031. $this->samplingrate = $samplingrate;
  6032. $this->thumbnails = $thumbnails;
  6033. $this->title = $title;
  6034. $this->type = $type;
  6035. $this->width = $width;
  6036. if (class_exists('idna_convert'))
  6037. {
  6038. $idn = new idna_convert;
  6039. $parsed = SimplePie_Misc::parse_url($link);
  6040. $this->link = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  6041. }
  6042. $this->handler = $this->get_handler(); // Needs to load last
  6043. }
  6044. function __toString()
  6045. {
  6046. // There is no $this->data here
  6047. return md5(serialize($this));
  6048. }
  6049. function get_bitrate()
  6050. {
  6051. if ($this->bitrate !== null)
  6052. {
  6053. return $this->bitrate;
  6054. }
  6055. else
  6056. {
  6057. return null;
  6058. }
  6059. }
  6060. function get_caption($key = 0)
  6061. {
  6062. $captions = $this->get_captions();
  6063. if (isset($captions[$key]))
  6064. {
  6065. return $captions[$key];
  6066. }
  6067. else
  6068. {
  6069. return null;
  6070. }
  6071. }
  6072. function get_captions()
  6073. {
  6074. if ($this->captions !== null)
  6075. {
  6076. return $this->captions;
  6077. }
  6078. else
  6079. {
  6080. return null;
  6081. }
  6082. }
  6083. function get_category($key = 0)
  6084. {
  6085. $categories = $this->get_categories();
  6086. if (isset($categories[$key]))
  6087. {
  6088. return $categories[$key];
  6089. }
  6090. else
  6091. {
  6092. return null;
  6093. }
  6094. }
  6095. function get_categories()
  6096. {
  6097. if ($this->categories !== null)
  6098. {
  6099. return $this->categories;
  6100. }
  6101. else
  6102. {
  6103. return null;
  6104. }
  6105. }
  6106. function get_channels()
  6107. {
  6108. if ($this->channels !== null)
  6109. {
  6110. return $this->channels;
  6111. }
  6112. else
  6113. {
  6114. return null;
  6115. }
  6116. }
  6117. function get_copyright()
  6118. {
  6119. if ($this->copyright !== null)
  6120. {
  6121. return $this->copyright;
  6122. }
  6123. else
  6124. {
  6125. return null;
  6126. }
  6127. }
  6128. function get_credit($key = 0)
  6129. {
  6130. $credits = $this->get_credits();
  6131. if (isset($credits[$key]))
  6132. {
  6133. return $credits[$key];
  6134. }
  6135. else
  6136. {
  6137. return null;
  6138. }
  6139. }
  6140. function get_credits()
  6141. {
  6142. if ($this->credits !== null)
  6143. {
  6144. return $this->credits;
  6145. }
  6146. else
  6147. {
  6148. return null;
  6149. }
  6150. }
  6151. function get_description()
  6152. {
  6153. if ($this->description !== null)
  6154. {
  6155. return $this->description;
  6156. }
  6157. else
  6158. {
  6159. return null;
  6160. }
  6161. }
  6162. function get_duration($convert = false)
  6163. {
  6164. if ($this->duration !== null)
  6165. {
  6166. if ($convert)
  6167. {
  6168. $time = SimplePie_Misc::time_hms($this->duration);
  6169. return $time;
  6170. }
  6171. else
  6172. {
  6173. return $this->duration;
  6174. }
  6175. }
  6176. else
  6177. {
  6178. return null;
  6179. }
  6180. }
  6181. function get_expression()
  6182. {
  6183. if ($this->expression !== null)
  6184. {
  6185. return $this->expression;
  6186. }
  6187. else
  6188. {
  6189. return 'full';
  6190. }
  6191. }
  6192. function get_extension()
  6193. {
  6194. if ($this->link !== null)
  6195. {
  6196. $url = SimplePie_Misc::parse_url($this->link);
  6197. if ($url['path'] !== '')
  6198. {
  6199. return pathinfo($url['path'], PATHINFO_EXTENSION);
  6200. }
  6201. }
  6202. return null;
  6203. }
  6204. function get_framerate()
  6205. {
  6206. if ($this->framerate !== null)
  6207. {
  6208. return $this->framerate;
  6209. }
  6210. else
  6211. {
  6212. return null;
  6213. }
  6214. }
  6215. function get_handler()
  6216. {
  6217. return $this->get_real_type(true);
  6218. }
  6219. function get_hash($key = 0)
  6220. {
  6221. $hashes = $this->get_hashes();
  6222. if (isset($hashes[$key]))
  6223. {
  6224. return $hashes[$key];
  6225. }
  6226. else
  6227. {
  6228. return null;
  6229. }
  6230. }
  6231. function get_hashes()
  6232. {
  6233. if ($this->hashes !== null)
  6234. {
  6235. return $this->hashes;
  6236. }
  6237. else
  6238. {
  6239. return null;
  6240. }
  6241. }
  6242. function get_height()
  6243. {
  6244. if ($this->height !== null)
  6245. {
  6246. return $this->height;
  6247. }
  6248. else
  6249. {
  6250. return null;
  6251. }
  6252. }
  6253. function get_language()
  6254. {
  6255. if ($this->lang !== null)
  6256. {
  6257. return $this->lang;
  6258. }
  6259. else
  6260. {
  6261. return null;
  6262. }
  6263. }
  6264. function get_keyword($key = 0)
  6265. {
  6266. $keywords = $this->get_keywords();
  6267. if (isset($keywords[$key]))
  6268. {
  6269. return $keywords[$key];
  6270. }
  6271. else
  6272. {
  6273. return null;
  6274. }
  6275. }
  6276. function get_keywords()
  6277. {
  6278. if ($this->keywords !== null)
  6279. {
  6280. return $this->keywords;
  6281. }
  6282. else
  6283. {
  6284. return null;
  6285. }
  6286. }
  6287. function get_length()
  6288. {
  6289. if ($this->length !== null)
  6290. {
  6291. return $this->length;
  6292. }
  6293. else
  6294. {
  6295. return null;
  6296. }
  6297. }
  6298. function get_link()
  6299. {
  6300. if ($this->link !== null)
  6301. {
  6302. return urldecode($this->link);
  6303. }
  6304. else
  6305. {
  6306. return null;
  6307. }
  6308. }
  6309. function get_medium()
  6310. {
  6311. if ($this->medium !== null)
  6312. {
  6313. return $this->medium;
  6314. }
  6315. else
  6316. {
  6317. return null;
  6318. }
  6319. }
  6320. function get_player()
  6321. {
  6322. if ($this->player !== null)
  6323. {
  6324. return $this->player;
  6325. }
  6326. else
  6327. {
  6328. return null;
  6329. }
  6330. }
  6331. function get_rating($key = 0)
  6332. {
  6333. $ratings = $this->get_ratings();
  6334. if (isset($ratings[$key]))
  6335. {
  6336. return $ratings[$key];
  6337. }
  6338. else
  6339. {
  6340. return null;
  6341. }
  6342. }
  6343. function get_ratings()
  6344. {
  6345. if ($this->ratings !== null)
  6346. {
  6347. return $this->ratings;
  6348. }
  6349. else
  6350. {
  6351. return null;
  6352. }
  6353. }
  6354. function get_restriction($key = 0)
  6355. {
  6356. $restrictions = $this->get_restrictions();
  6357. if (isset($restrictions[$key]))
  6358. {
  6359. return $restrictions[$key];
  6360. }
  6361. else
  6362. {
  6363. return null;
  6364. }
  6365. }
  6366. function get_restrictions()
  6367. {
  6368. if ($this->restrictions !== null)
  6369. {
  6370. return $this->restrictions;
  6371. }
  6372. else
  6373. {
  6374. return null;
  6375. }
  6376. }
  6377. function get_sampling_rate()
  6378. {
  6379. if ($this->samplingrate !== null)
  6380. {
  6381. return $this->samplingrate;
  6382. }
  6383. else
  6384. {
  6385. return null;
  6386. }
  6387. }
  6388. function get_size()
  6389. {
  6390. $length = $this->get_length();
  6391. if ($length !== null)
  6392. {
  6393. return round($length/1048576, 2);
  6394. }
  6395. else
  6396. {
  6397. return null;
  6398. }
  6399. }
  6400. function get_thumbnail($key = 0)
  6401. {
  6402. $thumbnails = $this->get_thumbnails();
  6403. if (isset($thumbnails[$key]))
  6404. {
  6405. return $thumbnails[$key];
  6406. }
  6407. else
  6408. {
  6409. return null;
  6410. }
  6411. }
  6412. function get_thumbnails()
  6413. {
  6414. if ($this->thumbnails !== null)
  6415. {
  6416. return $this->thumbnails;
  6417. }
  6418. else
  6419. {
  6420. return null;
  6421. }
  6422. }
  6423. function get_title()
  6424. {
  6425. if ($this->title !== null)
  6426. {
  6427. return $this->title;
  6428. }
  6429. else
  6430. {
  6431. return null;
  6432. }
  6433. }
  6434. function get_type()
  6435. {
  6436. if ($this->type !== null)
  6437. {
  6438. return $this->type;
  6439. }
  6440. else
  6441. {
  6442. return null;
  6443. }
  6444. }
  6445. function get_width()
  6446. {
  6447. if ($this->width !== null)
  6448. {
  6449. return $this->width;
  6450. }
  6451. else
  6452. {
  6453. return null;
  6454. }
  6455. }
  6456. function native_embed($options='')
  6457. {
  6458. return $this->embed($options, true);
  6459. }
  6460. /**
  6461. * @todo If the dimensions for media:content are defined, use them when width/height are set to 'auto'.
  6462. */
  6463. function embed($options = '', $native = false)
  6464. {
  6465. // Set up defaults
  6466. $audio = '';
  6467. $video = '';
  6468. $alt = '';
  6469. $altclass = '';
  6470. $loop = 'false';
  6471. $width = 'auto';
  6472. $height = 'auto';
  6473. $bgcolor = '#ffffff';
  6474. $mediaplayer = '';
  6475. $widescreen = false;
  6476. $handler = $this->get_handler();
  6477. $type = $this->get_real_type();
  6478. // Process options and reassign values as necessary
  6479. if (is_array($options))
  6480. {
  6481. extract($options);
  6482. }
  6483. else
  6484. {
  6485. $options = explode(',', $options);
  6486. foreach($options as $option)
  6487. {
  6488. $opt = explode(':', $option, 2);
  6489. if (isset($opt[0], $opt[1]))
  6490. {
  6491. $opt[0] = trim($opt[0]);
  6492. $opt[1] = trim($opt[1]);
  6493. switch ($opt[0])
  6494. {
  6495. case 'audio':
  6496. $audio = $opt[1];
  6497. break;
  6498. case 'video':
  6499. $video = $opt[1];
  6500. break;
  6501. case 'alt':
  6502. $alt = $opt[1];
  6503. break;
  6504. case 'altclass':
  6505. $altclass = $opt[1];
  6506. break;
  6507. case 'loop':
  6508. $loop = $opt[1];
  6509. break;
  6510. case 'width':
  6511. $width = $opt[1];
  6512. break;
  6513. case 'height':
  6514. $height = $opt[1];
  6515. break;
  6516. case 'bgcolor':
  6517. $bgcolor = $opt[1];
  6518. break;
  6519. case 'mediaplayer':
  6520. $mediaplayer = $opt[1];
  6521. break;
  6522. case 'widescreen':
  6523. $widescreen = $opt[1];
  6524. break;
  6525. }
  6526. }
  6527. }
  6528. }
  6529. $mime = explode('/', $type, 2);
  6530. $mime = $mime[0];
  6531. // Process values for 'auto'
  6532. if ($width === 'auto')
  6533. {
  6534. if ($mime === 'video')
  6535. {
  6536. if ($height === 'auto')
  6537. {
  6538. $width = 480;
  6539. }
  6540. elseif ($widescreen)
  6541. {
  6542. $width = round((intval($height)/9)*16);
  6543. }
  6544. else
  6545. {
  6546. $width = round((intval($height)/3)*4);
  6547. }
  6548. }
  6549. else
  6550. {
  6551. $width = '100%';
  6552. }
  6553. }
  6554. if ($height === 'auto')
  6555. {
  6556. if ($mime === 'audio')
  6557. {
  6558. $height = 0;
  6559. }
  6560. elseif ($mime === 'video')
  6561. {
  6562. if ($width === 'auto')
  6563. {
  6564. if ($widescreen)
  6565. {
  6566. $height = 270;
  6567. }
  6568. else
  6569. {
  6570. $height = 360;
  6571. }
  6572. }
  6573. elseif ($widescreen)
  6574. {
  6575. $height = round((intval($width)/16)*9);
  6576. }
  6577. else
  6578. {
  6579. $height = round((intval($width)/4)*3);
  6580. }
  6581. }
  6582. else
  6583. {
  6584. $height = 376;
  6585. }
  6586. }
  6587. elseif ($mime === 'audio')
  6588. {
  6589. $height = 0;
  6590. }
  6591. // Set proper placeholder value
  6592. if ($mime === 'audio')
  6593. {
  6594. $placeholder = $audio;
  6595. }
  6596. elseif ($mime === 'video')
  6597. {
  6598. $placeholder = $video;
  6599. }
  6600. $embed = '';
  6601. // Make sure the JS library is included
  6602. if (!$native)
  6603. {
  6604. static $javascript_outputted = null;
  6605. if (!$javascript_outputted && $this->javascript)
  6606. {
  6607. $embed .= '<script type="text/javascript" src="?' . htmlspecialchars($this->javascript) . '"></script>';
  6608. $javascript_outputted = true;
  6609. }
  6610. }
  6611. // Odeo Feed MP3's
  6612. if ($handler === 'odeo')
  6613. {
  6614. if ($native)
  6615. {
  6616. $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>';
  6617. }
  6618. else
  6619. {
  6620. $embed .= '<script type="text/javascript">embed_odeo("' . $this->get_link() . '");</script>';
  6621. }
  6622. }
  6623. // Flash
  6624. elseif ($handler === 'flash')
  6625. {
  6626. if ($native)
  6627. {
  6628. $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>";
  6629. }
  6630. else
  6631. {
  6632. $embed .= "<script type='text/javascript'>embed_flash('$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$loop', '$type');</script>";
  6633. }
  6634. }
  6635. // Flash Media Player file types.
  6636. // Preferred handler for MP3 file types.
  6637. elseif ($handler === 'fmedia' || ($handler === 'mp3' && $mediaplayer !== ''))
  6638. {
  6639. $height += 20;
  6640. if ($native)
  6641. {
  6642. $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>";
  6643. }
  6644. else
  6645. {
  6646. $embed .= "<script type='text/javascript'>embed_flv('$width', '$height', '" . rawurlencode($this->get_link().'?file_extension=.'.$this->get_extension()) . "', '$placeholder', '$loop', '$mediaplayer');</script>";
  6647. }
  6648. }
  6649. // QuickTime 7 file types. Need to test with QuickTime 6.
  6650. // Only handle MP3's if the Flash Media Player is not present.
  6651. elseif ($handler === 'quicktime' || ($handler === 'mp3' && $mediaplayer === ''))
  6652. {
  6653. $height += 16;
  6654. if ($native)
  6655. {
  6656. if ($placeholder !== '')
  6657. {
  6658. $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>";
  6659. }
  6660. else
  6661. {
  6662. $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>";
  6663. }
  6664. }
  6665. else
  6666. {
  6667. $embed .= "<script type='text/javascript'>embed_quicktime('$type', '$bgcolor', '$width', '$height', '" . $this->get_link() . "', '$placeholder', '$loop');</script>";
  6668. }
  6669. }
  6670. // Windows Media
  6671. elseif ($handler === 'wmedia')
  6672. {
  6673. $height += 45;
  6674. if ($native)
  6675. {
  6676. $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>";
  6677. }
  6678. else
  6679. {
  6680. $embed .= "<script type='text/javascript'>embed_wmedia('$width', '$height', '" . $this->get_link() . "');</script>";
  6681. }
  6682. }
  6683. // Everything else
  6684. else $embed .= '<a href="' . $this->get_link() . '" class="' . $altclass . '">' . $alt . '</a>';
  6685. return $embed;
  6686. }
  6687. function get_real_type($find_handler = false)
  6688. {
  6689. // If it's Odeo, let's get it out of the way.
  6690. if (substr(strtolower($this->get_link()), 0, 15) === 'http://odeo.com')
  6691. {
  6692. return 'odeo';
  6693. }
  6694. // Mime-types by handler.
  6695. $types_flash = array('application/x-shockwave-flash', 'application/futuresplash'); // Flash
  6696. $types_fmedia = array('video/flv', 'video/x-flv','flv-application/octet-stream'); // Flash Media Player
  6697. $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
  6698. $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
  6699. $types_mp3 = array('audio/mp3', 'audio/x-mp3', 'audio/mpeg', 'audio/x-mpeg'); // MP3
  6700. if ($this->get_type() !== null)
  6701. {
  6702. $type = strtolower($this->type);
  6703. }
  6704. else
  6705. {
  6706. $type = null;
  6707. }
  6708. // If we encounter an unsupported mime-type, check the file extension and guess intelligently.
  6709. if (!in_array($type, array_merge($types_flash, $types_fmedia, $types_quicktime, $types_wmedia, $types_mp3)))
  6710. {
  6711. switch (strtolower($this->get_extension()))
  6712. {
  6713. // Audio mime-types
  6714. case 'aac':
  6715. case 'adts':
  6716. $type = 'audio/acc';
  6717. break;
  6718. case 'aif':
  6719. case 'aifc':
  6720. case 'aiff':
  6721. case 'cdda':
  6722. $type = 'audio/aiff';
  6723. break;
  6724. case 'bwf':
  6725. $type = 'audio/wav';
  6726. break;
  6727. case 'kar':
  6728. case 'mid':
  6729. case 'midi':
  6730. case 'smf':
  6731. $type = 'audio/midi';
  6732. break;
  6733. case 'm4a':
  6734. $type = 'audio/x-m4a';
  6735. break;
  6736. case 'mp3':
  6737. case 'swa':
  6738. $type = 'audio/mp3';
  6739. break;
  6740. case 'wav':
  6741. $type = 'audio/wav';
  6742. break;
  6743. case 'wax':
  6744. $type = 'audio/x-ms-wax';
  6745. break;
  6746. case 'wma':
  6747. $type = 'audio/x-ms-wma';
  6748. break;
  6749. // Video mime-types
  6750. case '3gp':
  6751. case '3gpp':
  6752. $type = 'video/3gpp';
  6753. break;
  6754. case '3g2':
  6755. case '3gp2':
  6756. $type = 'video/3gpp2';
  6757. break;
  6758. case 'asf':
  6759. $type = 'video/x-ms-asf';
  6760. break;
  6761. case 'flv':
  6762. $type = 'video/x-flv';
  6763. break;
  6764. case 'm1a':
  6765. case 'm1s':
  6766. case 'm1v':
  6767. case 'm15':
  6768. case 'm75':
  6769. case 'mp2':
  6770. case 'mpa':
  6771. case 'mpeg':
  6772. case 'mpg':
  6773. case 'mpm':
  6774. case 'mpv':
  6775. $type = 'video/mpeg';
  6776. break;
  6777. case 'm4v':
  6778. $type = 'video/x-m4v';
  6779. break;
  6780. case 'mov':
  6781. case 'qt':
  6782. $type = 'video/quicktime';
  6783. break;
  6784. case 'mp4':
  6785. case 'mpg4':
  6786. $type = 'video/mp4';
  6787. break;
  6788. case 'sdv':
  6789. $type = 'video/sd-video';
  6790. break;
  6791. case 'wm':
  6792. $type = 'video/x-ms-wm';
  6793. break;
  6794. case 'wmv':
  6795. $type = 'video/x-ms-wmv';
  6796. break;
  6797. case 'wvx':
  6798. $type = 'video/x-ms-wvx';
  6799. break;
  6800. // Flash mime-types
  6801. case 'spl':
  6802. $type = 'application/futuresplash';
  6803. break;
  6804. case 'swf':
  6805. $type = 'application/x-shockwave-flash';
  6806. break;
  6807. }
  6808. }
  6809. if ($find_handler)
  6810. {
  6811. if (in_array($type, $types_flash))
  6812. {
  6813. return 'flash';
  6814. }
  6815. elseif (in_array($type, $types_fmedia))
  6816. {
  6817. return 'fmedia';
  6818. }
  6819. elseif (in_array($type, $types_quicktime))
  6820. {
  6821. return 'quicktime';
  6822. }
  6823. elseif (in_array($type, $types_wmedia))
  6824. {
  6825. return 'wmedia';
  6826. }
  6827. elseif (in_array($type, $types_mp3))
  6828. {
  6829. return 'mp3';
  6830. }
  6831. else
  6832. {
  6833. return null;
  6834. }
  6835. }
  6836. else
  6837. {
  6838. return $type;
  6839. }
  6840. }
  6841. }
  6842. class SimplePie_Caption
  6843. {
  6844. var $type;
  6845. var $lang;
  6846. var $startTime;
  6847. var $endTime;
  6848. var $text;
  6849. // Constructor, used to input the data
  6850. function SimplePie_Caption($type = null, $lang = null, $startTime = null, $endTime = null, $text = null)
  6851. {
  6852. $this->type = $type;
  6853. $this->lang = $lang;
  6854. $this->startTime = $startTime;
  6855. $this->endTime = $endTime;
  6856. $this->text = $text;
  6857. }
  6858. function __toString()
  6859. {
  6860. // There is no $this->data here
  6861. return md5(serialize($this));
  6862. }
  6863. function get_endtime()
  6864. {
  6865. if ($this->endTime !== null)
  6866. {
  6867. return $this->endTime;
  6868. }
  6869. else
  6870. {
  6871. return null;
  6872. }
  6873. }
  6874. function get_language()
  6875. {
  6876. if ($this->lang !== null)
  6877. {
  6878. return $this->lang;
  6879. }
  6880. else
  6881. {
  6882. return null;
  6883. }
  6884. }
  6885. function get_starttime()
  6886. {
  6887. if ($this->startTime !== null)
  6888. {
  6889. return $this->startTime;
  6890. }
  6891. else
  6892. {
  6893. return null;
  6894. }
  6895. }
  6896. function get_text()
  6897. {
  6898. if ($this->text !== null)
  6899. {
  6900. return $this->text;
  6901. }
  6902. else
  6903. {
  6904. return null;
  6905. }
  6906. }
  6907. function get_type()
  6908. {
  6909. if ($this->type !== null)
  6910. {
  6911. return $this->type;
  6912. }
  6913. else
  6914. {
  6915. return null;
  6916. }
  6917. }
  6918. }
  6919. class SimplePie_Credit
  6920. {
  6921. var $role;
  6922. var $scheme;
  6923. var $name;
  6924. // Constructor, used to input the data
  6925. function SimplePie_Credit($role = null, $scheme = null, $name = null)
  6926. {
  6927. $this->role = $role;
  6928. $this->scheme = $scheme;
  6929. $this->name = $name;
  6930. }
  6931. function __toString()
  6932. {
  6933. // There is no $this->data here
  6934. return md5(serialize($this));
  6935. }
  6936. function get_role()
  6937. {
  6938. if ($this->role !== null)
  6939. {
  6940. return $this->role;
  6941. }
  6942. else
  6943. {
  6944. return null;
  6945. }
  6946. }
  6947. function get_scheme()
  6948. {
  6949. if ($this->scheme !== null)
  6950. {
  6951. return $this->scheme;
  6952. }
  6953. else
  6954. {
  6955. return null;
  6956. }
  6957. }
  6958. function get_name()
  6959. {
  6960. if ($this->name !== null)
  6961. {
  6962. return $this->name;
  6963. }
  6964. else
  6965. {
  6966. return null;
  6967. }
  6968. }
  6969. }
  6970. class SimplePie_Copyright
  6971. {
  6972. var $url;
  6973. var $label;
  6974. // Constructor, used to input the data
  6975. function SimplePie_Copyright($url = null, $label = null)
  6976. {
  6977. $this->url = $url;
  6978. $this->label = $label;
  6979. }
  6980. function __toString()
  6981. {
  6982. // There is no $this->data here
  6983. return md5(serialize($this));
  6984. }
  6985. function get_url()
  6986. {
  6987. if ($this->url !== null)
  6988. {
  6989. return $this->url;
  6990. }
  6991. else
  6992. {
  6993. return null;
  6994. }
  6995. }
  6996. function get_attribution()
  6997. {
  6998. if ($this->label !== null)
  6999. {
  7000. return $this->label;
  7001. }
  7002. else
  7003. {
  7004. return null;
  7005. }
  7006. }
  7007. }
  7008. class SimplePie_Rating
  7009. {
  7010. var $scheme;
  7011. var $value;
  7012. // Constructor, used to input the data
  7013. function SimplePie_Rating($scheme = null, $value = null)
  7014. {
  7015. $this->scheme = $scheme;
  7016. $this->value = $value;
  7017. }
  7018. function __toString()
  7019. {
  7020. // There is no $this->data here
  7021. return md5(serialize($this));
  7022. }
  7023. function get_scheme()
  7024. {
  7025. if ($this->scheme !== null)
  7026. {
  7027. return $this->scheme;
  7028. }
  7029. else
  7030. {
  7031. return null;
  7032. }
  7033. }
  7034. function get_value()
  7035. {
  7036. if ($this->value !== null)
  7037. {
  7038. return $this->value;
  7039. }
  7040. else
  7041. {
  7042. return null;
  7043. }
  7044. }
  7045. }
  7046. class SimplePie_Restriction
  7047. {
  7048. var $relationship;
  7049. var $type;
  7050. var $value;
  7051. // Constructor, used to input the data
  7052. function SimplePie_Restriction($relationship = null, $type = null, $value = null)
  7053. {
  7054. $this->relationship = $relationship;
  7055. $this->type = $type;
  7056. $this->value = $value;
  7057. }
  7058. function __toString()
  7059. {
  7060. // There is no $this->data here
  7061. return md5(serialize($this));
  7062. }
  7063. function get_relationship()
  7064. {
  7065. if ($this->relationship !== null)
  7066. {
  7067. return $this->relationship;
  7068. }
  7069. else
  7070. {
  7071. return null;
  7072. }
  7073. }
  7074. function get_type()
  7075. {
  7076. if ($this->type !== null)
  7077. {
  7078. return $this->type;
  7079. }
  7080. else
  7081. {
  7082. return null;
  7083. }
  7084. }
  7085. function get_value()
  7086. {
  7087. if ($this->value !== null)
  7088. {
  7089. return $this->value;
  7090. }
  7091. else
  7092. {
  7093. return null;
  7094. }
  7095. }
  7096. }
  7097. /**
  7098. * @todo Move to properly supporting RFC2616 (HTTP/1.1)
  7099. */
  7100. class SimplePie_File
  7101. {
  7102. var $url;
  7103. var $useragent;
  7104. var $success = true;
  7105. var $headers = array();
  7106. var $body;
  7107. var $status_code;
  7108. var $redirects = 0;
  7109. var $error;
  7110. var $method = SIMPLEPIE_FILE_SOURCE_NONE;
  7111. function SimplePie_File($url, $timeout = 10, $redirects = 5, $headers = null, $useragent = null, $force_fsockopen = false)
  7112. {
  7113. if (class_exists('idna_convert'))
  7114. {
  7115. $idn = new idna_convert;
  7116. $parsed = SimplePie_Misc::parse_url($url);
  7117. $url = SimplePie_Misc::compress_parse_url($parsed['scheme'], $idn->encode($parsed['authority']), $parsed['path'], $parsed['query'], $parsed['fragment']);
  7118. }
  7119. $this->url = $url;
  7120. $this->useragent = $useragent;
  7121. if (preg_match('/^http(s)?:\/\//i', $url))
  7122. {
  7123. if ($useragent === null)
  7124. {
  7125. $useragent = ini_get('user_agent');
  7126. $this->useragent = $useragent;
  7127. }
  7128. if (!is_array($headers))
  7129. {
  7130. $headers = array();
  7131. }
  7132. if (!$force_fsockopen && function_exists('curl_exec'))
  7133. {
  7134. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_CURL;
  7135. $fp = curl_init();
  7136. $headers2 = array();
  7137. foreach ($headers as $key => $value)
  7138. {
  7139. $headers2[] = "$key: $value";
  7140. }
  7141. if (version_compare(SimplePie_Misc::get_curl_version(), '7.10.5', '>='))
  7142. {
  7143. curl_setopt($fp, CURLOPT_ENCODING, '');
  7144. }
  7145. curl_setopt($fp, CURLOPT_URL, $url);
  7146. curl_setopt($fp, CURLOPT_HEADER, 1);
  7147. curl_setopt($fp, CURLOPT_RETURNTRANSFER, 1);
  7148. curl_setopt($fp, CURLOPT_TIMEOUT, $timeout);
  7149. curl_setopt($fp, CURLOPT_CONNECTTIMEOUT, $timeout);
  7150. curl_setopt($fp, CURLOPT_REFERER, $url);
  7151. curl_setopt($fp, CURLOPT_USERAGENT, $useragent);
  7152. curl_setopt($fp, CURLOPT_HTTPHEADER, $headers2);
  7153. if (!ini_get('open_basedir') && !ini_get('safe_mode') && version_compare(SimplePie_Misc::get_curl_version(), '7.15.2', '>='))
  7154. {
  7155. curl_setopt($fp, CURLOPT_FOLLOWLOCATION, 1);
  7156. curl_setopt($fp, CURLOPT_MAXREDIRS, $redirects);
  7157. }
  7158. $this->headers = curl_exec($fp);
  7159. if (curl_errno($fp) === 23 || curl_errno($fp) === 61)
  7160. {
  7161. curl_setopt($fp, CURLOPT_ENCODING, 'none');
  7162. $this->headers = curl_exec($fp);
  7163. }
  7164. if (curl_errno($fp))
  7165. {
  7166. $this->error = 'cURL error ' . curl_errno($fp) . ': ' . curl_error($fp);
  7167. $this->success = false;
  7168. }
  7169. else
  7170. {
  7171. $info = curl_getinfo($fp);
  7172. curl_close($fp);
  7173. $this->headers = explode("\r\n\r\n", $this->headers, $info['redirect_count'] + 1);
  7174. $this->headers = array_pop($this->headers);
  7175. $parser = new SimplePie_HTTP_Parser($this->headers);
  7176. if ($parser->parse())
  7177. {
  7178. $this->headers = $parser->headers;
  7179. $this->body = $parser->body;
  7180. $this->status_code = $parser->status_code;
  7181. 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)
  7182. {
  7183. $this->redirects++;
  7184. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  7185. return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  7186. }
  7187. }
  7188. }
  7189. }
  7190. else
  7191. {
  7192. $this->method = SIMPLEPIE_FILE_SOURCE_REMOTE | SIMPLEPIE_FILE_SOURCE_FSOCKOPEN;
  7193. $url_parts = parse_url($url);
  7194. if (isset($url_parts['scheme']) && strtolower($url_parts['scheme']) === 'https')
  7195. {
  7196. $url_parts['host'] = "ssl://$url_parts[host]";
  7197. $url_parts['port'] = 443;
  7198. }
  7199. if (!isset($url_parts['port']))
  7200. {
  7201. $url_parts['port'] = 80;
  7202. }
  7203. $fp = @fsockopen($url_parts['host'], $url_parts['port'], $errno, $errstr, $timeout);
  7204. if (!$fp)
  7205. {
  7206. $this->error = 'fsockopen error: ' . $errstr;
  7207. $this->success = false;
  7208. }
  7209. else
  7210. {
  7211. stream_set_timeout($fp, $timeout);
  7212. if (isset($url_parts['path']))
  7213. {
  7214. if (isset($url_parts['query']))
  7215. {
  7216. $get = "$url_parts[path]?$url_parts[query]";
  7217. }
  7218. else
  7219. {
  7220. $get = $url_parts['path'];
  7221. }
  7222. }
  7223. else
  7224. {
  7225. $get = '/';
  7226. }
  7227. $out = "GET $get HTTP/1.0\r\n";
  7228. $out .= "Host: $url_parts[host]\r\n";
  7229. $out .= "User-Agent: $useragent\r\n";
  7230. if (extension_loaded('zlib'))
  7231. {
  7232. $out .= "Accept-Encoding: x-gzip,gzip,deflate\r\n";
  7233. }
  7234. if (isset($url_parts['user']) && isset($url_parts['pass']))
  7235. {
  7236. $out .= "Authorization: Basic " . base64_encode("$url_parts[user]:$url_parts[pass]") . "\r\n";
  7237. }
  7238. foreach ($headers as $key => $value)
  7239. {
  7240. $out .= "$key: $value\r\n";
  7241. }
  7242. $out .= "Connection: Close\r\n\r\n";
  7243. fwrite($fp, $out);
  7244. $info = stream_get_meta_data($fp);
  7245. $this->headers = '';
  7246. while (!$info['eof'] && !$info['timed_out'])
  7247. {
  7248. $this->headers .= fread($fp, 1160);
  7249. $info = stream_get_meta_data($fp);
  7250. }
  7251. if (!$info['timed_out'])
  7252. {
  7253. $parser = new SimplePie_HTTP_Parser($this->headers);
  7254. if ($parser->parse())
  7255. {
  7256. $this->headers = $parser->headers;
  7257. $this->body = $parser->body;
  7258. $this->status_code = $parser->status_code;
  7259. 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)
  7260. {
  7261. $this->redirects++;
  7262. $location = SimplePie_Misc::absolutize_url($this->headers['location'], $url);
  7263. return $this->SimplePie_File($location, $timeout, $redirects, $headers, $useragent, $force_fsockopen);
  7264. }
  7265. if (isset($this->headers['content-encoding']))
  7266. {
  7267. // Hey, we act dumb elsewhere, so let's do that here too
  7268. switch (strtolower(trim($this->headers['content-encoding'], "\x09\x0A\x0D\x20")))
  7269. {
  7270. case 'gzip':
  7271. case 'x-gzip':
  7272. $decoder = new SimplePie_gzdecode($this->body);
  7273. if (!$decoder->parse())
  7274. {
  7275. $this->error = 'Unable to decode HTTP "gzip" stream';
  7276. $this->success = false;
  7277. }
  7278. else
  7279. {
  7280. $this->body = $decoder->data;
  7281. }
  7282. break;
  7283. case 'deflate':
  7284. if (($body = gzuncompress($this->body)) === false)
  7285. {
  7286. if (($body = gzinflate($this->body)) === false)
  7287. {
  7288. $this->error = 'Unable to decode HTTP "deflate" stream';
  7289. $this->success = false;
  7290. }
  7291. }
  7292. $this->body = $body;
  7293. break;
  7294. default:
  7295. $this->error = 'Unknown content coding';
  7296. $this->success = false;
  7297. }
  7298. }
  7299. }
  7300. }
  7301. else
  7302. {
  7303. $this->error = 'fsocket timed out';
  7304. $this->success = false;
  7305. }
  7306. fclose($fp);
  7307. }
  7308. }
  7309. }
  7310. else
  7311. {
  7312. $this->method = SIMPLEPIE_FILE_SOURCE_LOCAL | SIMPLEPIE_FILE_SOURCE_FILE_GET_CONTENTS;
  7313. if (!$this->body = file_get_contents($url))
  7314. {
  7315. $this->error = 'file_get_contents could not read the file';
  7316. $this->success = false;
  7317. }
  7318. }
  7319. }
  7320. }
  7321. /**
  7322. * HTTP Response Parser
  7323. *
  7324. * @package SimplePie
  7325. */
  7326. class SimplePie_HTTP_Parser
  7327. {
  7328. /**
  7329. * HTTP Version
  7330. *
  7331. * @access public
  7332. * @var float
  7333. */
  7334. var $http_version = 0.0;
  7335. /**
  7336. * Status code
  7337. *
  7338. * @access public
  7339. * @var int
  7340. */
  7341. var $status_code = 0;
  7342. /**
  7343. * Reason phrase
  7344. *
  7345. * @access public
  7346. * @var string
  7347. */
  7348. var $reason = '';
  7349. /**
  7350. * Key/value pairs of the headers
  7351. *
  7352. * @access public
  7353. * @var array
  7354. */
  7355. var $headers = array();
  7356. /**
  7357. * Body of the response
  7358. *
  7359. * @access public
  7360. * @var string
  7361. */
  7362. var $body = '';
  7363. /**
  7364. * Current state of the state machine
  7365. *
  7366. * @access private
  7367. * @var string
  7368. */
  7369. var $state = 'http_version';
  7370. /**
  7371. * Input data
  7372. *
  7373. * @access private
  7374. * @var string
  7375. */
  7376. var $data = '';
  7377. /**
  7378. * Input data length (to avoid calling strlen() everytime this is needed)
  7379. *
  7380. * @access private
  7381. * @var int
  7382. */
  7383. var $data_length = 0;
  7384. /**
  7385. * Current position of the pointer
  7386. *
  7387. * @var int
  7388. * @access private
  7389. */
  7390. var $position = 0;
  7391. /**
  7392. * Name of the hedaer currently being parsed
  7393. *
  7394. * @access private
  7395. * @var string
  7396. */
  7397. var $name = '';
  7398. /**
  7399. * Value of the hedaer currently being parsed
  7400. *
  7401. * @access private
  7402. * @var string
  7403. */
  7404. var $value = '';
  7405. /**
  7406. * Create an instance of the class with the input data
  7407. *
  7408. * @access public
  7409. * @param string $data Input data
  7410. */
  7411. function SimplePie_HTTP_Parser($data)
  7412. {
  7413. $this->data = $data;
  7414. $this->data_length = strlen($this->data);
  7415. }
  7416. /**
  7417. * Parse the input data
  7418. *
  7419. * @access public
  7420. * @return bool true on success, false on failure
  7421. */
  7422. function parse()
  7423. {
  7424. while ($this->state && $this->state !== 'emit' && $this->has_data())
  7425. {
  7426. $state = $this->state;
  7427. $this->$state();
  7428. }
  7429. $this->data = '';
  7430. if ($this->state === 'emit' || $this->state === 'body')
  7431. {
  7432. return true;
  7433. }
  7434. else
  7435. {
  7436. $this->http_version = '';
  7437. $this->status_code = '';
  7438. $this->reason = '';
  7439. $this->headers = array();
  7440. $this->body = '';
  7441. return false;
  7442. }
  7443. }
  7444. /**
  7445. * Check whether there is data beyond the pointer
  7446. *
  7447. * @access private
  7448. * @return bool true if there is further data, false if not
  7449. */
  7450. function has_data()
  7451. {
  7452. return (bool) ($this->position < $this->data_length);
  7453. }
  7454. /**
  7455. * See if the next character is LWS
  7456. *
  7457. * @access private
  7458. * @return bool true if the next character is LWS, false if not
  7459. */
  7460. function is_linear_whitespace()
  7461. {
  7462. return (bool) ($this->data[$this->position] === "\x09"
  7463. || $this->data[$this->position] === "\x20"
  7464. || ($this->data[$this->position] === "\x0A"
  7465. && isset($this->data[$this->position + 1])
  7466. && ($this->data[$this->position + 1] === "\x09" || $this->data[$this->position + 1] === "\x20")));
  7467. }
  7468. /**
  7469. * Parse the HTTP version
  7470. *
  7471. * @access private
  7472. */
  7473. function http_version()
  7474. {
  7475. if (strpos($this->data, "\x0A") !== false && strtoupper(substr($this->data, 0, 5)) === 'HTTP/')
  7476. {
  7477. $len = strspn($this->data, '0123456789.', 5);
  7478. $this->http_version = substr($this->data, 5, $len);
  7479. $this->position += 5 + $len;
  7480. if (substr_count($this->http_version, '.') <= 1)
  7481. {
  7482. $this->http_version = (float) $this->http_version;
  7483. $this->position += strspn($this->data, "\x09\x20", $this->position);
  7484. $this->state = 'status';
  7485. }
  7486. else
  7487. {
  7488. $this->state = false;
  7489. }
  7490. }
  7491. else
  7492. {
  7493. $this->state = false;
  7494. }
  7495. }
  7496. /**
  7497. * Parse the status code
  7498. *
  7499. * @access private
  7500. */
  7501. function status()
  7502. {
  7503. if ($len = strspn($this->data, '0123456789', $this->position))
  7504. {
  7505. $this->status_code = (int) substr($this->data, $this->position, $len);
  7506. $this->position += $len;
  7507. $this->state = 'reason';
  7508. }
  7509. else
  7510. {
  7511. $this->state = false;
  7512. }
  7513. }
  7514. /**
  7515. * Parse the reason phrase
  7516. *
  7517. * @access private
  7518. */
  7519. function reason()
  7520. {
  7521. $len = strcspn($this->data, "\x0A", $this->position);
  7522. $this->reason = trim(substr($this->data, $this->position, $len), "\x09\x0D\x20");
  7523. $this->position += $len + 1;
  7524. $this->state = 'new_line';
  7525. }
  7526. /**
  7527. * Deal with a new line, shifting data around as needed
  7528. *
  7529. * @access private
  7530. */
  7531. function new_line()
  7532. {
  7533. $this->value = trim($this->value, "\x0D\x20");
  7534. if ($this->name !== '' && $this->value !== '')
  7535. {
  7536. $this->name = strtolower($this->name);
  7537. if (isset($this->headers[$this->name]))
  7538. {
  7539. $this->headers[$this->name] .= ', ' . $this->value;
  7540. }
  7541. else
  7542. {
  7543. $this->headers[$this->name] = $this->value;
  7544. }
  7545. }
  7546. $this->name = '';
  7547. $this->value = '';
  7548. if (substr($this->data[$this->position], 0, 2) === "\x0D\x0A")
  7549. {
  7550. $this->position += 2;
  7551. $this->state = 'body';
  7552. }
  7553. elseif ($this->data[$this->position] === "\x0A")
  7554. {
  7555. $this->position++;
  7556. $this->state = 'body';
  7557. }
  7558. else
  7559. {
  7560. $this->state = 'name';
  7561. }
  7562. }
  7563. /**
  7564. * Parse a header name
  7565. *
  7566. * @access private
  7567. */
  7568. function name()
  7569. {
  7570. $len = strcspn($this->data, "\x0A:", $this->position);
  7571. if (isset($this->data[$this->position + $len]))
  7572. {
  7573. if ($this->data[$this->position + $len] === "\x0A")
  7574. {
  7575. $this->position += $len;
  7576. $this->state = 'new_line';
  7577. }
  7578. else
  7579. {
  7580. $this->name = substr($this->data, $this->position, $len);
  7581. $this->position += $len + 1;
  7582. $this->state = 'value';
  7583. }
  7584. }
  7585. else
  7586. {
  7587. $this->state = false;
  7588. }
  7589. }
  7590. /**
  7591. * Parse LWS, replacing consecutive LWS characters with a single space
  7592. *
  7593. * @access private
  7594. */
  7595. function linear_whitespace()
  7596. {
  7597. do
  7598. {
  7599. if (substr($this->data, $this->position, 2) === "\x0D\x0A")
  7600. {
  7601. $this->position += 2;
  7602. }
  7603. elseif ($this->data[$this->position] === "\x0A")
  7604. {
  7605. $this->position++;
  7606. }
  7607. $this->position += strspn($this->data, "\x09\x20", $this->position);
  7608. } while ($this->has_data() && $this->is_linear_whitespace());
  7609. $this->value .= "\x20";
  7610. }
  7611. /**
  7612. * See what state to move to while within non-quoted header values
  7613. *
  7614. * @access private
  7615. */
  7616. function value()
  7617. {
  7618. if ($this->is_linear_whitespace())
  7619. {
  7620. $this->linear_whitespace();
  7621. }
  7622. else
  7623. {
  7624. switch ($this->data[$this->position])
  7625. {
  7626. case '"':
  7627. $this->position++;
  7628. $this->state = 'quote';
  7629. break;
  7630. case "\x0A":
  7631. $this->position++;
  7632. $this->state = 'new_line';
  7633. break;
  7634. default:
  7635. $this->state = 'value_char';
  7636. break;
  7637. }
  7638. }
  7639. }
  7640. /**
  7641. * Parse a header value while outside quotes
  7642. *
  7643. * @access private
  7644. */
  7645. function value_char()
  7646. {
  7647. $len = strcspn($this->data, "\x09\x20\x0A\"", $this->position);
  7648. $this->value .= substr($this->data, $this->position, $len);
  7649. $this->position += $len;
  7650. $this->state = 'value';
  7651. }
  7652. /**
  7653. * See what state to move to while within quoted header values
  7654. *
  7655. * @access private
  7656. */
  7657. function quote()
  7658. {
  7659. if ($this->is_linear_whitespace())
  7660. {
  7661. $this->linear_whitespace();
  7662. }
  7663. else
  7664. {
  7665. switch ($this->data[$this->position])
  7666. {
  7667. case '"':
  7668. $this->position++;
  7669. $this->state = 'value';
  7670. break;
  7671. case "\x0A":
  7672. $this->position++;
  7673. $this->state = 'new_line';
  7674. break;
  7675. case '\\':
  7676. $this->position++;
  7677. $this->state = 'quote_escaped';
  7678. break;
  7679. default:
  7680. $this->state = 'quote_char';
  7681. break;
  7682. }
  7683. }
  7684. }
  7685. /**
  7686. * Parse a header value while within quotes
  7687. *
  7688. * @access private
  7689. */
  7690. function quote_char()
  7691. {
  7692. $len = strcspn($this->data, "\x09\x20\x0A\"\\", $this->position);
  7693. $this->value .= substr($this->data, $this->position, $len);
  7694. $this->position += $len;
  7695. $this->state = 'value';
  7696. }
  7697. /**
  7698. * Parse an escaped character within quotes
  7699. *
  7700. * @access private
  7701. */
  7702. function quote_escaped()
  7703. {
  7704. $this->value .= $this->data[$this->position];
  7705. $this->position++;
  7706. $this->state = 'quote';
  7707. }
  7708. /**
  7709. * Parse the body
  7710. *
  7711. * @access private
  7712. */
  7713. function body()
  7714. {
  7715. $this->body = substr($this->data, $this->position);
  7716. $this->state = 'emit';
  7717. }
  7718. }
  7719. /**
  7720. * gzdecode
  7721. *
  7722. * @package SimplePie
  7723. */
  7724. class SimplePie_gzdecode
  7725. {
  7726. /**
  7727. * Compressed data
  7728. *
  7729. * @access private
  7730. * @see gzdecode::$data
  7731. */
  7732. var $compressed_data;
  7733. /**
  7734. * Size of compressed data
  7735. *
  7736. * @access private
  7737. */
  7738. var $compressed_size;
  7739. /**
  7740. * Minimum size of a valid gzip string
  7741. *
  7742. * @access private
  7743. */
  7744. var $min_compressed_size = 18;
  7745. /**
  7746. * Current position of pointer
  7747. *
  7748. * @access private
  7749. */
  7750. var $position = 0;
  7751. /**
  7752. * Flags (FLG)
  7753. *
  7754. * @access private
  7755. */
  7756. var $flags;
  7757. /**
  7758. * Uncompressed data
  7759. *
  7760. * @access public
  7761. * @see gzdecode::$compressed_data
  7762. */
  7763. var $data;
  7764. /**
  7765. * Modified time
  7766. *
  7767. * @access public
  7768. */
  7769. var $MTIME;
  7770. /**
  7771. * Extra Flags
  7772. *
  7773. * @access public
  7774. */
  7775. var $XFL;
  7776. /**
  7777. * Operating System
  7778. *
  7779. * @access public
  7780. */
  7781. var $OS;
  7782. /**
  7783. * Subfield ID 1
  7784. *
  7785. * @access public
  7786. * @see gzdecode::$extra_field
  7787. * @see gzdecode::$SI2
  7788. */
  7789. var $SI1;
  7790. /**
  7791. * Subfield ID 2
  7792. *
  7793. * @access public
  7794. * @see gzdecode::$extra_field
  7795. * @see gzdecode::$SI1
  7796. */
  7797. var $SI2;
  7798. /**
  7799. * Extra field content
  7800. *
  7801. * @access public
  7802. * @see gzdecode::$SI1
  7803. * @see gzdecode::$SI2
  7804. */
  7805. var $extra_field;
  7806. /**
  7807. * Original filename
  7808. *
  7809. * @access public
  7810. */
  7811. var $filename;
  7812. /**
  7813. * Human readable comment
  7814. *
  7815. * @access public
  7816. */
  7817. var $comment;
  7818. /**
  7819. * Don't allow anything to be set
  7820. *
  7821. * @access public
  7822. */
  7823. function __set($name, $value)
  7824. {
  7825. trigger_error("Cannot write property $name", E_USER_ERROR);
  7826. }
  7827. /**
  7828. * Set the compressed string and related properties
  7829. *
  7830. * @access public
  7831. */
  7832. function SimplePie_gzdecode($data)
  7833. {
  7834. $this->compressed_data = $data;
  7835. $this->compressed_size = strlen($data);
  7836. }
  7837. /**
  7838. * Decode the GZIP stream
  7839. *
  7840. * @access public
  7841. */
  7842. function parse()
  7843. {
  7844. if ($this->compressed_size >= $this->min_compressed_size)
  7845. {
  7846. // Check ID1, ID2, and CM
  7847. if (substr($this->compressed_data, 0, 3) !== "\x1F\x8B\x08")
  7848. {
  7849. return false;
  7850. }
  7851. // Get the FLG (FLaGs)
  7852. $this->flags = ord($this->compressed_data[3]);
  7853. // FLG bits above (1 << 4) are reserved
  7854. if ($this->flags > 0x1F)
  7855. {
  7856. return false;
  7857. }
  7858. // Advance the pointer after the above
  7859. $this->position += 4;
  7860. // MTIME
  7861. $mtime = substr($this->compressed_data, $this->position, 4);
  7862. // Reverse the string if we're on a big-endian arch because l is the only signed long and is machine endianness
  7863. if (current(unpack('S', "\x00\x01")) === 1)
  7864. {
  7865. $mtime = strrev($mtime);
  7866. }
  7867. $this->MTIME = current(unpack('l', $mtime));
  7868. $this->position += 4;
  7869. // Get the XFL (eXtra FLags)
  7870. $this->XFL = ord($this->compressed_data[$this->position++]);
  7871. // Get the OS (Operating System)
  7872. $this->OS = ord($this->compressed_data[$this->position++]);
  7873. // Parse the FEXTRA
  7874. if ($this->flags & 4)
  7875. {
  7876. // Read subfield IDs
  7877. $this->SI1 = $this->compressed_data[$this->position++];
  7878. $this->SI2 = $this->compressed_data[$this->position++];
  7879. // SI2 set to zero is reserved for future use
  7880. if ($this->SI2 === "\x00")
  7881. {
  7882. return false;
  7883. }
  7884. // Get the length of the extra field
  7885. $len = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  7886. $position += 2;
  7887. // Check the length of the string is still valid
  7888. $this->min_compressed_size += $len + 4;
  7889. if ($this->compressed_size >= $this->min_compressed_size)
  7890. {
  7891. // Set the extra field to the given data
  7892. $this->extra_field = substr($this->compressed_data, $this->position, $len);
  7893. $this->position += $len;
  7894. }
  7895. else
  7896. {
  7897. return false;
  7898. }
  7899. }
  7900. // Parse the FNAME
  7901. if ($this->flags & 8)
  7902. {
  7903. // Get the length of the filename
  7904. $len = strcspn($this->compressed_data, "\x00", $this->position);
  7905. // Check the length of the string is still valid
  7906. $this->min_compressed_size += $len + 1;
  7907. if ($this->compressed_size >= $this->min_compressed_size)
  7908. {
  7909. // Set the original filename to the given string
  7910. $this->filename = substr($this->compressed_data, $this->position, $len);
  7911. $this->position += $len + 1;
  7912. }
  7913. else
  7914. {
  7915. return false;
  7916. }
  7917. }
  7918. // Parse the FCOMMENT
  7919. if ($this->flags & 16)
  7920. {
  7921. // Get the length of the comment
  7922. $len = strcspn($this->compressed_data, "\x00", $this->position);
  7923. // Check the length of the string is still valid
  7924. $this->min_compressed_size += $len + 1;
  7925. if ($this->compressed_size >= $this->min_compressed_size)
  7926. {
  7927. // Set the original comment to the given string
  7928. $this->comment = substr($this->compressed_data, $this->position, $len);
  7929. $this->position += $len + 1;
  7930. }
  7931. else
  7932. {
  7933. return false;
  7934. }
  7935. }
  7936. // Parse the FHCRC
  7937. if ($this->flags & 2)
  7938. {
  7939. // Check the length of the string is still valid
  7940. $this->min_compressed_size += $len + 2;
  7941. if ($this->compressed_size >= $this->min_compressed_size)
  7942. {
  7943. // Read the CRC
  7944. $crc = current(unpack('v', substr($this->compressed_data, $this->position, 2)));
  7945. // Check the CRC matches
  7946. if ((crc32(substr($this->compressed_data, 0, $this->position)) & 0xFFFF) === $crc)
  7947. {
  7948. $this->position += 2;
  7949. }
  7950. else
  7951. {
  7952. return false;
  7953. }
  7954. }
  7955. else
  7956. {
  7957. return false;
  7958. }
  7959. }
  7960. // Decompress the actual data
  7961. if (($this->data = gzinflate(substr($this->compressed_data, $this->position, -8))) === false)
  7962. {
  7963. return false;
  7964. }
  7965. else
  7966. {
  7967. $this->position = $this->compressed_size - 8;
  7968. }
  7969. // Check CRC of data
  7970. $crc = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  7971. $this->position += 4;
  7972. /*if (extension_loaded('hash') && sprintf('%u', current(unpack('V', hash('crc32b', $this->data)))) !== sprintf('%u', $crc))
  7973. {
  7974. return false;
  7975. }*/
  7976. // Check ISIZE of data
  7977. $isize = current(unpack('V', substr($this->compressed_data, $this->position, 4)));
  7978. $this->position += 4;
  7979. if (sprintf('%u', strlen($this->data) & 0xFFFFFFFF) !== sprintf('%u', $isize))
  7980. {
  7981. return false;
  7982. }
  7983. // Wow, against all odds, we've actually got a valid gzip string
  7984. return true;
  7985. }
  7986. else
  7987. {
  7988. return false;
  7989. }
  7990. }
  7991. }
  7992. class SimplePie_Cache
  7993. {
  7994. /**
  7995. * Don't call the constructor. Please.
  7996. *
  7997. * @access private
  7998. */
  7999. function SimplePie_Cache()
  8000. {
  8001. trigger_error('Please call SimplePie_Cache::create() instead of the constructor', E_USER_ERROR);
  8002. }
  8003. /**
  8004. * Create a new SimplePie_Cache object
  8005. *
  8006. * @static
  8007. * @access public
  8008. */
  8009. function create($location, $filename, $extension)
  8010. {
  8011. $location_iri = new SimplePie_IRI($location);
  8012. switch ($location_iri->get_scheme())
  8013. {
  8014. case 'mysql':
  8015. if (extension_loaded('mysql'))
  8016. {
  8017. return new SimplePie_Cache_MySQL($location_iri, $filename, $extension);
  8018. }
  8019. break;
  8020. default:
  8021. return new SimplePie_Cache_File($location, $filename, $extension);
  8022. }
  8023. }
  8024. }
  8025. class SimplePie_Cache_File
  8026. {
  8027. var $location;
  8028. var $filename;
  8029. var $extension;
  8030. var $name;
  8031. function SimplePie_Cache_File($location, $filename, $extension)
  8032. {
  8033. $this->location = $location;
  8034. $this->filename = $filename;
  8035. $this->extension = $extension;
  8036. $this->name = "$this->location/$this->filename.$this->extension";
  8037. }
  8038. function save($data)
  8039. {
  8040. if (file_exists($this->name) && is_writeable($this->name) || file_exists($this->location) && is_writeable($this->location))
  8041. {
  8042. if (is_a($data, 'SimplePie'))
  8043. {
  8044. $data = $data->data;
  8045. }
  8046. $data = serialize($data);
  8047. if (function_exists('file_put_contents'))
  8048. {
  8049. return (bool) file_put_contents($this->name, $data);
  8050. }
  8051. else
  8052. {
  8053. $fp = fopen($this->name, 'wb');
  8054. if ($fp)
  8055. {
  8056. fwrite($fp, $data);
  8057. fclose($fp);
  8058. return true;
  8059. }
  8060. }
  8061. }
  8062. return false;
  8063. }
  8064. function load()
  8065. {
  8066. if (file_exists($this->name) && is_readable($this->name))
  8067. {
  8068. return unserialize(file_get_contents($this->name));
  8069. }
  8070. return false;
  8071. }
  8072. function mtime()
  8073. {
  8074. if (file_exists($this->name))
  8075. {
  8076. return filemtime($this->name);
  8077. }
  8078. return false;
  8079. }
  8080. function touch()
  8081. {
  8082. if (file_exists($this->name))
  8083. {
  8084. return touch($this->name);
  8085. }
  8086. return false;
  8087. }
  8088. function unlink()
  8089. {
  8090. if (file_exists($this->name))
  8091. {
  8092. return unlink($this->name);
  8093. }
  8094. return false;
  8095. }
  8096. }
  8097. class SimplePie_Cache_DB
  8098. {
  8099. function prepare_simplepie_object_for_cache($data)
  8100. {
  8101. $items = $data->get_items();
  8102. $items_by_id = array();
  8103. if (!empty($items))
  8104. {
  8105. foreach ($items as $item)
  8106. {
  8107. $items_by_id[$item->get_id()] = $item;
  8108. }
  8109. if (count($items_by_id) !== count($items))
  8110. {
  8111. $items_by_id = array();
  8112. foreach ($items as $item)
  8113. {
  8114. $items_by_id[$item->get_id(true)] = $item;
  8115. }
  8116. }
  8117. if (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  8118. {
  8119. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  8120. }
  8121. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  8122. {
  8123. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  8124. }
  8125. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  8126. {
  8127. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  8128. }
  8129. elseif (isset($data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0]))
  8130. {
  8131. $channel =& $data->data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]['child'][SIMPLEPIE_NAMESPACE_RSS_20]['channel'][0];
  8132. }
  8133. else
  8134. {
  8135. $channel = null;
  8136. }
  8137. if ($channel !== null)
  8138. {
  8139. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']))
  8140. {
  8141. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry']);
  8142. }
  8143. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']))
  8144. {
  8145. unset($channel['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['entry']);
  8146. }
  8147. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']))
  8148. {
  8149. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_10]['item']);
  8150. }
  8151. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']))
  8152. {
  8153. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_090]['item']);
  8154. }
  8155. if (isset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']))
  8156. {
  8157. unset($channel['child'][SIMPLEPIE_NAMESPACE_RSS_20]['item']);
  8158. }
  8159. }
  8160. if (isset($data->data['items']))
  8161. {
  8162. unset($data->data['items']);
  8163. }
  8164. if (isset($data->data['ordered_items']))
  8165. {
  8166. unset($data->data['ordered_items']);
  8167. }
  8168. }
  8169. return array(serialize($data->data), $items_by_id);
  8170. }
  8171. }
  8172. class SimplePie_Cache_MySQL extends SimplePie_Cache_DB
  8173. {
  8174. var $mysql;
  8175. var $options;
  8176. var $id;
  8177. function SimplePie_Cache_MySQL($mysql_location, $name, $extension)
  8178. {
  8179. $host = $mysql_location->get_host();
  8180. if (SimplePie_Misc::stripos($host, 'unix(') === 0 && substr($host, -1) === ')')
  8181. {
  8182. $server = ':' . substr($host, 5, -1);
  8183. }
  8184. else
  8185. {
  8186. $server = $host;
  8187. if ($mysql_location->get_port() !== null)
  8188. {
  8189. $server .= ':' . $mysql_location->get_port();
  8190. }
  8191. }
  8192. if (strpos($mysql_location->get_userinfo(), ':') !== false)
  8193. {
  8194. list($username, $password) = explode(':', $mysql_location->get_userinfo(), 2);
  8195. }
  8196. else
  8197. {
  8198. $username = $mysql_location->get_userinfo();
  8199. $password = null;
  8200. }
  8201. if ($this->mysql = mysql_connect($server, $username, $password))
  8202. {
  8203. $this->id = $name . $extension;
  8204. $this->options = SimplePie_Misc::parse_str($mysql_location->get_query());
  8205. if (!isset($this->options['prefix'][0]))
  8206. {
  8207. $this->options['prefix'][0] = '';
  8208. }
  8209. if (mysql_select_db(ltrim($mysql_location->get_path(), '/'))
  8210. && mysql_query('SET NAMES utf8')
  8211. && ($query = mysql_unbuffered_query('SHOW TABLES')))
  8212. {
  8213. $db = array();
  8214. while ($row = mysql_fetch_row($query))
  8215. {
  8216. $db[] = $row[0];
  8217. }
  8218. if (!in_array($this->options['prefix'][0] . 'cache_data', $db))
  8219. {
  8220. 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)))'))
  8221. {
  8222. $this->mysql = null;
  8223. }
  8224. }
  8225. if (!in_array($this->options['prefix'][0] . 'items', $db))
  8226. {
  8227. 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)))'))
  8228. {
  8229. $this->mysql = null;
  8230. }
  8231. }
  8232. }
  8233. else
  8234. {
  8235. $this->mysql = null;
  8236. }
  8237. }
  8238. }
  8239. function save($data)
  8240. {
  8241. if ($this->mysql)
  8242. {
  8243. $feed_id = "'" . mysql_real_escape_string($this->id) . "'";
  8244. if (is_a($data, 'SimplePie'))
  8245. {
  8246. if (SIMPLEPIE_PHP5)
  8247. {
  8248. // This keyword needs to defy coding standards for PHP4 compatibility
  8249. $data = clone($data);
  8250. }
  8251. $prepared = $this->prepare_simplepie_object_for_cache($data);
  8252. if ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
  8253. {
  8254. if (mysql_num_rows($query))
  8255. {
  8256. $items = count($prepared[1]);
  8257. if ($items)
  8258. {
  8259. $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `items` = ' . $items . ', `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
  8260. }
  8261. else
  8262. {
  8263. $sql = 'UPDATE `' . $this->options['prefix'][0] . 'cache_data` SET `data` = \'' . mysql_real_escape_string($prepared[0]) . '\', `mtime` = ' . time() . ' WHERE `id` = ' . $feed_id;
  8264. }
  8265. if (!mysql_query($sql, $this->mysql))
  8266. {
  8267. return false;
  8268. }
  8269. }
  8270. 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))
  8271. {
  8272. return false;
  8273. }
  8274. $ids = array_keys($prepared[1]);
  8275. if (!empty($ids))
  8276. {
  8277. foreach ($ids as $id)
  8278. {
  8279. $database_ids[] = mysql_real_escape_string($id);
  8280. }
  8281. 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))
  8282. {
  8283. $existing_ids = array();
  8284. while ($row = mysql_fetch_row($query))
  8285. {
  8286. $existing_ids[] = $row[0];
  8287. }
  8288. $new_ids = array_diff($ids, $existing_ids);
  8289. foreach ($new_ids as $new_id)
  8290. {
  8291. if (!($date = $prepared[1][$new_id]->get_date('U')))
  8292. {
  8293. $date = time();
  8294. }
  8295. 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))
  8296. {
  8297. return false;
  8298. }
  8299. }
  8300. return true;
  8301. }
  8302. }
  8303. else
  8304. {
  8305. return true;
  8306. }
  8307. }
  8308. }
  8309. elseif ($query = mysql_query('SELECT `id` FROM `' . $this->options['prefix'][0] . 'cache_data` WHERE `id` = ' . $feed_id, $this->mysql))
  8310. {
  8311. if (mysql_num_rows($query))
  8312. {
  8313. 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))
  8314. {
  8315. return true;
  8316. }
  8317. }
  8318. 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))
  8319. {
  8320. return true;
  8321. }
  8322. }
  8323. }
  8324. return false;
  8325. }
  8326. function load()
  8327. {
  8328. 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)))
  8329. {
  8330. $data = unserialize($row[1]);
  8331. if (isset($this->options['items'][0]))
  8332. {
  8333. $items = (int) $this->options['items'][0];
  8334. }
  8335. else
  8336. {
  8337. $items = (int) $row[0];
  8338. }
  8339. if ($items !== 0)
  8340. {
  8341. if (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0]))
  8342. {
  8343. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['feed'][0];
  8344. }
  8345. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0]))
  8346. {
  8347. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_ATOM_03]['feed'][0];
  8348. }
  8349. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0]))
  8350. {
  8351. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RDF]['RDF'][0];
  8352. }
  8353. elseif (isset($data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0]))
  8354. {
  8355. $feed =& $data['child'][SIMPLEPIE_NAMESPACE_RSS_20]['rss'][0];
  8356. }
  8357. else
  8358. {
  8359. $feed = null;
  8360. }
  8361. if ($feed !== null)
  8362. {
  8363. $sql = 'SELECT `data` FROM `' . $this->options['prefix'][0] . 'items` WHERE `feed_id` = \'' . mysql_real_escape_string($this->id) . '\' ORDER BY `posted` DESC';
  8364. if ($items > 0)
  8365. {
  8366. $sql .= ' LIMIT ' . $items;
  8367. }
  8368. if ($query = mysql_unbuffered_query($sql, $this->mysql))
  8369. {
  8370. while ($row = mysql_fetch_row($query))
  8371. {
  8372. $feed['child'][SIMPLEPIE_NAMESPACE_ATOM_10]['entry'][] = unserialize($row[0]);
  8373. }
  8374. }
  8375. else
  8376. {
  8377. return false;
  8378. }
  8379. }
  8380. }
  8381. return $data;
  8382. }
  8383. return false;
  8384. }
  8385. function mtime()
  8386. {
  8387. 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)))
  8388. {
  8389. return $row[0];
  8390. }
  8391. else
  8392. {
  8393. return false;
  8394. }
  8395. }
  8396. function touch()
  8397. {
  8398. 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))
  8399. {
  8400. return true;
  8401. }
  8402. else
  8403. {
  8404. return false;
  8405. }
  8406. }
  8407. function unlink()
  8408. {
  8409. 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)))
  8410. {
  8411. return true;
  8412. }
  8413. else
  8414. {
  8415. return false;
  8416. }
  8417. }
  8418. }
  8419. class SimplePie_Misc
  8420. {
  8421. function time_hms($seconds)
  8422. {
  8423. $time = '';
  8424. $hours = floor($seconds / 3600);
  8425. $remainder = $seconds % 3600;
  8426. if ($hours > 0)
  8427. {
  8428. $time .= $hours.':';
  8429. }
  8430. $minutes = floor($remainder / 60);
  8431. $seconds = $remainder % 60;
  8432. if ($minutes < 10 && $hours > 0)
  8433. {
  8434. $minutes = '0' . $minutes;
  8435. }
  8436. if ($seconds < 10)
  8437. {
  8438. $seconds = '0' . $seconds;
  8439. }
  8440. $time .= $minutes.':';
  8441. $time .= $seconds;
  8442. return $time;
  8443. }
  8444. function absolutize_url($relative, $base)
  8445. {
  8446. $iri = SimplePie_IRI::absolutize(new SimplePie_IRI($base), $relative);
  8447. return $iri->get_iri();
  8448. }
  8449. function remove_dot_segments($input)
  8450. {
  8451. $output = '';
  8452. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  8453. {
  8454. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  8455. if (strpos($input, '../') === 0)
  8456. {
  8457. $input = substr($input, 3);
  8458. }
  8459. elseif (strpos($input, './') === 0)
  8460. {
  8461. $input = substr($input, 2);
  8462. }
  8463. // 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,
  8464. elseif (strpos($input, '/./') === 0)
  8465. {
  8466. $input = substr_replace($input, '/', 0, 3);
  8467. }
  8468. elseif ($input === '/.')
  8469. {
  8470. $input = '/';
  8471. }
  8472. // 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,
  8473. elseif (strpos($input, '/../') === 0)
  8474. {
  8475. $input = substr_replace($input, '/', 0, 4);
  8476. $output = substr_replace($output, '', strrpos($output, '/'));
  8477. }
  8478. elseif ($input === '/..')
  8479. {
  8480. $input = '/';
  8481. $output = substr_replace($output, '', strrpos($output, '/'));
  8482. }
  8483. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  8484. elseif ($input === '.' || $input === '..')
  8485. {
  8486. $input = '';
  8487. }
  8488. // 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
  8489. elseif (($pos = strpos($input, '/', 1)) !== false)
  8490. {
  8491. $output .= substr($input, 0, $pos);
  8492. $input = substr_replace($input, '', 0, $pos);
  8493. }
  8494. else
  8495. {
  8496. $output .= $input;
  8497. $input = '';
  8498. }
  8499. }
  8500. return $output . $input;
  8501. }
  8502. function get_element($realname, $string)
  8503. {
  8504. $return = array();
  8505. $name = preg_quote($realname, '/');
  8506. if (preg_match_all("/<($name)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$name>|(\/)?>)/siU", $string, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE))
  8507. {
  8508. for ($i = 0, $total_matches = count($matches); $i < $total_matches; $i++)
  8509. {
  8510. $return[$i]['tag'] = $realname;
  8511. $return[$i]['full'] = $matches[$i][0][0];
  8512. $return[$i]['offset'] = $matches[$i][0][1];
  8513. if (strlen($matches[$i][3][0]) <= 2)
  8514. {
  8515. $return[$i]['self_closing'] = true;
  8516. }
  8517. else
  8518. {
  8519. $return[$i]['self_closing'] = false;
  8520. $return[$i]['content'] = $matches[$i][4][0];
  8521. }
  8522. $return[$i]['attribs'] = array();
  8523. 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))
  8524. {
  8525. for ($j = 0, $total_attribs = count($attribs); $j < $total_attribs; $j++)
  8526. {
  8527. if (count($attribs[$j]) === 2)
  8528. {
  8529. $attribs[$j][2] = $attribs[$j][1];
  8530. }
  8531. $return[$i]['attribs'][strtolower($attribs[$j][1])]['data'] = SimplePie_Misc::entities_decode(end($attribs[$j]), 'UTF-8');
  8532. }
  8533. }
  8534. }
  8535. }
  8536. return $return;
  8537. }
  8538. function element_implode($element)
  8539. {
  8540. $full = "<$element[tag]";
  8541. foreach ($element['attribs'] as $key => $value)
  8542. {
  8543. $key = strtolower($key);
  8544. $full .= " $key=\"" . htmlspecialchars($value['data']) . '"';
  8545. }
  8546. if ($element['self_closing'])
  8547. {
  8548. $full .= ' />';
  8549. }
  8550. else
  8551. {
  8552. $full .= ">$element[content]</$element[tag]>";
  8553. }
  8554. return $full;
  8555. }
  8556. function error($message, $level, $file, $line)
  8557. {
  8558. if ((ini_get('error_reporting') & $level) > 0)
  8559. {
  8560. switch ($level)
  8561. {
  8562. case E_USER_ERROR:
  8563. $note = 'PHP Error';
  8564. break;
  8565. case E_USER_WARNING:
  8566. $note = 'PHP Warning';
  8567. break;
  8568. case E_USER_NOTICE:
  8569. $note = 'PHP Notice';
  8570. break;
  8571. default:
  8572. $note = 'Unknown Error';
  8573. break;
  8574. }
  8575. error_log("$note: $message in $file on line $line", 0);
  8576. }
  8577. return $message;
  8578. }
  8579. /**
  8580. * If a file has been cached, retrieve and display it.
  8581. *
  8582. * This is most useful for caching images (get_favicon(), etc.),
  8583. * however it works for all cached files. This WILL NOT display ANY
  8584. * file/image/page/whatever, but rather only display what has already
  8585. * been cached by SimplePie.
  8586. *
  8587. * @access public
  8588. * @see SimplePie::get_favicon()
  8589. * @param str $identifier_url URL that is used to identify the content.
  8590. * This may or may not be the actual URL of the live content.
  8591. * @param str $cache_location Location of SimplePie's cache. Defaults
  8592. * to './cache'.
  8593. * @param str $cache_extension The file extension that the file was
  8594. * cached with. Defaults to 'spc'.
  8595. * @param str $cache_class Name of the cache-handling class being used
  8596. * in SimplePie. Defaults to 'SimplePie_Cache', and should be left
  8597. * as-is unless you've overloaded the class.
  8598. * @param str $cache_name_function Obsolete. Exists for backwards
  8599. * compatibility reasons only.
  8600. */
  8601. function display_cached_file($identifier_url, $cache_location = './cache', $cache_extension = 'spc', $cache_class = 'SimplePie_Cache', $cache_name_function = 'md5')
  8602. {
  8603. $cache = call_user_func(array($cache_class, 'create'), $cache_location, $identifier_url, $cache_extension);
  8604. if ($file = $cache->load())
  8605. {
  8606. if (isset($file['headers']['content-type']))
  8607. {
  8608. header('Content-type:' . $file['headers']['content-type']);
  8609. }
  8610. else
  8611. {
  8612. header('Content-type: application/octet-stream');
  8613. }
  8614. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
  8615. echo $file['body'];
  8616. exit;
  8617. }
  8618. die('Cached file for ' . $identifier_url . ' cannot be found.');
  8619. }
  8620. function fix_protocol($url, $http = 1)
  8621. {
  8622. $url = SimplePie_Misc::normalize_url($url);
  8623. $parsed = SimplePie_Misc::parse_url($url);
  8624. if ($parsed['scheme'] !== '' && $parsed['scheme'] !== 'http' && $parsed['scheme'] !== 'https')
  8625. {
  8626. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['authority'], $parsed['path'], $parsed['query'], $parsed['fragment']), $http);
  8627. }
  8628. if ($parsed['scheme'] === '' && $parsed['authority'] === '' && !file_exists($url))
  8629. {
  8630. return SimplePie_Misc::fix_protocol(SimplePie_Misc::compress_parse_url('http', $parsed['path'], '', $parsed['query'], $parsed['fragment']), $http);
  8631. }
  8632. if ($http === 2 && $parsed['scheme'] !== '')
  8633. {
  8634. return "feed:$url";
  8635. }
  8636. elseif ($http === 3 && strtolower($parsed['scheme']) === 'http')
  8637. {
  8638. return substr_replace($url, 'podcast', 0, 4);
  8639. }
  8640. elseif ($http === 4 && strtolower($parsed['scheme']) === 'http')
  8641. {
  8642. return substr_replace($url, 'itpc', 0, 4);
  8643. }
  8644. else
  8645. {
  8646. return $url;
  8647. }
  8648. }
  8649. function parse_url($url)
  8650. {
  8651. $iri = new SimplePie_IRI($url);
  8652. return array(
  8653. 'scheme' => (string) $iri->get_scheme(),
  8654. 'authority' => (string) $iri->get_authority(),
  8655. 'path' => (string) $iri->get_path(),
  8656. 'query' => (string) $iri->get_query(),
  8657. 'fragment' => (string) $iri->get_fragment()
  8658. );
  8659. }
  8660. function compress_parse_url($scheme = '', $authority = '', $path = '', $query = '', $fragment = '')
  8661. {
  8662. $iri = new SimplePie_IRI('');
  8663. $iri->set_scheme($scheme);
  8664. $iri->set_authority($authority);
  8665. $iri->set_path($path);
  8666. $iri->set_query($query);
  8667. $iri->set_fragment($fragment);
  8668. return $iri->get_iri();
  8669. }
  8670. function normalize_url($url)
  8671. {
  8672. $iri = new SimplePie_IRI($url);
  8673. return $iri->get_iri();
  8674. }
  8675. function percent_encoding_normalization($match)
  8676. {
  8677. $integer = hexdec($match[1]);
  8678. if ($integer >= 0x41 && $integer <= 0x5A || $integer >= 0x61 && $integer <= 0x7A || $integer >= 0x30 && $integer <= 0x39 || $integer === 0x2D || $integer === 0x2E || $integer === 0x5F || $integer === 0x7E)
  8679. {
  8680. return chr($integer);
  8681. }
  8682. else
  8683. {
  8684. return strtoupper($match[0]);
  8685. }
  8686. }
  8687. /**
  8688. * Remove bad UTF-8 bytes
  8689. *
  8690. * PCRE Pattern to locate bad bytes in a UTF-8 string comes from W3C
  8691. * FAQ: Multilingual Forms (modified to include full ASCII range)
  8692. *
  8693. * @author Geoffrey Sneddon
  8694. * @see http://www.w3.org/International/questions/qa-forms-utf-8
  8695. * @param string $str String to remove bad UTF-8 bytes from
  8696. * @return string UTF-8 string
  8697. */
  8698. function utf8_bad_replace($str)
  8699. {
  8700. if (function_exists('iconv') && ($return = @iconv('UTF-8', 'UTF-8//IGNORE', $str)))
  8701. {
  8702. return $return;
  8703. }
  8704. elseif (function_exists('mb_convert_encoding') && ($return = @mb_convert_encoding($str, 'UTF-8', 'UTF-8')))
  8705. {
  8706. return $return;
  8707. }
  8708. elseif (preg_match_all('/(?:[\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})+/', $str, $matches))
  8709. {
  8710. return implode("\xEF\xBF\xBD", $matches[0]);
  8711. }
  8712. elseif ($str !== '')
  8713. {
  8714. return "\xEF\xBF\xBD";
  8715. }
  8716. else
  8717. {
  8718. return '';
  8719. }
  8720. }
  8721. /**
  8722. * Converts a Windows-1252 encoded string to a UTF-8 encoded string
  8723. *
  8724. * @static
  8725. * @access public
  8726. * @param string $string Windows-1252 encoded string
  8727. * @return string UTF-8 encoded string
  8728. */
  8729. function windows_1252_to_utf8($string)
  8730. {
  8731. 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");
  8732. return strtr($string, $convert_table);
  8733. }
  8734. function change_encoding($data, $input, $output)
  8735. {
  8736. $input = SimplePie_Misc::encoding($input);
  8737. $output = SimplePie_Misc::encoding($output);
  8738. // We fail to fail on non US-ASCII bytes
  8739. if ($input === 'US-ASCII')
  8740. {
  8741. static $non_ascii_octects = '';
  8742. if (!$non_ascii_octects)
  8743. {
  8744. for ($i = 0x80; $i <= 0xFF; $i++)
  8745. {
  8746. $non_ascii_octects .= chr($i);
  8747. }
  8748. }
  8749. $data = substr($data, 0, strcspn($data, $non_ascii_octects));
  8750. }
  8751. // This is first, as behaviour of this is completely predictable
  8752. if ($input === 'Windows-1252' && $output === 'UTF-8')
  8753. {
  8754. return SimplePie_Misc::windows_1252_to_utf8($data);
  8755. }
  8756. // This is second, as behaviour of this varies only with PHP version (the middle part of this expression checks the encoding is supported).
  8757. elseif (function_exists('mb_convert_encoding') && @mb_convert_encoding("\x80", 'UTF-16BE', $input) !== "\x00\x80" && ($return = @mb_convert_encoding($data, $output, $input)))
  8758. {
  8759. return $return;
  8760. }
  8761. // This is last, as behaviour of this varies with OS userland and PHP version
  8762. elseif (function_exists('iconv') && ($return = @iconv($input, $output, $data)))
  8763. {
  8764. return $return;
  8765. }
  8766. // If we can't do anything, just fail
  8767. else
  8768. {
  8769. return false;
  8770. }
  8771. }
  8772. function encoding($charset)
  8773. {
  8774. // Normalization from UTS #22
  8775. switch (strtolower(preg_replace('/(?:[^a-zA-Z0-9]+|([^0-9])0+)/', '\1', $charset)))
  8776. {
  8777. case 'adobestandardencoding':
  8778. case 'csadobestandardencoding':
  8779. return 'Adobe-Standard-Encoding';
  8780. case 'adobesymbolencoding':
  8781. case 'cshppsmath':
  8782. return 'Adobe-Symbol-Encoding';
  8783. case 'ami1251':
  8784. case 'amiga1251':
  8785. return 'Amiga-1251';
  8786. case 'ansix31101983':
  8787. case 'csat5001983':
  8788. case 'csiso99naplps':
  8789. case 'isoir99':
  8790. case 'naplps':
  8791. return 'ANSI_X3.110-1983';
  8792. case 'arabic7':
  8793. case 'asmo449':
  8794. case 'csiso89asmo449':
  8795. case 'iso9036':
  8796. case 'isoir89':
  8797. return 'ASMO_449';
  8798. case 'big5':
  8799. case 'csbig5':
  8800. case 'xxbig5':
  8801. return 'Big5';
  8802. case 'big5hkscs':
  8803. return 'Big5-HKSCS';
  8804. case 'bocu1':
  8805. case 'csbocu1':
  8806. return 'BOCU-1';
  8807. case 'brf':
  8808. case 'csbrf':
  8809. return 'BRF';
  8810. case 'bs4730':
  8811. case 'csiso4unitedkingdom':
  8812. case 'gb':
  8813. case 'iso646gb':
  8814. case 'isoir4':
  8815. case 'uk':
  8816. return 'BS_4730';
  8817. case 'bsviewdata':
  8818. case 'csiso47bsviewdata':
  8819. case 'isoir47':
  8820. return 'BS_viewdata';
  8821. case 'cesu8':
  8822. case 'cscesu8':
  8823. return 'CESU-8';
  8824. case 'ca':
  8825. case 'csa71':
  8826. case 'csaz243419851':
  8827. case 'csiso121canadian1':
  8828. case 'iso646ca':
  8829. case 'isoir121':
  8830. return 'CSA_Z243.4-1985-1';
  8831. case 'csa72':
  8832. case 'csaz243419852':
  8833. case 'csiso122canadian2':
  8834. case 'iso646ca2':
  8835. case 'isoir122':
  8836. return 'CSA_Z243.4-1985-2';
  8837. case 'csaz24341985gr':
  8838. case 'csiso123csaz24341985gr':
  8839. case 'isoir123':
  8840. return 'CSA_Z243.4-1985-gr';
  8841. case 'csiso139csn369103':
  8842. case 'csn369103':
  8843. case 'isoir139':
  8844. return 'CSN_369103';
  8845. case 'csdecmcs':
  8846. case 'dec':
  8847. case 'decmcs':
  8848. return 'DEC-MCS';
  8849. case 'csiso21german':
  8850. case 'de':
  8851. case 'din66003':
  8852. case 'iso646de':
  8853. case 'isoir21':
  8854. return 'DIN_66003';
  8855. case 'csdkus':
  8856. case 'dkus':
  8857. return 'dk-us';
  8858. case 'csiso646danish':
  8859. case 'dk':
  8860. case 'ds2089':
  8861. case 'iso646dk':
  8862. return 'DS_2089';
  8863. case 'csibmebcdicatde':
  8864. case 'ebcdicatde':
  8865. return 'EBCDIC-AT-DE';
  8866. case 'csebcdicatdea':
  8867. case 'ebcdicatdea':
  8868. return 'EBCDIC-AT-DE-A';
  8869. case 'csebcdiccafr':
  8870. case 'ebcdiccafr':
  8871. return 'EBCDIC-CA-FR';
  8872. case 'csebcdicdkno':
  8873. case 'ebcdicdkno':
  8874. return 'EBCDIC-DK-NO';
  8875. case 'csebcdicdknoa':
  8876. case 'ebcdicdknoa':
  8877. return 'EBCDIC-DK-NO-A';
  8878. case 'csebcdices':
  8879. case 'ebcdices':
  8880. return 'EBCDIC-ES';
  8881. case 'csebcdicesa':
  8882. case 'ebcdicesa':
  8883. return 'EBCDIC-ES-A';
  8884. case 'csebcdicess':
  8885. case 'ebcdicess':
  8886. return 'EBCDIC-ES-S';
  8887. case 'csebcdicfise':
  8888. case 'ebcdicfise':
  8889. return 'EBCDIC-FI-SE';
  8890. case 'csebcdicfisea':
  8891. case 'ebcdicfisea':
  8892. return 'EBCDIC-FI-SE-A';
  8893. case 'csebcdicfr':
  8894. case 'ebcdicfr':
  8895. return 'EBCDIC-FR';
  8896. case 'csebcdicit':
  8897. case 'ebcdicit':
  8898. return 'EBCDIC-IT';
  8899. case 'csebcdicpt':
  8900. case 'ebcdicpt':
  8901. return 'EBCDIC-PT';
  8902. case 'csebcdicuk':
  8903. case 'ebcdicuk':
  8904. return 'EBCDIC-UK';
  8905. case 'csebcdicus':
  8906. case 'ebcdicus':
  8907. return 'EBCDIC-US';
  8908. case 'csiso111ecmacyrillic':
  8909. case 'ecmacyrillic':
  8910. case 'isoir111':
  8911. case 'koi8e':
  8912. return 'ECMA-cyrillic';
  8913. case 'csiso17spanish':
  8914. case 'es':
  8915. case 'iso646es':
  8916. case 'isoir17':
  8917. return 'ES';
  8918. case 'csiso85spanish2':
  8919. case 'es2':
  8920. case 'iso646es2':
  8921. case 'isoir85':
  8922. return 'ES2';
  8923. case 'cseucfixwidjapanese':
  8924. case 'extendedunixcodefixedwidthforjapanese':
  8925. return 'Extended_UNIX_Code_Fixed_Width_for_Japanese';
  8926. case 'cseucpkdfmtjapanese':
  8927. case 'eucjp':
  8928. case 'extendedunixcodepackedformatforjapanese':
  8929. return 'Extended_UNIX_Code_Packed_Format_for_Japanese';
  8930. case 'gb18030':
  8931. return 'GB18030';
  8932. case 'chinese':
  8933. case 'cp936':
  8934. case 'csgb2312':
  8935. case 'csiso58gb231280':
  8936. case 'gb2312':
  8937. case 'gb231280':
  8938. case 'gbk':
  8939. case 'isoir58':
  8940. case 'ms936':
  8941. case 'windows936':
  8942. return 'GBK';
  8943. case 'cn':
  8944. case 'csiso57gb1988':
  8945. case 'gb198880':
  8946. case 'iso646cn':
  8947. case 'isoir57':
  8948. return 'GB_1988-80';
  8949. case 'csiso153gost1976874':
  8950. case 'gost1976874':
  8951. case 'isoir153':
  8952. case 'stsev35888':
  8953. return 'GOST_19768-74';
  8954. case 'csiso150':
  8955. case 'csiso150greekccitt':
  8956. case 'greekccitt':
  8957. case 'isoir150':
  8958. return 'greek-ccitt';
  8959. case 'csiso88greek7':
  8960. case 'greek7':
  8961. case 'isoir88':
  8962. return 'greek7';
  8963. case 'csiso18greek7old':
  8964. case 'greek7old':
  8965. case 'isoir18':
  8966. return 'greek7-old';
  8967. case 'cshpdesktop':
  8968. case 'hpdesktop':
  8969. return 'HP-DeskTop';
  8970. case 'cshplegal':
  8971. case 'hplegal':
  8972. return 'HP-Legal';
  8973. case 'cshpmath8':
  8974. case 'hpmath8':
  8975. return 'HP-Math8';
  8976. case 'cshppifont':
  8977. case 'hppifont':
  8978. return 'HP-Pi-font';
  8979. case 'cshproman8':
  8980. case 'hproman8':
  8981. case 'r8':
  8982. case 'roman8':
  8983. return 'hp-roman8';
  8984. case 'hzgb2312':
  8985. return 'HZ-GB-2312';
  8986. case 'csibmsymbols':
  8987. case 'ibmsymbols':
  8988. return 'IBM-Symbols';
  8989. case 'csibmthai':
  8990. case 'ibmthai':
  8991. return 'IBM-Thai';
  8992. case 'ccsid858':
  8993. case 'cp858':
  8994. case 'ibm858':
  8995. case 'pcmultilingual850euro':
  8996. return 'IBM00858';
  8997. case 'ccsid924':
  8998. case 'cp924':
  8999. case 'ebcdiclatin9euro':
  9000. case 'ibm924':
  9001. return 'IBM00924';
  9002. case 'ccsid1140':
  9003. case 'cp1140':
  9004. case 'ebcdicus37euro':
  9005. case 'ibm1140':
  9006. return 'IBM01140';
  9007. case 'ccsid1141':
  9008. case 'cp1141':
  9009. case 'ebcdicde273euro':
  9010. case 'ibm1141':
  9011. return 'IBM01141';
  9012. case 'ccsid1142':
  9013. case 'cp1142':
  9014. case 'ebcdicdk277euro':
  9015. case 'ebcdicno277euro':
  9016. case 'ibm1142':
  9017. return 'IBM01142';
  9018. case 'ccsid1143':
  9019. case 'cp1143':
  9020. case 'ebcdicfi278euro':
  9021. case 'ebcdicse278euro':
  9022. case 'ibm1143':
  9023. return 'IBM01143';
  9024. case 'ccsid1144':
  9025. case 'cp1144':
  9026. case 'ebcdicit280euro':
  9027. case 'ibm1144':
  9028. return 'IBM01144';
  9029. case 'ccsid1145':
  9030. case 'cp1145':
  9031. case 'ebcdices284euro':
  9032. case 'ibm1145':
  9033. return 'IBM01145';
  9034. case 'ccsid1146':
  9035. case 'cp1146':
  9036. case 'ebcdicgb285euro':
  9037. case 'ibm1146':
  9038. return 'IBM01146';
  9039. case 'ccsid1147':
  9040. case 'cp1147':
  9041. case 'ebcdicfr297euro':
  9042. case 'ibm1147':
  9043. return 'IBM01147';
  9044. case 'ccsid1148':
  9045. case 'cp1148':
  9046. case 'ebcdicinternational500euro':
  9047. case 'ibm1148':
  9048. return 'IBM01148';
  9049. case 'ccsid1149':
  9050. case 'cp1149':
  9051. case 'ebcdicis871euro':
  9052. case 'ibm1149':
  9053. return 'IBM01149';
  9054. case 'cp37':
  9055. case 'csibm37':
  9056. case 'ebcdiccpca':
  9057. case 'ebcdiccpnl':
  9058. case 'ebcdiccpus':
  9059. case 'ebcdiccpwt':
  9060. case 'ibm37':
  9061. return 'IBM037';
  9062. case 'cp38':
  9063. case 'csibm38':
  9064. case 'ebcdicint':
  9065. case 'ibm38':
  9066. return 'IBM038';
  9067. case 'cp273':
  9068. case 'csibm273':
  9069. case 'ibm273':
  9070. return 'IBM273';
  9071. case 'cp274':
  9072. case 'csibm274':
  9073. case 'ebcdicbe':
  9074. case 'ibm274':
  9075. return 'IBM274';
  9076. case 'cp275':
  9077. case 'csibm275':
  9078. case 'ebcdicbr':
  9079. case 'ibm275':
  9080. return 'IBM275';
  9081. case 'csibm277':
  9082. case 'ebcdiccpdk':
  9083. case 'ebcdiccpno':
  9084. case 'ibm277':
  9085. return 'IBM277';
  9086. case 'cp278':
  9087. case 'csibm278':
  9088. case 'ebcdiccpfi':
  9089. case 'ebcdiccpse':
  9090. case 'ibm278':
  9091. return 'IBM278';
  9092. case 'cp280':
  9093. case 'csibm280':
  9094. case 'ebcdiccpit':
  9095. case 'ibm280':
  9096. return 'IBM280';
  9097. case 'cp281':
  9098. case 'csibm281':
  9099. case 'ebcdicjpe':
  9100. case 'ibm281':
  9101. return 'IBM281';
  9102. case 'cp284':
  9103. case 'csibm284':
  9104. case 'ebcdiccpes':
  9105. case 'ibm284':
  9106. return 'IBM284';
  9107. case 'cp285':
  9108. case 'csibm285':
  9109. case 'ebcdiccpgb':
  9110. case 'ibm285':
  9111. return 'IBM285';
  9112. case 'cp290':
  9113. case 'csibm290':
  9114. case 'ebcdicjpkana':
  9115. case 'ibm290':
  9116. return 'IBM290';
  9117. case 'cp297':
  9118. case 'csibm297':
  9119. case 'ebcdiccpfr':
  9120. case 'ibm297':
  9121. return 'IBM297';
  9122. case 'cp420':
  9123. case 'csibm420':
  9124. case 'ebcdiccpar1':
  9125. case 'ibm420':
  9126. return 'IBM420';
  9127. case 'cp423':
  9128. case 'csibm423':
  9129. case 'ebcdiccpgr':
  9130. case 'ibm423':
  9131. return 'IBM423';
  9132. case 'cp424':
  9133. case 'csibm424':
  9134. case 'ebcdiccphe':
  9135. case 'ibm424':
  9136. return 'IBM424';
  9137. case '437':
  9138. case 'cp437':
  9139. case 'cspc8codepage437':
  9140. case 'ibm437':
  9141. return 'IBM437';
  9142. case 'cp500':
  9143. case 'csibm500':
  9144. case 'ebcdiccpbe':
  9145. case 'ebcdiccpch':
  9146. case 'ibm500':
  9147. return 'IBM500';
  9148. case 'cp775':
  9149. case 'cspc775baltic':
  9150. case 'ibm775':
  9151. return 'IBM775';
  9152. case '850':
  9153. case 'cp850':
  9154. case 'cspc850multilingual':
  9155. case 'ibm850':
  9156. return 'IBM850';
  9157. case '851':
  9158. case 'cp851':
  9159. case 'csibm851':
  9160. case 'ibm851':
  9161. return 'IBM851';
  9162. case '852':
  9163. case 'cp852':
  9164. case 'cspcp852':
  9165. case 'ibm852':
  9166. return 'IBM852';
  9167. case '855':
  9168. case 'cp855':
  9169. case 'csibm855':
  9170. case 'ibm855':
  9171. return 'IBM855';
  9172. case '857':
  9173. case 'cp857':
  9174. case 'csibm857':
  9175. case 'ibm857':
  9176. return 'IBM857';
  9177. case '860':
  9178. case 'cp860':
  9179. case 'csibm860':
  9180. case 'ibm860':
  9181. return 'IBM860';
  9182. case '861':
  9183. case 'cp861':
  9184. case 'cpis':
  9185. case 'csibm861':
  9186. case 'ibm861':
  9187. return 'IBM861';
  9188. case '862':
  9189. case 'cp862':
  9190. case 'cspc862latinhebrew':
  9191. case 'ibm862':
  9192. return 'IBM862';
  9193. case '863':
  9194. case 'cp863':
  9195. case 'csibm863':
  9196. case 'ibm863':
  9197. return 'IBM863';
  9198. case 'cp864':
  9199. case 'csibm864':
  9200. case 'ibm864':
  9201. return 'IBM864';
  9202. case '865':
  9203. case 'cp865':
  9204. case 'csibm865':
  9205. case 'ibm865':
  9206. return 'IBM865';
  9207. case '866':
  9208. case 'cp866':
  9209. case 'csibm866':
  9210. case 'ibm866':
  9211. return 'IBM866';
  9212. case 'cp868':
  9213. case 'cpar':
  9214. case 'csibm868':
  9215. case 'ibm868':
  9216. return 'IBM868';
  9217. case '869':
  9218. case 'cp869':
  9219. case 'cpgr':
  9220. case 'csibm869':
  9221. case 'ibm869':
  9222. return 'IBM869';
  9223. case 'cp870':
  9224. case 'csibm870':
  9225. case 'ebcdiccproece':
  9226. case 'ebcdiccpyu':
  9227. case 'ibm870':
  9228. return 'IBM870';
  9229. case 'cp871':
  9230. case 'csibm871':
  9231. case 'ebcdiccpis':
  9232. case 'ibm871':
  9233. return 'IBM871';
  9234. case 'cp880':
  9235. case 'csibm880':
  9236. case 'ebcdiccyrillic':
  9237. case 'ibm880':
  9238. return 'IBM880';
  9239. case 'cp891':
  9240. case 'csibm891':
  9241. case 'ibm891':
  9242. return 'IBM891';
  9243. case 'cp903':
  9244. case 'csibm903':
  9245. case 'ibm903':
  9246. return 'IBM903';
  9247. case '904':
  9248. case 'cp904':
  9249. case 'csibbm904':
  9250. case 'ibm904':
  9251. return 'IBM904';
  9252. case 'cp905':
  9253. case 'csibm905':
  9254. case 'ebcdiccptr':
  9255. case 'ibm905':
  9256. return 'IBM905';
  9257. case 'cp918':
  9258. case 'csibm918':
  9259. case 'ebcdiccpar2':
  9260. case 'ibm918':
  9261. return 'IBM918';
  9262. case 'cp1026':
  9263. case 'csibm1026':
  9264. case 'ibm1026':
  9265. return 'IBM1026';
  9266. case 'ibm1047':
  9267. return 'IBM1047';
  9268. case 'csiso143iecp271':
  9269. case 'iecp271':
  9270. case 'isoir143':
  9271. return 'IEC_P27-1';
  9272. case 'csiso49inis':
  9273. case 'inis':
  9274. case 'isoir49':
  9275. return 'INIS';
  9276. case 'csiso50inis8':
  9277. case 'inis8':
  9278. case 'isoir50':
  9279. return 'INIS-8';
  9280. case 'csiso51iniscyrillic':
  9281. case 'iniscyrillic':
  9282. case 'isoir51':
  9283. return 'INIS-cyrillic';
  9284. case 'csinvariant':
  9285. case 'invariant':
  9286. return 'INVARIANT';
  9287. case 'iso2022cn':
  9288. return 'ISO-2022-CN';
  9289. case 'iso2022cnext':
  9290. return 'ISO-2022-CN-EXT';
  9291. case 'csiso2022jp':
  9292. case 'iso2022jp':
  9293. return 'ISO-2022-JP';
  9294. case 'csiso2022jp2':
  9295. case 'iso2022jp2':
  9296. return 'ISO-2022-JP-2';
  9297. case 'csiso2022kr':
  9298. case 'iso2022kr':
  9299. return 'ISO-2022-KR';
  9300. case 'cswindows30latin1':
  9301. case 'iso88591windows30latin1':
  9302. return 'ISO-8859-1-Windows-3.0-Latin-1';
  9303. case 'cswindows31latin1':
  9304. case 'iso88591windows31latin1':
  9305. return 'ISO-8859-1-Windows-3.1-Latin-1';
  9306. case 'csisolatin2':
  9307. case 'iso88592':
  9308. case 'iso885921987':
  9309. case 'isoir101':
  9310. case 'l2':
  9311. case 'latin2':
  9312. return 'ISO-8859-2';
  9313. case 'cswindows31latin2':
  9314. case 'iso88592windowslatin2':
  9315. return 'ISO-8859-2-Windows-Latin-2';
  9316. case 'csisolatin3':
  9317. case 'iso88593':
  9318. case 'iso885931988':
  9319. case 'isoir109':
  9320. case 'l3':
  9321. case 'latin3':
  9322. return 'ISO-8859-3';
  9323. case 'csisolatin4':
  9324. case 'iso88594':
  9325. case 'iso885941988':
  9326. case 'isoir110':
  9327. case 'l4':
  9328. case 'latin4':
  9329. return 'ISO-8859-4';
  9330. case 'csisolatincyrillic':
  9331. case 'cyrillic':
  9332. case 'iso88595':
  9333. case 'iso885951988':
  9334. case 'isoir144':
  9335. return 'ISO-8859-5';
  9336. case 'arabic':
  9337. case 'asmo708':
  9338. case 'csisolatinarabic':
  9339. case 'ecma114':
  9340. case 'iso88596':
  9341. case 'iso885961987':
  9342. case 'isoir127':
  9343. return 'ISO-8859-6';
  9344. case 'csiso88596e':
  9345. case 'iso88596e':
  9346. return 'ISO-8859-6-E';
  9347. case 'csiso88596i':
  9348. case 'iso88596i':
  9349. return 'ISO-8859-6-I';
  9350. case 'csisolatingreek':
  9351. case 'ecma118':
  9352. case 'elot928':
  9353. case 'greek':
  9354. case 'greek8':
  9355. case 'iso88597':
  9356. case 'iso885971987':
  9357. case 'isoir126':
  9358. return 'ISO-8859-7';
  9359. case 'csisolatinhebrew':
  9360. case 'hebrew':
  9361. case 'iso88598':
  9362. case 'iso885981988':
  9363. case 'isoir138':
  9364. return 'ISO-8859-8';
  9365. case 'csiso88598e':
  9366. case 'iso88598e':
  9367. return 'ISO-8859-8-E';
  9368. case 'csiso88598i':
  9369. case 'iso88598i':
  9370. return 'ISO-8859-8-I';
  9371. case 'cswindows31latin5':
  9372. case 'iso88599windowslatin5':
  9373. return 'ISO-8859-9-Windows-Latin-5';
  9374. case 'csisolatin6':
  9375. case 'iso885910':
  9376. case 'iso8859101992':
  9377. case 'isoir157':
  9378. case 'l6':
  9379. case 'latin6':
  9380. return 'ISO-8859-10';
  9381. case 'iso885913':
  9382. return 'ISO-8859-13';
  9383. case 'iso885914':
  9384. case 'iso8859141998':
  9385. case 'isoceltic':
  9386. case 'isoir199':
  9387. case 'l8':
  9388. case 'latin8':
  9389. return 'ISO-8859-14';
  9390. case 'iso885915':
  9391. case 'latin9':
  9392. return 'ISO-8859-15';
  9393. case 'iso885916':
  9394. case 'iso8859162001':
  9395. case 'isoir226':
  9396. case 'l10':
  9397. case 'latin10':
  9398. return 'ISO-8859-16';
  9399. case 'iso10646j1':
  9400. return 'ISO-10646-J-1';
  9401. case 'csunicode':
  9402. case 'iso10646ucs2':
  9403. return 'ISO-10646-UCS-2';
  9404. case 'csucs4':
  9405. case 'iso10646ucs4':
  9406. return 'ISO-10646-UCS-4';
  9407. case 'csunicodeascii':
  9408. case 'iso10646ucsbasic':
  9409. return 'ISO-10646-UCS-Basic';
  9410. case 'csunicodelatin1':
  9411. case 'iso10646':
  9412. case 'iso10646unicodelatin1':
  9413. return 'ISO-10646-Unicode-Latin1';
  9414. case 'csiso10646utf1':
  9415. case 'iso10646utf1':
  9416. return 'ISO-10646-UTF-1';
  9417. case 'csiso115481':
  9418. case 'iso115481':
  9419. case 'isotr115481':
  9420. return 'ISO-11548-1';
  9421. case 'csiso90':
  9422. case 'isoir90':
  9423. return 'iso-ir-90';
  9424. case 'csunicodeibm1261':
  9425. case 'isounicodeibm1261':
  9426. return 'ISO-Unicode-IBM-1261';
  9427. case 'csunicodeibm1264':
  9428. case 'isounicodeibm1264':
  9429. return 'ISO-Unicode-IBM-1264';
  9430. case 'csunicodeibm1265':
  9431. case 'isounicodeibm1265':
  9432. return 'ISO-Unicode-IBM-1265';
  9433. case 'csunicodeibm1268':
  9434. case 'isounicodeibm1268':
  9435. return 'ISO-Unicode-IBM-1268';
  9436. case 'csunicodeibm1276':
  9437. case 'isounicodeibm1276':
  9438. return 'ISO-Unicode-IBM-1276';
  9439. case 'csiso646basic1983':
  9440. case 'iso646basic1983':
  9441. case 'ref':
  9442. return 'ISO_646.basic:1983';
  9443. case 'csiso2intlrefversion':
  9444. case 'irv':
  9445. case 'iso646irv1983':
  9446. case 'isoir2':
  9447. return 'ISO_646.irv:1983';
  9448. case 'csiso2033':
  9449. case 'e13b':
  9450. case 'iso20331983':
  9451. case 'isoir98':
  9452. return 'ISO_2033-1983';
  9453. case 'csiso5427cyrillic':
  9454. case 'iso5427':
  9455. case 'isoir37':
  9456. return 'ISO_5427';
  9457. case 'iso5427cyrillic1981':
  9458. case 'iso54271981':
  9459. case 'isoir54':
  9460. return 'ISO_5427:1981';
  9461. case 'csiso5428greek':
  9462. case 'iso54281980':
  9463. case 'isoir55':
  9464. return 'ISO_5428:1980';
  9465. case 'csiso6937add':
  9466. case 'iso6937225':
  9467. case 'isoir152':
  9468. return 'ISO_6937-2-25';
  9469. case 'csisotextcomm':
  9470. case 'iso69372add':
  9471. case 'isoir142':
  9472. return 'ISO_6937-2-add';
  9473. case 'csiso8859supp':
  9474. case 'iso8859supp':
  9475. case 'isoir154':
  9476. case 'latin125':
  9477. return 'ISO_8859-supp';
  9478. case 'csiso10367box':
  9479. case 'iso10367box':
  9480. case 'isoir155':
  9481. return 'ISO_10367-box';
  9482. case 'csiso15italian':
  9483. case 'iso646it':
  9484. case 'isoir15':
  9485. case 'it':
  9486. return 'IT';
  9487. case 'csiso13jisc6220jp':
  9488. case 'isoir13':
  9489. case 'jisc62201969':
  9490. case 'jisc62201969jp':
  9491. case 'katakana':
  9492. case 'x2017':
  9493. return 'JIS_C6220-1969-jp';
  9494. case 'csiso14jisc6220ro':
  9495. case 'iso646jp':
  9496. case 'isoir14':
  9497. case 'jisc62201969ro':
  9498. case 'jp':
  9499. return 'JIS_C6220-1969-ro';
  9500. case 'csiso42jisc62261978':
  9501. case 'isoir42':
  9502. case 'jisc62261978':
  9503. return 'JIS_C6226-1978';
  9504. case 'csiso87jisx208':
  9505. case 'isoir87':
  9506. case 'jisc62261983':
  9507. case 'jisx2081983':
  9508. case 'x208':
  9509. return 'JIS_C6226-1983';
  9510. case 'csiso91jisc62291984a':
  9511. case 'isoir91':
  9512. case 'jisc62291984a':
  9513. case 'jpocra':
  9514. return 'JIS_C6229-1984-a';
  9515. case 'csiso92jisc62991984b':
  9516. case 'iso646jpocrb':
  9517. case 'isoir92':
  9518. case 'jisc62291984b':
  9519. case 'jpocrb':
  9520. return 'JIS_C6229-1984-b';
  9521. case 'csiso93jis62291984badd':
  9522. case 'isoir93':
  9523. case 'jisc62291984badd':
  9524. case 'jpocrbadd':
  9525. return 'JIS_C6229-1984-b-add';
  9526. case 'csiso94jis62291984hand':
  9527. case 'isoir94':
  9528. case 'jisc62291984hand':
  9529. case 'jpocrhand':
  9530. return 'JIS_C6229-1984-hand';
  9531. case 'csiso95jis62291984handadd':
  9532. case 'isoir95':
  9533. case 'jisc62291984handadd':
  9534. case 'jpocrhandadd':
  9535. return 'JIS_C6229-1984-hand-add';
  9536. case 'csiso96jisc62291984kana':
  9537. case 'isoir96':
  9538. case 'jisc62291984kana':
  9539. return 'JIS_C6229-1984-kana';
  9540. case 'csjisencoding':
  9541. case 'jisencoding':
  9542. return 'JIS_Encoding';
  9543. case 'cshalfwidthkatakana':
  9544. case 'jisx201':
  9545. case 'x201':
  9546. return 'JIS_X0201';
  9547. case 'csiso159jisx2121990':
  9548. case 'isoir159':
  9549. case 'jisx2121990':
  9550. case 'x212':
  9551. return 'JIS_X0212-1990';
  9552. case 'csiso141jusib1002':
  9553. case 'iso646yu':
  9554. case 'isoir141':
  9555. case 'js':
  9556. case 'jusib1002':
  9557. case 'yu':
  9558. return 'JUS_I.B1.002';
  9559. case 'csiso147macedonian':
  9560. case 'isoir147':
  9561. case 'jusib1003mac':
  9562. case 'macedonian':
  9563. return 'JUS_I.B1.003-mac';
  9564. case 'csiso146serbian':
  9565. case 'isoir146':
  9566. case 'jusib1003serb':
  9567. case 'serbian':
  9568. return 'JUS_I.B1.003-serb';
  9569. case 'koi7switched':
  9570. return 'KOI7-switched';
  9571. case 'cskoi8r':
  9572. case 'koi8r':
  9573. return 'KOI8-R';
  9574. case 'koi8u':
  9575. return 'KOI8-U';
  9576. case 'csksc5636':
  9577. case 'iso646kr':
  9578. case 'ksc5636':
  9579. return 'KSC5636';
  9580. case 'cskz1048':
  9581. case 'kz1048':
  9582. case 'rk1048':
  9583. case 'strk10482002':
  9584. return 'KZ-1048';
  9585. case 'csiso19latingreek':
  9586. case 'isoir19':
  9587. case 'latingreek':
  9588. return 'latin-greek';
  9589. case 'csiso27latingreek1':
  9590. case 'isoir27':
  9591. case 'latingreek1':
  9592. return 'Latin-greek-1';
  9593. case 'csiso158lap':
  9594. case 'isoir158':
  9595. case 'lap':
  9596. case 'latinlap':
  9597. return 'latin-lap';
  9598. case 'csmacintosh':
  9599. case 'mac':
  9600. case 'macintosh':
  9601. return 'macintosh';
  9602. case 'csmicrosoftpublishing':
  9603. case 'microsoftpublishing':
  9604. return 'Microsoft-Publishing';
  9605. case 'csmnem':
  9606. case 'mnem':
  9607. return 'MNEM';
  9608. case 'csmnemonic':
  9609. case 'mnemonic':
  9610. return 'MNEMONIC';
  9611. case 'csiso86hungarian':
  9612. case 'hu':
  9613. case 'iso646hu':
  9614. case 'isoir86':
  9615. case 'msz77953':
  9616. return 'MSZ_7795.3';
  9617. case 'csnatsdano':
  9618. case 'isoir91':
  9619. case 'natsdano':
  9620. return 'NATS-DANO';
  9621. case 'csnatsdanoadd':
  9622. case 'isoir92':
  9623. case 'natsdanoadd':
  9624. return 'NATS-DANO-ADD';
  9625. case 'csnatssefi':
  9626. case 'isoir81':
  9627. case 'natssefi':
  9628. return 'NATS-SEFI';
  9629. case 'csnatssefiadd':
  9630. case 'isoir82':
  9631. case 'natssefiadd':
  9632. return 'NATS-SEFI-ADD';
  9633. case 'csiso151cuba':
  9634. case 'cuba':
  9635. case 'iso646cu':
  9636. case 'isoir151':
  9637. case 'ncnc1081':
  9638. return 'NC_NC00-10:81';
  9639. case 'csiso69french':
  9640. case 'fr':
  9641. case 'iso646fr':
  9642. case 'isoir69':
  9643. case 'nfz62010':
  9644. return 'NF_Z_62-010';
  9645. case 'csiso25french':
  9646. case 'iso646fr1':
  9647. case 'isoir25':
  9648. case 'nfz620101973':
  9649. return 'NF_Z_62-010_(1973)';
  9650. case 'csiso60danishnorwegian':
  9651. case 'csiso60norwegian1':
  9652. case 'iso646no':
  9653. case 'isoir60':
  9654. case 'no':
  9655. case 'ns45511':
  9656. return 'NS_4551-1';
  9657. case 'csiso61norwegian2':
  9658. case 'iso646no2':
  9659. case 'isoir61':
  9660. case 'no2':
  9661. case 'ns45512':
  9662. return 'NS_4551-2';
  9663. case 'osdebcdicdf3irv':
  9664. return 'OSD_EBCDIC_DF03_IRV';
  9665. case 'osdebcdicdf41':
  9666. return 'OSD_EBCDIC_DF04_1';
  9667. case 'osdebcdicdf415':
  9668. return 'OSD_EBCDIC_DF04_15';
  9669. case 'cspc8danishnorwegian':
  9670. case 'pc8danishnorwegian':
  9671. return 'PC8-Danish-Norwegian';
  9672. case 'cspc8turkish':
  9673. case 'pc8turkish':
  9674. return 'PC8-Turkish';
  9675. case 'csiso16portuguese':
  9676. case 'iso646pt':
  9677. case 'isoir16':
  9678. case 'pt':
  9679. return 'PT';
  9680. case 'csiso84portuguese2':
  9681. case 'iso646pt2':
  9682. case 'isoir84':
  9683. case 'pt2':
  9684. return 'PT2';
  9685. case 'cp154':
  9686. case 'csptcp154':
  9687. case 'cyrillicasian':
  9688. case 'pt154':
  9689. case 'ptcp154':
  9690. return 'PTCP154';
  9691. case 'scsu':
  9692. return 'SCSU';
  9693. case 'csiso10swedish':
  9694. case 'fi':
  9695. case 'iso646fi':
  9696. case 'iso646se':
  9697. case 'isoir10':
  9698. case 'se':
  9699. case 'sen850200b':
  9700. return 'SEN_850200_B';
  9701. case 'csiso11swedishfornames':
  9702. case 'iso646se2':
  9703. case 'isoir11':
  9704. case 'se2':
  9705. case 'sen850200c':
  9706. return 'SEN_850200_C';
  9707. case 'csshiftjis':
  9708. case 'mskanji':
  9709. case 'shiftjis':
  9710. return 'Shift_JIS';
  9711. case 'csiso102t617bit':
  9712. case 'isoir102':
  9713. case 't617bit':
  9714. return 'T.61-7bit';
  9715. case 'csiso103t618bit':
  9716. case 'isoir103':
  9717. case 't61':
  9718. case 't618bit':
  9719. return 'T.61-8bit';
  9720. case 'csiso128t101g2':
  9721. case 'isoir128':
  9722. case 't101g2':
  9723. return 'T.101-G2';
  9724. case 'cstscii':
  9725. case 'tscii':
  9726. return 'TSCII';
  9727. case 'csunicode11':
  9728. case 'unicode11':
  9729. return 'UNICODE-1-1';
  9730. case 'csunicode11utf7':
  9731. case 'unicode11utf7':
  9732. return 'UNICODE-1-1-UTF-7';
  9733. case 'csunknown8bit':
  9734. case 'unknown8bit':
  9735. return 'UNKNOWN-8BIT';
  9736. case 'ansix341968':
  9737. case 'ansix341986':
  9738. case 'ascii':
  9739. case 'cp367':
  9740. case 'csascii':
  9741. case 'ibm367':
  9742. case 'iso646irv1991':
  9743. case 'iso646us':
  9744. case 'isoir6':
  9745. case 'us':
  9746. case 'usascii':
  9747. return 'US-ASCII';
  9748. case 'csusdk':
  9749. case 'usdk':
  9750. return 'us-dk';
  9751. case 'utf7':
  9752. return 'UTF-7';
  9753. case 'utf8':
  9754. return 'UTF-8';
  9755. case 'utf16':
  9756. return 'UTF-16';
  9757. case 'utf16be':
  9758. return 'UTF-16BE';
  9759. case 'utf16le':
  9760. return 'UTF-16LE';
  9761. case 'utf32':
  9762. return 'UTF-32';
  9763. case 'utf32be':
  9764. return 'UTF-32BE';
  9765. case 'utf32le':
  9766. return 'UTF-32LE';
  9767. case 'csventurainternational':
  9768. case 'venturainternational':
  9769. return 'Ventura-International';
  9770. case 'csventuramath':
  9771. case 'venturamath':
  9772. return 'Ventura-Math';
  9773. case 'csventuraus':
  9774. case 'venturaus':
  9775. return 'Ventura-US';
  9776. case 'csiso70videotexsupp1':
  9777. case 'isoir70':
  9778. case 'videotexsuppl':
  9779. return 'videotex-suppl';
  9780. case 'csviqr':
  9781. case 'viqr':
  9782. return 'VIQR';
  9783. case 'csviscii':
  9784. case 'viscii':
  9785. return 'VISCII';
  9786. case 'cswindows31j':
  9787. case 'windows31j':
  9788. return 'Windows-31J';
  9789. case 'iso885911':
  9790. case 'tis620':
  9791. return 'windows-874';
  9792. case 'cseuckr':
  9793. case 'csksc56011987':
  9794. case 'euckr':
  9795. case 'isoir149':
  9796. case 'korean':
  9797. case 'ksc5601':
  9798. case 'ksc56011987':
  9799. case 'ksc56011989':
  9800. case 'windows949':
  9801. return 'windows-949';
  9802. case 'windows1250':
  9803. return 'windows-1250';
  9804. case 'windows1251':
  9805. return 'windows-1251';
  9806. case 'cp819':
  9807. case 'csisolatin1':
  9808. case 'ibm819':
  9809. case 'iso88591':
  9810. case 'iso885911987':
  9811. case 'isoir100':
  9812. case 'l1':
  9813. case 'latin1':
  9814. case 'windows1252':
  9815. return 'windows-1252';
  9816. case 'windows1253':
  9817. return 'windows-1253';
  9818. case 'csisolatin5':
  9819. case 'iso88599':
  9820. case 'iso885991989':
  9821. case 'isoir148':
  9822. case 'l5':
  9823. case 'latin5':
  9824. case 'windows1254':
  9825. return 'windows-1254';
  9826. case 'windows1255':
  9827. return 'windows-1255';
  9828. case 'windows1256':
  9829. return 'windows-1256';
  9830. case 'windows1257':
  9831. return 'windows-1257';
  9832. case 'windows1258':
  9833. return 'windows-1258';
  9834. default:
  9835. return $charset;
  9836. }
  9837. }
  9838. function get_curl_version()
  9839. {
  9840. if (is_array($curl = curl_version()))
  9841. {
  9842. $curl = $curl['version'];
  9843. }
  9844. elseif (substr($curl, 0, 5) === 'curl/')
  9845. {
  9846. $curl = substr($curl, 5, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 5));
  9847. }
  9848. elseif (substr($curl, 0, 8) === 'libcurl/')
  9849. {
  9850. $curl = substr($curl, 8, strcspn($curl, "\x09\x0A\x0B\x0C\x0D", 8));
  9851. }
  9852. else
  9853. {
  9854. $curl = 0;
  9855. }
  9856. return $curl;
  9857. }
  9858. function is_subclass_of($class1, $class2)
  9859. {
  9860. if (func_num_args() !== 2)
  9861. {
  9862. trigger_error('Wrong parameter count for SimplePie_Misc::is_subclass_of()', E_USER_WARNING);
  9863. }
  9864. elseif (version_compare(PHP_VERSION, '5.0.3', '>=') || is_object($class1))
  9865. {
  9866. return is_subclass_of($class1, $class2);
  9867. }
  9868. elseif (is_string($class1) && is_string($class2))
  9869. {
  9870. if (class_exists($class1))
  9871. {
  9872. if (class_exists($class2))
  9873. {
  9874. $class2 = strtolower($class2);
  9875. while ($class1 = strtolower(get_parent_class($class1)))
  9876. {
  9877. if ($class1 === $class2)
  9878. {
  9879. return true;
  9880. }
  9881. }
  9882. }
  9883. }
  9884. else
  9885. {
  9886. trigger_error('Unknown class passed as parameter', E_USER_WARNNG);
  9887. }
  9888. }
  9889. return false;
  9890. }
  9891. /**
  9892. * Strip HTML comments
  9893. *
  9894. * @access public
  9895. * @param string $data Data to strip comments from
  9896. * @return string Comment stripped string
  9897. */
  9898. function strip_comments($data)
  9899. {
  9900. $output = '';
  9901. while (($start = strpos($data, '<!--')) !== false)
  9902. {
  9903. $output .= substr($data, 0, $start);
  9904. if (($end = strpos($data, '-->', $start)) !== false)
  9905. {
  9906. $data = substr_replace($data, '', 0, $end + 3);
  9907. }
  9908. else
  9909. {
  9910. $data = '';
  9911. }
  9912. }
  9913. return $output . $data;
  9914. }
  9915. function parse_date($dt)
  9916. {
  9917. $parser = SimplePie_Parse_Date::get();
  9918. return $parser->parse($dt);
  9919. }
  9920. /**
  9921. * Decode HTML entities
  9922. *
  9923. * @static
  9924. * @access public
  9925. * @param string $data Input data
  9926. * @return string Output data
  9927. */
  9928. function entities_decode($data)
  9929. {
  9930. $decoder = new SimplePie_Decode_HTML_Entities($data);
  9931. return $decoder->parse();
  9932. }
  9933. /**
  9934. * Remove RFC822 comments
  9935. *
  9936. * @access public
  9937. * @param string $data Data to strip comments from
  9938. * @return string Comment stripped string
  9939. */
  9940. function uncomment_rfc822($string)
  9941. {
  9942. $string = (string) $string;
  9943. $position = 0;
  9944. $length = strlen($string);
  9945. $depth = 0;
  9946. $output = '';
  9947. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  9948. {
  9949. $output .= substr($string, $position, $pos - $position);
  9950. $position = $pos + 1;
  9951. if ($string[$pos - 1] !== '\\')
  9952. {
  9953. $depth++;
  9954. while ($depth && $position < $length)
  9955. {
  9956. $position += strcspn($string, '()', $position);
  9957. if ($string[$position - 1] === '\\')
  9958. {
  9959. $position++;
  9960. continue;
  9961. }
  9962. elseif (isset($string[$position]))
  9963. {
  9964. switch ($string[$position])
  9965. {
  9966. case '(':
  9967. $depth++;
  9968. break;
  9969. case ')':
  9970. $depth--;
  9971. break;
  9972. }
  9973. $position++;
  9974. }
  9975. else
  9976. {
  9977. break;
  9978. }
  9979. }
  9980. }
  9981. else
  9982. {
  9983. $output .= '(';
  9984. }
  9985. }
  9986. $output .= substr($string, $position);
  9987. return $output;
  9988. }
  9989. function parse_mime($mime)
  9990. {
  9991. if (($pos = strpos($mime, ';')) === false)
  9992. {
  9993. return trim($mime);
  9994. }
  9995. else
  9996. {
  9997. return trim(substr($mime, 0, $pos));
  9998. }
  9999. }
  10000. function htmlspecialchars_decode($string, $quote_style)
  10001. {
  10002. if (function_exists('htmlspecialchars_decode'))
  10003. {
  10004. return htmlspecialchars_decode($string, $quote_style);
  10005. }
  10006. else
  10007. {
  10008. return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
  10009. }
  10010. }
  10011. function atom_03_construct_type($attribs)
  10012. {
  10013. if (isset($attribs['']['mode']) && strtolower(trim($attribs['']['mode']) === 'base64'))
  10014. {
  10015. $mode = SIMPLEPIE_CONSTRUCT_BASE64;
  10016. }
  10017. else
  10018. {
  10019. $mode = SIMPLEPIE_CONSTRUCT_NONE;
  10020. }
  10021. if (isset($attribs['']['type']))
  10022. {
  10023. switch (strtolower(trim($attribs['']['type'])))
  10024. {
  10025. case 'text':
  10026. case 'text/plain':
  10027. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  10028. case 'html':
  10029. case 'text/html':
  10030. return SIMPLEPIE_CONSTRUCT_HTML | $mode;
  10031. case 'xhtml':
  10032. case 'application/xhtml+xml':
  10033. return SIMPLEPIE_CONSTRUCT_XHTML | $mode;
  10034. default:
  10035. return SIMPLEPIE_CONSTRUCT_NONE | $mode;
  10036. }
  10037. }
  10038. else
  10039. {
  10040. return SIMPLEPIE_CONSTRUCT_TEXT | $mode;
  10041. }
  10042. }
  10043. function atom_10_construct_type($attribs)
  10044. {
  10045. if (isset($attribs['']['type']))
  10046. {
  10047. switch (strtolower(trim($attribs['']['type'])))
  10048. {
  10049. case 'text':
  10050. return SIMPLEPIE_CONSTRUCT_TEXT;
  10051. case 'html':
  10052. return SIMPLEPIE_CONSTRUCT_HTML;
  10053. case 'xhtml':
  10054. return SIMPLEPIE_CONSTRUCT_XHTML;
  10055. default:
  10056. return SIMPLEPIE_CONSTRUCT_NONE;
  10057. }
  10058. }
  10059. return SIMPLEPIE_CONSTRUCT_TEXT;
  10060. }
  10061. function atom_10_content_construct_type($attribs)
  10062. {
  10063. if (isset($attribs['']['type']))
  10064. {
  10065. $type = strtolower(trim($attribs['']['type']));
  10066. switch ($type)
  10067. {
  10068. case 'text':
  10069. return SIMPLEPIE_CONSTRUCT_TEXT;
  10070. case 'html':
  10071. return SIMPLEPIE_CONSTRUCT_HTML;
  10072. case 'xhtml':
  10073. return SIMPLEPIE_CONSTRUCT_XHTML;
  10074. }
  10075. if (in_array(substr($type, -4), array('+xml', '/xml')) || substr($type, 0, 5) === 'text/')
  10076. {
  10077. return SIMPLEPIE_CONSTRUCT_NONE;
  10078. }
  10079. else
  10080. {
  10081. return SIMPLEPIE_CONSTRUCT_BASE64;
  10082. }
  10083. }
  10084. else
  10085. {
  10086. return SIMPLEPIE_CONSTRUCT_TEXT;
  10087. }
  10088. }
  10089. function is_isegment_nz_nc($string)
  10090. {
  10091. 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);
  10092. }
  10093. function space_seperated_tokens($string)
  10094. {
  10095. $space_characters = "\x20\x09\x0A\x0B\x0C\x0D";
  10096. $string_length = strlen($string);
  10097. $position = strspn($string, $space_characters);
  10098. $tokens = array();
  10099. while ($position < $string_length)
  10100. {
  10101. $len = strcspn($string, $space_characters, $position);
  10102. $tokens[] = substr($string, $position, $len);
  10103. $position += $len;
  10104. $position += strspn($string, $space_characters, $position);
  10105. }
  10106. return $tokens;
  10107. }
  10108. function array_unique($array)
  10109. {
  10110. if (version_compare(PHP_VERSION, '5.2', '>='))
  10111. {
  10112. return array_unique($array);
  10113. }
  10114. else
  10115. {
  10116. $array = (array) $array;
  10117. $new_array = array();
  10118. $new_array_strings = array();
  10119. foreach ($array as $key => $value)
  10120. {
  10121. if (is_object($value))
  10122. {
  10123. if (method_exists($value, '__toString'))
  10124. {
  10125. $cmp = $value->__toString();
  10126. }
  10127. else
  10128. {
  10129. trigger_error('Object of class ' . get_class($value) . ' could not be converted to string', E_USER_ERROR);
  10130. }
  10131. }
  10132. elseif (is_array($value))
  10133. {
  10134. $cmp = (string) reset($value);
  10135. }
  10136. else
  10137. {
  10138. $cmp = (string) $value;
  10139. }
  10140. if (!in_array($cmp, $new_array_strings))
  10141. {
  10142. $new_array[$key] = $value;
  10143. $new_array_strings[] = $cmp;
  10144. }
  10145. }
  10146. return $new_array;
  10147. }
  10148. }
  10149. /**
  10150. * Converts a unicode codepoint to a UTF-8 character
  10151. *
  10152. * @static
  10153. * @access public
  10154. * @param int $codepoint Unicode codepoint
  10155. * @return string UTF-8 character
  10156. */
  10157. function codepoint_to_utf8($codepoint)
  10158. {
  10159. $codepoint = (int) $codepoint;
  10160. if ($codepoint < 0)
  10161. {
  10162. return false;
  10163. }
  10164. else if ($codepoint <= 0x7f)
  10165. {
  10166. return chr($codepoint);
  10167. }
  10168. else if ($codepoint <= 0x7ff)
  10169. {
  10170. return chr(0xc0 | ($codepoint >> 6)) . chr(0x80 | ($codepoint & 0x3f));
  10171. }
  10172. else if ($codepoint <= 0xffff)
  10173. {
  10174. return chr(0xe0 | ($codepoint >> 12)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  10175. }
  10176. else if ($codepoint <= 0x10ffff)
  10177. {
  10178. return chr(0xf0 | ($codepoint >> 18)) . chr(0x80 | (($codepoint >> 12) & 0x3f)) . chr(0x80 | (($codepoint >> 6) & 0x3f)) . chr(0x80 | ($codepoint & 0x3f));
  10179. }
  10180. else
  10181. {
  10182. // U+FFFD REPLACEMENT CHARACTER
  10183. return "\xEF\xBF\xBD";
  10184. }
  10185. }
  10186. /**
  10187. * Re-implementation of PHP 5's stripos()
  10188. *
  10189. * Returns the numeric position of the first occurrence of needle in the
  10190. * haystack string.
  10191. *
  10192. * @static
  10193. * @access string
  10194. * @param object $haystack
  10195. * @param string $needle Note that the needle may be a string of one or more
  10196. * characters. If needle is not a string, it is converted to an integer
  10197. * and applied as the ordinal value of a character.
  10198. * @param int $offset The optional offset parameter allows you to specify which
  10199. * character in haystack to start searching. The position returned is still
  10200. * relative to the beginning of haystack.
  10201. * @return bool If needle is not found, stripos() will return boolean false.
  10202. */
  10203. function stripos($haystack, $needle, $offset = 0)
  10204. {
  10205. if (function_exists('stripos'))
  10206. {
  10207. return stripos($haystack, $needle, $offset);
  10208. }
  10209. else
  10210. {
  10211. if (is_string($needle))
  10212. {
  10213. $needle = strtolower($needle);
  10214. }
  10215. elseif (is_int($needle) || is_bool($needle) || is_double($needle))
  10216. {
  10217. $needle = strtolower(chr($needle));
  10218. }
  10219. else
  10220. {
  10221. trigger_error('needle is not a string or an integer', E_USER_WARNING);
  10222. return false;
  10223. }
  10224. return strpos(strtolower($haystack), $needle, $offset);
  10225. }
  10226. }
  10227. /**
  10228. * Similar to parse_str()
  10229. *
  10230. * Returns an associative array of name/value pairs, where the value is an
  10231. * array of values that have used the same name
  10232. *
  10233. * @static
  10234. * @access string
  10235. * @param string $str The input string.
  10236. * @return array
  10237. */
  10238. function parse_str($str)
  10239. {
  10240. $return = array();
  10241. $str = explode('&', $str);
  10242. foreach ($str as $section)
  10243. {
  10244. if (strpos($section, '=') !== false)
  10245. {
  10246. list($name, $value) = explode('=', $section, 2);
  10247. $return[urldecode($name)][] = urldecode($value);
  10248. }
  10249. else
  10250. {
  10251. $return[urldecode($section)][] = null;
  10252. }
  10253. }
  10254. return $return;
  10255. }
  10256. /**
  10257. * Detect XML encoding, as per XML 1.0 Appendix F.1
  10258. *
  10259. * @todo Add support for EBCDIC
  10260. * @param string $data XML data
  10261. * @return array Possible encodings
  10262. */
  10263. function xml_encoding($data)
  10264. {
  10265. // UTF-32 Big Endian BOM
  10266. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  10267. {
  10268. $encoding[] = 'UTF-32BE';
  10269. }
  10270. // UTF-32 Little Endian BOM
  10271. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  10272. {
  10273. $encoding[] = 'UTF-32LE';
  10274. }
  10275. // UTF-16 Big Endian BOM
  10276. elseif (substr($data, 0, 2) === "\xFE\xFF")
  10277. {
  10278. $encoding[] = 'UTF-16BE';
  10279. }
  10280. // UTF-16 Little Endian BOM
  10281. elseif (substr($data, 0, 2) === "\xFF\xFE")
  10282. {
  10283. $encoding[] = 'UTF-16LE';
  10284. }
  10285. // UTF-8 BOM
  10286. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  10287. {
  10288. $encoding[] = 'UTF-8';
  10289. }
  10290. // UTF-32 Big Endian Without BOM
  10291. 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")
  10292. {
  10293. if ($pos = strpos($data, "\x00\x00\x00\x3F\x00\x00\x00\x3E"))
  10294. {
  10295. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32BE', 'UTF-8'));
  10296. if ($parser->parse())
  10297. {
  10298. $encoding[] = $parser->encoding;
  10299. }
  10300. }
  10301. $encoding[] = 'UTF-32BE';
  10302. }
  10303. // UTF-32 Little Endian Without BOM
  10304. 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")
  10305. {
  10306. if ($pos = strpos($data, "\x3F\x00\x00\x00\x3E\x00\x00\x00"))
  10307. {
  10308. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 20), 'UTF-32LE', 'UTF-8'));
  10309. if ($parser->parse())
  10310. {
  10311. $encoding[] = $parser->encoding;
  10312. }
  10313. }
  10314. $encoding[] = 'UTF-32LE';
  10315. }
  10316. // UTF-16 Big Endian Without BOM
  10317. elseif (substr($data, 0, 10) === "\x00\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C")
  10318. {
  10319. if ($pos = strpos($data, "\x00\x3F\x00\x3E"))
  10320. {
  10321. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16BE', 'UTF-8'));
  10322. if ($parser->parse())
  10323. {
  10324. $encoding[] = $parser->encoding;
  10325. }
  10326. }
  10327. $encoding[] = 'UTF-16BE';
  10328. }
  10329. // UTF-16 Little Endian Without BOM
  10330. elseif (substr($data, 0, 10) === "\x3C\x00\x3F\x00\x78\x00\x6D\x00\x6C\x00")
  10331. {
  10332. if ($pos = strpos($data, "\x3F\x00\x3E\x00"))
  10333. {
  10334. $parser = new SimplePie_XML_Declaration_Parser(SimplePie_Misc::change_encoding(substr($data, 20, $pos - 10), 'UTF-16LE', 'UTF-8'));
  10335. if ($parser->parse())
  10336. {
  10337. $encoding[] = $parser->encoding;
  10338. }
  10339. }
  10340. $encoding[] = 'UTF-16LE';
  10341. }
  10342. // US-ASCII (or superset)
  10343. elseif (substr($data, 0, 5) === "\x3C\x3F\x78\x6D\x6C")
  10344. {
  10345. if ($pos = strpos($data, "\x3F\x3E"))
  10346. {
  10347. $parser = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  10348. if ($parser->parse())
  10349. {
  10350. $encoding[] = $parser->encoding;
  10351. }
  10352. }
  10353. $encoding[] = 'UTF-8';
  10354. }
  10355. // Fallback to UTF-8
  10356. else
  10357. {
  10358. $encoding[] = 'UTF-8';
  10359. }
  10360. return $encoding;
  10361. }
  10362. function output_javascript()
  10363. {
  10364. if (function_exists('ob_gzhandler'))
  10365. {
  10366. ob_start('ob_gzhandler');
  10367. }
  10368. header('Content-type: text/javascript; charset: UTF-8');
  10369. header('Cache-Control: must-revalidate');
  10370. header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 604800) . ' GMT'); // 7 days
  10371. ?>
  10372. function embed_odeo(link) {
  10373. 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>');
  10374. }
  10375. function embed_quicktime(type, bgcolor, width, height, link, placeholder, loop) {
  10376. if (placeholder != '')
  10377. {
  10378. 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>');
  10379. }
  10380. else {
  10381. 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>');
  10382. }
  10383. }
  10384. function embed_flash(bgcolor, width, height, link, loop, type) {
  10385. 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>');
  10386. }
  10387. function embed_flv(width, height, link, placeholder, loop, player) {
  10388. 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>');
  10389. }
  10390. function embed_wmedia(width, height, link) {
  10391. document.writeln('<embed type="application/x-mplayer2" src="'+link+'" autosize="1" width="'+width+'" height="'+height+'" showcontrols="1" showstatusbar="0" showdisplay="0" autostart="0"></embed>');
  10392. }
  10393. <?php
  10394. }
  10395. }
  10396. /**
  10397. * Decode HTML Entities
  10398. *
  10399. * This implements HTML5 as of revision 967 (2007-06-28)
  10400. *
  10401. * @package SimplePie
  10402. */
  10403. class SimplePie_Decode_HTML_Entities
  10404. {
  10405. /**
  10406. * Data to be parsed
  10407. *
  10408. * @access private
  10409. * @var string
  10410. */
  10411. var $data = '';
  10412. /**
  10413. * Currently consumed bytes
  10414. *
  10415. * @access private
  10416. * @var string
  10417. */
  10418. var $consumed = '';
  10419. /**
  10420. * Position of the current byte being parsed
  10421. *
  10422. * @access private
  10423. * @var int
  10424. */
  10425. var $position = 0;
  10426. /**
  10427. * Create an instance of the class with the input data
  10428. *
  10429. * @access public
  10430. * @param string $data Input data
  10431. */
  10432. function SimplePie_Decode_HTML_Entities($data)
  10433. {
  10434. $this->data = $data;
  10435. }
  10436. /**
  10437. * Parse the input data
  10438. *
  10439. * @access public
  10440. * @return string Output data
  10441. */
  10442. function parse()
  10443. {
  10444. while (($this->position = strpos($this->data, '&', $this->position)) !== false)
  10445. {
  10446. $this->consume();
  10447. $this->entity();
  10448. $this->consumed = '';
  10449. }
  10450. return $this->data;
  10451. }
  10452. /**
  10453. * Consume the next byte
  10454. *
  10455. * @access private
  10456. * @return mixed The next byte, or false, if there is no more data
  10457. */
  10458. function consume()
  10459. {
  10460. if (isset($this->data[$this->position]))
  10461. {
  10462. $this->consumed .= $this->data[$this->position];
  10463. return $this->data[$this->position++];
  10464. }
  10465. else
  10466. {
  10467. return false;
  10468. }
  10469. }
  10470. /**
  10471. * Consume a range of characters
  10472. *
  10473. * @access private
  10474. * @param string $chars Characters to consume
  10475. * @return mixed A series of characters that match the range, or false
  10476. */
  10477. function consume_range($chars)
  10478. {
  10479. if ($len = strspn($this->data, $chars, $this->position))
  10480. {
  10481. $data = substr($this->data, $this->position, $len);
  10482. $this->consumed .= $data;
  10483. $this->position += $len;
  10484. return $data;
  10485. }
  10486. else
  10487. {
  10488. return false;
  10489. }
  10490. }
  10491. /**
  10492. * Unconsume one byte
  10493. *
  10494. * @access private
  10495. */
  10496. function unconsume()
  10497. {
  10498. $this->consumed = substr($this->consumed, 0, -1);
  10499. $this->position--;
  10500. }
  10501. /**
  10502. * Decode an entity
  10503. *
  10504. * @access private
  10505. */
  10506. function entity()
  10507. {
  10508. switch ($this->consume())
  10509. {
  10510. case "\x09":
  10511. case "\x0A":
  10512. case "\x0B":
  10513. case "\x0B":
  10514. case "\x0C":
  10515. case "\x20":
  10516. case "\x3C":
  10517. case "\x26":
  10518. case false:
  10519. break;
  10520. case "\x23":
  10521. switch ($this->consume())
  10522. {
  10523. case "\x78":
  10524. case "\x58":
  10525. $range = '0123456789ABCDEFabcdef';
  10526. $hex = true;
  10527. break;
  10528. default:
  10529. $range = '0123456789';
  10530. $hex = false;
  10531. $this->unconsume();
  10532. break;
  10533. }
  10534. if ($codepoint = $this->consume_range($range))
  10535. {
  10536. 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");
  10537. if ($hex)
  10538. {
  10539. $codepoint = hexdec($codepoint);
  10540. }
  10541. else
  10542. {
  10543. $codepoint = intval($codepoint);
  10544. }
  10545. if (isset($windows_1252_specials[$codepoint]))
  10546. {
  10547. $replacement = $windows_1252_specials[$codepoint];
  10548. }
  10549. else
  10550. {
  10551. $replacement = SimplePie_Misc::codepoint_to_utf8($codepoint);
  10552. }
  10553. if (!in_array($this->consume(), array(';', false), true))
  10554. {
  10555. $this->unconsume();
  10556. }
  10557. $consumed_length = strlen($this->consumed);
  10558. $this->data = substr_replace($this->data, $replacement, $this->position - $consumed_length, $consumed_length);
  10559. $this->position += strlen($replacement) - $consumed_length;
  10560. }
  10561. break;
  10562. default:
  10563. 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");
  10564. for ($i = 0, $match = null; $i < 9 && $this->consume() !== false; $i++)
  10565. {
  10566. $consumed = substr($this->consumed, 1);
  10567. if (isset($entities[$consumed]))
  10568. {
  10569. $match = $consumed;
  10570. }
  10571. }
  10572. if ($match !== null)
  10573. {
  10574. $this->data = substr_replace($this->data, $entities[$match], $this->position - strlen($consumed) - 1, strlen($match) + 1);
  10575. $this->position += strlen($entities[$match]) - strlen($consumed) - 1;
  10576. }
  10577. break;
  10578. }
  10579. }
  10580. }
  10581. /**
  10582. * IRI parser/serialiser
  10583. *
  10584. * @package SimplePie
  10585. */
  10586. class SimplePie_IRI
  10587. {
  10588. /**
  10589. * Scheme
  10590. *
  10591. * @access private
  10592. * @var string
  10593. */
  10594. var $scheme;
  10595. /**
  10596. * User Information
  10597. *
  10598. * @access private
  10599. * @var string
  10600. */
  10601. var $userinfo;
  10602. /**
  10603. * Host
  10604. *
  10605. * @access private
  10606. * @var string
  10607. */
  10608. var $host;
  10609. /**
  10610. * Port
  10611. *
  10612. * @access private
  10613. * @var string
  10614. */
  10615. var $port;
  10616. /**
  10617. * Path
  10618. *
  10619. * @access private
  10620. * @var string
  10621. */
  10622. var $path;
  10623. /**
  10624. * Query
  10625. *
  10626. * @access private
  10627. * @var string
  10628. */
  10629. var $query;
  10630. /**
  10631. * Fragment
  10632. *
  10633. * @access private
  10634. * @var string
  10635. */
  10636. var $fragment;
  10637. /**
  10638. * Whether the object represents a valid IRI
  10639. *
  10640. * @access private
  10641. * @var array
  10642. */
  10643. var $valid = array();
  10644. /**
  10645. * Return the entire IRI when you try and read the object as a string
  10646. *
  10647. * @access public
  10648. * @return string
  10649. */
  10650. function __toString()
  10651. {
  10652. return $this->get_iri();
  10653. }
  10654. /**
  10655. * Create a new IRI object, from a specified string
  10656. *
  10657. * @access public
  10658. * @param string $iri
  10659. * @return SimplePie_IRI
  10660. */
  10661. function SimplePie_IRI($iri)
  10662. {
  10663. $iri = (string) $iri;
  10664. if ($iri !== '')
  10665. {
  10666. $parsed = $this->parse_iri($iri);
  10667. $this->set_scheme($parsed['scheme']);
  10668. $this->set_authority($parsed['authority']);
  10669. $this->set_path($parsed['path']);
  10670. $this->set_query($parsed['query']);
  10671. $this->set_fragment($parsed['fragment']);
  10672. }
  10673. }
  10674. /**
  10675. * Create a new IRI object by resolving a relative IRI
  10676. *
  10677. * @static
  10678. * @access public
  10679. * @param SimplePie_IRI $base Base IRI
  10680. * @param string $relative Relative IRI
  10681. * @return SimplePie_IRI
  10682. */
  10683. function absolutize($base, $relative)
  10684. {
  10685. $relative = (string) $relative;
  10686. if ($relative !== '')
  10687. {
  10688. $relative = new SimplePie_IRI($relative);
  10689. if ($relative->get_scheme() !== null)
  10690. {
  10691. $target = $relative;
  10692. }
  10693. elseif ($base->get_iri() !== null)
  10694. {
  10695. if ($relative->get_authority() !== null)
  10696. {
  10697. $target = $relative;
  10698. $target->set_scheme($base->get_scheme());
  10699. }
  10700. else
  10701. {
  10702. $target = new SimplePie_IRI('');
  10703. $target->set_scheme($base->get_scheme());
  10704. $target->set_userinfo($base->get_userinfo());
  10705. $target->set_host($base->get_host());
  10706. $target->set_port($base->get_port());
  10707. if ($relative->get_path() !== null)
  10708. {
  10709. if (strpos($relative->get_path(), '/') === 0)
  10710. {
  10711. $target->set_path($relative->get_path());
  10712. }
  10713. elseif (($base->get_userinfo() !== null || $base->get_host() !== null || $base->get_port() !== null) && $base->get_path() === null)
  10714. {
  10715. $target->set_path('/' . $relative->get_path());
  10716. }
  10717. elseif (($last_segment = strrpos($base->get_path(), '/')) !== false)
  10718. {
  10719. $target->set_path(substr($base->get_path(), 0, $last_segment + 1) . $relative->get_path());
  10720. }
  10721. else
  10722. {
  10723. $target->set_path($relative->get_path());
  10724. }
  10725. $target->set_query($relative->get_query());
  10726. }
  10727. else
  10728. {
  10729. $target->set_path($base->get_path());
  10730. if ($relative->get_query() !== null)
  10731. {
  10732. $target->set_query($relative->get_query());
  10733. }
  10734. elseif ($base->get_query() !== null)
  10735. {
  10736. $target->set_query($base->get_query());
  10737. }
  10738. }
  10739. }
  10740. $target->set_fragment($relative->get_fragment());
  10741. }
  10742. else
  10743. {
  10744. // No base URL, just return the relative URL
  10745. $target = $relative;
  10746. }
  10747. }
  10748. else
  10749. {
  10750. $target = $base;
  10751. }
  10752. return $target;
  10753. }
  10754. /**
  10755. * Parse an IRI into scheme/authority/path/query/fragment segments
  10756. *
  10757. * @access private
  10758. * @param string $iri
  10759. * @return array
  10760. */
  10761. function parse_iri($iri)
  10762. {
  10763. preg_match('/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/', $iri, $match);
  10764. for ($i = count($match); $i <= 9; $i++)
  10765. {
  10766. $match[$i] = '';
  10767. }
  10768. return array('scheme' => $match[2], 'authority' => $match[4], 'path' => $match[5], 'query' => $match[7], 'fragment' => $match[9]);
  10769. }
  10770. /**
  10771. * Remove dot segments from a path
  10772. *
  10773. * @access private
  10774. * @param string $input
  10775. * @return string
  10776. */
  10777. function remove_dot_segments($input)
  10778. {
  10779. $output = '';
  10780. while (strpos($input, './') !== false || strpos($input, '/.') !== false || $input === '.' || $input === '..')
  10781. {
  10782. // A: If the input buffer begins with a prefix of "../" or "./", then remove that prefix from the input buffer; otherwise,
  10783. if (strpos($input, '../') === 0)
  10784. {
  10785. $input = substr($input, 3);
  10786. }
  10787. elseif (strpos($input, './') === 0)
  10788. {
  10789. $input = substr($input, 2);
  10790. }
  10791. // 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,
  10792. elseif (strpos($input, '/./') === 0)
  10793. {
  10794. $input = substr_replace($input, '/', 0, 3);
  10795. }
  10796. elseif ($input === '/.')
  10797. {
  10798. $input = '/';
  10799. }
  10800. // 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,
  10801. elseif (strpos($input, '/../') === 0)
  10802. {
  10803. $input = substr_replace($input, '/', 0, 4);
  10804. $output = substr_replace($output, '', strrpos($output, '/'));
  10805. }
  10806. elseif ($input === '/..')
  10807. {
  10808. $input = '/';
  10809. $output = substr_replace($output, '', strrpos($output, '/'));
  10810. }
  10811. // D: if the input buffer consists only of "." or "..", then remove that from the input buffer; otherwise,
  10812. elseif ($input === '.' || $input === '..')
  10813. {
  10814. $input = '';
  10815. }
  10816. // 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
  10817. elseif (($pos = strpos($input, '/', 1)) !== false)
  10818. {
  10819. $output .= substr($input, 0, $pos);
  10820. $input = substr_replace($input, '', 0, $pos);
  10821. }
  10822. else
  10823. {
  10824. $output .= $input;
  10825. $input = '';
  10826. }
  10827. }
  10828. return $output . $input;
  10829. }
  10830. /**
  10831. * Replace invalid character with percent encoding
  10832. *
  10833. * @access private
  10834. * @param string $string Input string
  10835. * @param string $valid_chars Valid characters
  10836. * @param int $case Normalise case
  10837. * @return string
  10838. */
  10839. function replace_invalid_with_pct_encoding($string, $valid_chars, $case = SIMPLEPIE_SAME_CASE)
  10840. {
  10841. // Normalise case
  10842. if ($case & SIMPLEPIE_LOWERCASE)
  10843. {
  10844. $string = strtolower($string);
  10845. }
  10846. elseif ($case & SIMPLEPIE_UPPERCASE)
  10847. {
  10848. $string = strtoupper($string);
  10849. }
  10850. // Store position and string length (to avoid constantly recalculating this)
  10851. $position = 0;
  10852. $strlen = strlen($string);
  10853. // Loop as long as we have invalid characters, advancing the position to the next invalid character
  10854. while (($position += strspn($string, $valid_chars, $position)) < $strlen)
  10855. {
  10856. // If we have a % character
  10857. if ($string[$position] === '%')
  10858. {
  10859. // If we have a pct-encoded section
  10860. if ($position + 2 < $strlen && strspn($string, '0123456789ABCDEFabcdef', $position + 1, 2) === 2)
  10861. {
  10862. // Get the the represented character
  10863. $chr = chr(hexdec(substr($string, $position + 1, 2)));
  10864. // If the character is valid, replace the pct-encoded with the actual character while normalising case
  10865. if (strpos($valid_chars, $chr) !== false)
  10866. {
  10867. if ($case & SIMPLEPIE_LOWERCASE)
  10868. {
  10869. $chr = strtolower($chr);
  10870. }
  10871. elseif ($case & SIMPLEPIE_UPPERCASE)
  10872. {
  10873. $chr = strtoupper($chr);
  10874. }
  10875. $string = substr_replace($string, $chr, $position, 3);
  10876. $strlen -= 2;
  10877. $position++;
  10878. }
  10879. // Otherwise just normalise the pct-encoded to uppercase
  10880. else
  10881. {
  10882. $string = substr_replace($string, strtoupper(substr($string, $position + 1, 2)), $position + 1, 2);
  10883. $position += 3;
  10884. }
  10885. }
  10886. // If we don't have a pct-encoded section, just replace the % with its own esccaped form
  10887. else
  10888. {
  10889. $string = substr_replace($string, '%25', $position, 1);
  10890. $strlen += 2;
  10891. $position += 3;
  10892. }
  10893. }
  10894. // If we have an invalid character, change into its pct-encoded form
  10895. else
  10896. {
  10897. $replacement = sprintf("%%%02X", ord($string[$position]));
  10898. $string = str_replace($string[$position], $replacement, $string);
  10899. $strlen = strlen($string);
  10900. }
  10901. }
  10902. return $string;
  10903. }
  10904. /**
  10905. * Check if the object represents a valid IRI
  10906. *
  10907. * @access public
  10908. * @return bool
  10909. */
  10910. function is_valid()
  10911. {
  10912. return array_sum($this->valid) === count($this->valid);
  10913. }
  10914. /**
  10915. * Set the scheme. Returns true on success, false on failure (if there are
  10916. * any invalid characters).
  10917. *
  10918. * @access public
  10919. * @param string $scheme
  10920. * @return bool
  10921. */
  10922. function set_scheme($scheme)
  10923. {
  10924. if ($scheme === null || $scheme === '')
  10925. {
  10926. $this->scheme = null;
  10927. }
  10928. else
  10929. {
  10930. $len = strlen($scheme);
  10931. switch (true)
  10932. {
  10933. case $len > 1:
  10934. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-.', 1))
  10935. {
  10936. $this->scheme = null;
  10937. $this->valid[__FUNCTION__] = false;
  10938. return false;
  10939. }
  10940. case $len > 0:
  10941. if (!strspn($scheme, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 0, 1))
  10942. {
  10943. $this->scheme = null;
  10944. $this->valid[__FUNCTION__] = false;
  10945. return false;
  10946. }
  10947. }
  10948. $this->scheme = strtolower($scheme);
  10949. }
  10950. $this->valid[__FUNCTION__] = true;
  10951. return true;
  10952. }
  10953. /**
  10954. * Set the authority. Returns true on success, false on failure (if there are
  10955. * any invalid characters).
  10956. *
  10957. * @access public
  10958. * @param string $authority
  10959. * @return bool
  10960. */
  10961. function set_authority($authority)
  10962. {
  10963. if (($userinfo_end = strrpos($authority, '@')) !== false)
  10964. {
  10965. $userinfo = substr($authority, 0, $userinfo_end);
  10966. $authority = substr($authority, $userinfo_end + 1);
  10967. }
  10968. else
  10969. {
  10970. $userinfo = null;
  10971. }
  10972. if (($port_start = strpos($authority, ':')) !== false)
  10973. {
  10974. $port = substr($authority, $port_start + 1);
  10975. $authority = substr($authority, 0, $port_start);
  10976. }
  10977. else
  10978. {
  10979. $port = null;
  10980. }
  10981. return $this->set_userinfo($userinfo) && $this->set_host($authority) && $this->set_port($port);
  10982. }
  10983. /**
  10984. * Set the userinfo.
  10985. *
  10986. * @access public
  10987. * @param string $userinfo
  10988. * @return bool
  10989. */
  10990. function set_userinfo($userinfo)
  10991. {
  10992. if ($userinfo === null || $userinfo === '')
  10993. {
  10994. $this->userinfo = null;
  10995. }
  10996. else
  10997. {
  10998. $this->userinfo = $this->replace_invalid_with_pct_encoding($userinfo, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:');
  10999. }
  11000. $this->valid[__FUNCTION__] = true;
  11001. return true;
  11002. }
  11003. /**
  11004. * Set the host. Returns true on success, false on failure (if there are
  11005. * any invalid characters).
  11006. *
  11007. * @access public
  11008. * @param string $host
  11009. * @return bool
  11010. */
  11011. function set_host($host)
  11012. {
  11013. if ($host === null || $host === '')
  11014. {
  11015. $this->host = null;
  11016. $this->valid[__FUNCTION__] = true;
  11017. return true;
  11018. }
  11019. elseif ($host[0] === '[' && substr($host, -1) === ']')
  11020. {
  11021. if (Net_IPv6::checkIPv6(substr($host, 1, -1)))
  11022. {
  11023. $this->host = $host;
  11024. $this->valid[__FUNCTION__] = true;
  11025. return true;
  11026. }
  11027. else
  11028. {
  11029. $this->host = null;
  11030. $this->valid[__FUNCTION__] = false;
  11031. return false;
  11032. }
  11033. }
  11034. else
  11035. {
  11036. $this->host = $this->replace_invalid_with_pct_encoding($host, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=', SIMPLEPIE_LOWERCASE);
  11037. $this->valid[__FUNCTION__] = true;
  11038. return true;
  11039. }
  11040. }
  11041. /**
  11042. * Set the port. Returns true on success, false on failure (if there are
  11043. * any invalid characters).
  11044. *
  11045. * @access public
  11046. * @param string $port
  11047. * @return bool
  11048. */
  11049. function set_port($port)
  11050. {
  11051. if ($port === null || $port === '')
  11052. {
  11053. $this->port = null;
  11054. $this->valid[__FUNCTION__] = true;
  11055. return true;
  11056. }
  11057. elseif (strspn($port, '0123456789') === strlen($port))
  11058. {
  11059. $this->port = (int) $port;
  11060. $this->valid[__FUNCTION__] = true;
  11061. return true;
  11062. }
  11063. else
  11064. {
  11065. $this->port = null;
  11066. $this->valid[__FUNCTION__] = false;
  11067. return false;
  11068. }
  11069. }
  11070. /**
  11071. * Set the path.
  11072. *
  11073. * @access public
  11074. * @param string $path
  11075. * @return bool
  11076. */
  11077. function set_path($path)
  11078. {
  11079. if ($path === null || $path === '')
  11080. {
  11081. $this->path = null;
  11082. $this->valid[__FUNCTION__] = true;
  11083. return true;
  11084. }
  11085. elseif (substr($path, 0, 2) === '//' && $this->userinfo === null && $this->host === null && $this->port === null)
  11086. {
  11087. $this->path = null;
  11088. $this->valid[__FUNCTION__] = false;
  11089. return false;
  11090. }
  11091. else
  11092. {
  11093. $this->path = $this->replace_invalid_with_pct_encoding($path, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=@/');
  11094. if ($this->scheme !== null)
  11095. {
  11096. $this->path = $this->remove_dot_segments($this->path);
  11097. }
  11098. $this->valid[__FUNCTION__] = true;
  11099. return true;
  11100. }
  11101. }
  11102. /**
  11103. * Set the query.
  11104. *
  11105. * @access public
  11106. * @param string $query
  11107. * @return bool
  11108. */
  11109. function set_query($query)
  11110. {
  11111. if ($query === null || $query === '')
  11112. {
  11113. $this->query = null;
  11114. }
  11115. else
  11116. {
  11117. $this->query = $this->replace_invalid_with_pct_encoding($query, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
  11118. }
  11119. $this->valid[__FUNCTION__] = true;
  11120. return true;
  11121. }
  11122. /**
  11123. * Set the fragment.
  11124. *
  11125. * @access public
  11126. * @param string $fragment
  11127. * @return bool
  11128. */
  11129. function set_fragment($fragment)
  11130. {
  11131. if ($fragment === null || $fragment === '')
  11132. {
  11133. $this->fragment = null;
  11134. }
  11135. else
  11136. {
  11137. $this->fragment = $this->replace_invalid_with_pct_encoding($fragment, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~!$&\'()*+,;=:@/?');
  11138. }
  11139. $this->valid[__FUNCTION__] = true;
  11140. return true;
  11141. }
  11142. /**
  11143. * Get the complete IRI
  11144. *
  11145. * @access public
  11146. * @return string
  11147. */
  11148. function get_iri()
  11149. {
  11150. $iri = '';
  11151. if ($this->scheme !== null)
  11152. {
  11153. $iri .= $this->scheme . ':';
  11154. }
  11155. if (($authority = $this->get_authority()) !== null)
  11156. {
  11157. $iri .= '//' . $authority;
  11158. }
  11159. if ($this->path !== null)
  11160. {
  11161. $iri .= $this->path;
  11162. }
  11163. if ($this->query !== null)
  11164. {
  11165. $iri .= '?' . $this->query;
  11166. }
  11167. if ($this->fragment !== null)
  11168. {
  11169. $iri .= '#' . $this->fragment;
  11170. }
  11171. if ($iri !== '')
  11172. {
  11173. return $iri;
  11174. }
  11175. else
  11176. {
  11177. return null;
  11178. }
  11179. }
  11180. /**
  11181. * Get the scheme
  11182. *
  11183. * @access public
  11184. * @return string
  11185. */
  11186. function get_scheme()
  11187. {
  11188. return $this->scheme;
  11189. }
  11190. /**
  11191. * Get the complete authority
  11192. *
  11193. * @access public
  11194. * @return string
  11195. */
  11196. function get_authority()
  11197. {
  11198. $authority = '';
  11199. if ($this->userinfo !== null)
  11200. {
  11201. $authority .= $this->userinfo . '@';
  11202. }
  11203. if ($this->host !== null)
  11204. {
  11205. $authority .= $this->host;
  11206. }
  11207. if ($this->port !== null)
  11208. {
  11209. $authority .= ':' . $this->port;
  11210. }
  11211. if ($authority !== '')
  11212. {
  11213. return $authority;
  11214. }
  11215. else
  11216. {
  11217. return null;
  11218. }
  11219. }
  11220. /**
  11221. * Get the user information
  11222. *
  11223. * @access public
  11224. * @return string
  11225. */
  11226. function get_userinfo()
  11227. {
  11228. return $this->userinfo;
  11229. }
  11230. /**
  11231. * Get the host
  11232. *
  11233. * @access public
  11234. * @return string
  11235. */
  11236. function get_host()
  11237. {
  11238. return $this->host;
  11239. }
  11240. /**
  11241. * Get the port
  11242. *
  11243. * @access public
  11244. * @return string
  11245. */
  11246. function get_port()
  11247. {
  11248. return $this->port;
  11249. }
  11250. /**
  11251. * Get the path
  11252. *
  11253. * @access public
  11254. * @return string
  11255. */
  11256. function get_path()
  11257. {
  11258. return $this->path;
  11259. }
  11260. /**
  11261. * Get the query
  11262. *
  11263. * @access public
  11264. * @return string
  11265. */
  11266. function get_query()
  11267. {
  11268. return $this->query;
  11269. }
  11270. /**
  11271. * Get the fragment
  11272. *
  11273. * @access public
  11274. * @return string
  11275. */
  11276. function get_fragment()
  11277. {
  11278. return $this->fragment;
  11279. }
  11280. }
  11281. /**
  11282. * Class to validate and to work with IPv6 addresses.
  11283. *
  11284. * @package SimplePie
  11285. * @copyright 2003-2005 The PHP Group
  11286. * @license http://www.opensource.org/licenses/bsd-license.php
  11287. * @link http://pear.php.net/package/Net_IPv6
  11288. * @author Alexander Merz <alexander.merz@web.de>
  11289. * @author elfrink at introweb dot nl
  11290. * @author Josh Peck <jmp at joshpeck dot org>
  11291. * @author Geoffrey Sneddon <geoffers@gmail.com>
  11292. */
  11293. class SimplePie_Net_IPv6
  11294. {
  11295. /**
  11296. * Removes a possible existing netmask specification of an IP address.
  11297. *
  11298. * @param string $ip the (compressed) IP as Hex representation
  11299. * @return string the IP the without netmask
  11300. * @since 1.1.0
  11301. * @access public
  11302. * @static
  11303. */
  11304. function removeNetmaskSpec($ip)
  11305. {
  11306. if (strpos($ip, '/') !== false)
  11307. {
  11308. list($addr, $nm) = explode('/', $ip);
  11309. }
  11310. else
  11311. {
  11312. $addr = $ip;
  11313. }
  11314. return $addr;
  11315. }
  11316. /**
  11317. * Uncompresses an IPv6 address
  11318. *
  11319. * RFC 2373 allows you to compress zeros in an address to '::'. This
  11320. * function expects an valid IPv6 address and expands the '::' to
  11321. * the required zeros.
  11322. *
  11323. * Example: FF01::101 -> FF01:0:0:0:0:0:0:101
  11324. * ::1 -> 0:0:0:0:0:0:0:1
  11325. *
  11326. * @access public
  11327. * @static
  11328. * @param string $ip a valid IPv6-address (hex format)
  11329. * @return string the uncompressed IPv6-address (hex format)
  11330. */
  11331. function Uncompress($ip)
  11332. {
  11333. $uip = SimplePie_Net_IPv6::removeNetmaskSpec($ip);
  11334. $c1 = -1;
  11335. $c2 = -1;
  11336. if (strpos($ip, '::') !== false)
  11337. {
  11338. list($ip1, $ip2) = explode('::', $ip);
  11339. if ($ip1 === '')
  11340. {
  11341. $c1 = -1;
  11342. }
  11343. else
  11344. {
  11345. $pos = 0;
  11346. if (($pos = substr_count($ip1, ':')) > 0)
  11347. {
  11348. $c1 = $pos;
  11349. }
  11350. else
  11351. {
  11352. $c1 = 0;
  11353. }
  11354. }
  11355. if ($ip2 === '')
  11356. {
  11357. $c2 = -1;
  11358. }
  11359. else
  11360. {
  11361. $pos = 0;
  11362. if (($pos = substr_count($ip2, ':')) > 0)
  11363. {
  11364. $c2 = $pos;
  11365. }
  11366. else
  11367. {
  11368. $c2 = 0;
  11369. }
  11370. }
  11371. if (strstr($ip2, '.'))
  11372. {
  11373. $c2++;
  11374. }
  11375. // ::
  11376. if ($c1 === -1 && $c2 === -1)
  11377. {
  11378. $uip = '0:0:0:0:0:0:0:0';
  11379. }
  11380. // ::xxx
  11381. else if ($c1 === -1)
  11382. {
  11383. $fill = str_repeat('0:', 7 - $c2);
  11384. $uip = str_replace('::', $fill, $uip);
  11385. }
  11386. // xxx::
  11387. else if ($c2 === -1)
  11388. {
  11389. $fill = str_repeat(':0', 7 - $c1);
  11390. $uip = str_replace('::', $fill, $uip);
  11391. }
  11392. // xxx::xxx
  11393. else
  11394. {
  11395. $fill = str_repeat(':0:', 6 - $c2 - $c1);
  11396. $uip = str_replace('::', $fill, $uip);
  11397. $uip = str_replace('::', ':', $uip);
  11398. }
  11399. }
  11400. return $uip;
  11401. }
  11402. /**
  11403. * Splits an IPv6 address into the IPv6 and a possible IPv4 part
  11404. *
  11405. * RFC 2373 allows you to note the last two parts of an IPv6 address as
  11406. * an IPv4 compatible address
  11407. *
  11408. * Example: 0:0:0:0:0:0:13.1.68.3
  11409. * 0:0:0:0:0:FFFF:129.144.52.38
  11410. *
  11411. * @access public
  11412. * @static
  11413. * @param string $ip a valid IPv6-address (hex format)
  11414. * @return array [0] contains the IPv6 part, [1] the IPv4 part (hex format)
  11415. */
  11416. function SplitV64($ip)
  11417. {
  11418. $ip = SimplePie_Net_IPv6::Uncompress($ip);
  11419. if (strstr($ip, '.'))
  11420. {
  11421. $pos = strrpos($ip, ':');
  11422. $ip[$pos] = '_';
  11423. $ipPart = explode('_', $ip);
  11424. return $ipPart;
  11425. }
  11426. else
  11427. {
  11428. return array($ip, '');
  11429. }
  11430. }
  11431. /**
  11432. * Checks an IPv6 address
  11433. *
  11434. * Checks if the given IP is IPv6-compatible
  11435. *
  11436. * @access public
  11437. * @static
  11438. * @param string $ip a valid IPv6-address
  11439. * @return bool true if $ip is an IPv6 address
  11440. */
  11441. function checkIPv6($ip)
  11442. {
  11443. $ipPart = SimplePie_Net_IPv6::SplitV64($ip);
  11444. $count = 0;
  11445. if (!empty($ipPart[0]))
  11446. {
  11447. $ipv6 = explode(':', $ipPart[0]);
  11448. for ($i = 0; $i < count($ipv6); $i++)
  11449. {
  11450. $dec = hexdec($ipv6[$i]);
  11451. $hex = strtoupper(preg_replace('/^[0]{1,3}(.*[0-9a-fA-F])$/', '\\1', $ipv6[$i]));
  11452. if ($ipv6[$i] >= 0 && $dec <= 65535 && $hex === strtoupper(dechex($dec)))
  11453. {
  11454. $count++;
  11455. }
  11456. }
  11457. if ($count === 8)
  11458. {
  11459. return true;
  11460. }
  11461. elseif ($count === 6 && !empty($ipPart[1]))
  11462. {
  11463. $ipv4 = explode('.', $ipPart[1]);
  11464. $count = 0;
  11465. foreach ($ipv4 as $ipv4_part)
  11466. {
  11467. if ($ipv4_part >= 0 && $ipv4_part <= 255 && preg_match('/^\d{1,3}$/', $ipv4_part))
  11468. {
  11469. $count++;
  11470. }
  11471. }
  11472. if ($count === 4)
  11473. {
  11474. return true;
  11475. }
  11476. }
  11477. else
  11478. {
  11479. return false;
  11480. }
  11481. }
  11482. else
  11483. {
  11484. return false;
  11485. }
  11486. }
  11487. }
  11488. /**
  11489. * Date Parser
  11490. *
  11491. * @package SimplePie
  11492. */
  11493. class SimplePie_Parse_Date
  11494. {
  11495. /**
  11496. * Input data
  11497. *
  11498. * @access protected
  11499. * @var string
  11500. */
  11501. var $date;
  11502. /**
  11503. * List of days, calendar day name => ordinal day number in the week
  11504. *
  11505. * @access protected
  11506. * @var array
  11507. */
  11508. var $day = array(
  11509. // English
  11510. 'mon' => 1,
  11511. 'monday' => 1,
  11512. 'tue' => 2,
  11513. 'tuesday' => 2,
  11514. 'wed' => 3,
  11515. 'wednesday' => 3,
  11516. 'thu' => 4,
  11517. 'thursday' => 4,
  11518. 'fri' => 5,
  11519. 'friday' => 5,
  11520. 'sat' => 6,
  11521. 'saturday' => 6,
  11522. 'sun' => 7,
  11523. 'sunday' => 7,
  11524. // Dutch
  11525. 'maandag' => 1,
  11526. 'dinsdag' => 2,
  11527. 'woensdag' => 3,
  11528. 'donderdag' => 4,
  11529. 'vrijdag' => 5,
  11530. 'zaterdag' => 6,
  11531. 'zondag' => 7,
  11532. // French
  11533. 'lundi' => 1,
  11534. 'mardi' => 2,
  11535. 'mercredi' => 3,
  11536. 'jeudi' => 4,
  11537. 'vendredi' => 5,
  11538. 'samedi' => 6,
  11539. 'dimanche' => 7,
  11540. // German
  11541. 'montag' => 1,
  11542. 'dienstag' => 2,
  11543. 'mittwoch' => 3,
  11544. 'donnerstag' => 4,
  11545. 'freitag' => 5,
  11546. 'samstag' => 6,
  11547. 'sonnabend' => 6,
  11548. 'sonntag' => 7,
  11549. // Italian
  11550. 'lunedì' => 1,
  11551. 'martedì' => 2,
  11552. 'mercoledì' => 3,
  11553. 'giovedì' => 4,
  11554. 'venerdì' => 5,
  11555. 'sabato' => 6,
  11556. 'domenica' => 7,
  11557. // Spanish
  11558. 'lunes' => 1,
  11559. 'martes' => 2,
  11560. 'miércoles' => 3,
  11561. 'jueves' => 4,
  11562. 'viernes' => 5,
  11563. 'sábado' => 6,
  11564. 'domingo' => 7,
  11565. // Finnish
  11566. 'maanantai' => 1,
  11567. 'tiistai' => 2,
  11568. 'keskiviikko' => 3,
  11569. 'torstai' => 4,
  11570. 'perjantai' => 5,
  11571. 'lauantai' => 6,
  11572. 'sunnuntai' => 7,
  11573. // Hungarian
  11574. 'hétfő' => 1,
  11575. 'kedd' => 2,
  11576. 'szerda' => 3,
  11577. 'csütörtok' => 4,
  11578. 'péntek' => 5,
  11579. 'szombat' => 6,
  11580. 'vasárnap' => 7,
  11581. // Greek
  11582. 'Δευ' => 1,
  11583. 'Τρι' => 2,
  11584. 'Τετ' => 3,
  11585. 'Πεμ' => 4,
  11586. 'Παρ' => 5,
  11587. 'Σαβ' => 6,
  11588. 'Κυρ' => 7,
  11589. );
  11590. /**
  11591. * List of months, calendar month name => calendar month number
  11592. *
  11593. * @access protected
  11594. * @var array
  11595. */
  11596. var $month = array(
  11597. // English
  11598. 'jan' => 1,
  11599. 'january' => 1,
  11600. 'feb' => 2,
  11601. 'february' => 2,
  11602. 'mar' => 3,
  11603. 'march' => 3,
  11604. 'apr' => 4,
  11605. 'april' => 4,
  11606. 'may' => 5,
  11607. // No long form of May
  11608. 'jun' => 6,
  11609. 'june' => 6,
  11610. 'jul' => 7,
  11611. 'july' => 7,
  11612. 'aug' => 8,
  11613. 'august' => 8,
  11614. 'sep' => 9,
  11615. 'september' => 8,
  11616. 'oct' => 10,
  11617. 'october' => 10,
  11618. 'nov' => 11,
  11619. 'november' => 11,
  11620. 'dec' => 12,
  11621. 'december' => 12,
  11622. // Dutch
  11623. 'januari' => 1,
  11624. 'februari' => 2,
  11625. 'maart' => 3,
  11626. 'april' => 4,
  11627. 'mei' => 5,
  11628. 'juni' => 6,
  11629. 'juli' => 7,
  11630. 'augustus' => 8,
  11631. 'september' => 9,
  11632. 'oktober' => 10,
  11633. 'november' => 11,
  11634. 'december' => 12,
  11635. // French
  11636. 'janvier' => 1,
  11637. 'février' => 2,
  11638. 'mars' => 3,
  11639. 'avril' => 4,
  11640. 'mai' => 5,
  11641. 'juin' => 6,
  11642. 'juillet' => 7,
  11643. 'août' => 8,
  11644. 'septembre' => 9,
  11645. 'octobre' => 10,
  11646. 'novembre' => 11,
  11647. 'décembre' => 12,
  11648. // German
  11649. 'januar' => 1,
  11650. 'februar' => 2,
  11651. 'märz' => 3,
  11652. 'april' => 4,
  11653. 'mai' => 5,
  11654. 'juni' => 6,
  11655. 'juli' => 7,
  11656. 'august' => 8,
  11657. 'september' => 9,
  11658. 'oktober' => 10,
  11659. 'november' => 11,
  11660. 'dezember' => 12,
  11661. // Italian
  11662. 'gennaio' => 1,
  11663. 'febbraio' => 2,
  11664. 'marzo' => 3,
  11665. 'aprile' => 4,
  11666. 'maggio' => 5,
  11667. 'giugno' => 6,
  11668. 'luglio' => 7,
  11669. 'agosto' => 8,
  11670. 'settembre' => 9,
  11671. 'ottobre' => 10,
  11672. 'novembre' => 11,
  11673. 'dicembre' => 12,
  11674. // Spanish
  11675. 'enero' => 1,
  11676. 'febrero' => 2,
  11677. 'marzo' => 3,
  11678. 'abril' => 4,
  11679. 'mayo' => 5,
  11680. 'junio' => 6,
  11681. 'julio' => 7,
  11682. 'agosto' => 8,
  11683. 'septiembre' => 9,
  11684. 'setiembre' => 9,
  11685. 'octubre' => 10,
  11686. 'noviembre' => 11,
  11687. 'diciembre' => 12,
  11688. // Finnish
  11689. 'tammikuu' => 1,
  11690. 'helmikuu' => 2,
  11691. 'maaliskuu' => 3,
  11692. 'huhtikuu' => 4,
  11693. 'toukokuu' => 5,
  11694. 'kesäkuu' => 6,
  11695. 'heinäkuu' => 7,
  11696. 'elokuu' => 8,
  11697. 'suuskuu' => 9,
  11698. 'lokakuu' => 10,
  11699. 'marras' => 11,
  11700. 'joulukuu' => 12,
  11701. // Hungarian
  11702. 'január' => 1,
  11703. 'február' => 2,
  11704. 'március' => 3,
  11705. 'április' => 4,
  11706. 'május' => 5,
  11707. 'június' => 6,
  11708. 'július' => 7,
  11709. 'augusztus' => 8,
  11710. 'szeptember' => 9,
  11711. 'október' => 10,
  11712. 'november' => 11,
  11713. 'december' => 12,
  11714. // Greek
  11715. 'Ιαν' => 1,
  11716. 'Φεβ' => 2,
  11717. 'Μάώ' => 3,
  11718. 'Μαώ' => 3,
  11719. 'Απρ' => 4,
  11720. 'Μάι' => 5,
  11721. 'Μαϊ' => 5,
  11722. 'Μαι' => 5,
  11723. 'Ιούν' => 6,
  11724. 'Ιον' => 6,
  11725. 'Ιούλ' => 7,
  11726. 'Ιολ' => 7,
  11727. 'Αύγ' => 8,
  11728. 'Αυγ' => 8,
  11729. 'Σεπ' => 9,
  11730. 'Οκτ' => 10,
  11731. 'Νοέ' => 11,
  11732. 'Δεκ' => 12,
  11733. );
  11734. /**
  11735. * List of timezones, abbreviation => offset from UTC
  11736. *
  11737. * @access protected
  11738. * @var array
  11739. */
  11740. var $timezone = array(
  11741. 'ACDT' => 37800,
  11742. 'ACIT' => 28800,
  11743. 'ACST' => 34200,
  11744. 'ACT' => -18000,
  11745. 'ACWDT' => 35100,
  11746. 'ACWST' => 31500,
  11747. 'AEDT' => 39600,
  11748. 'AEST' => 36000,
  11749. 'AFT' => 16200,
  11750. 'AKDT' => -28800,
  11751. 'AKST' => -32400,
  11752. 'AMDT' => 18000,
  11753. 'AMT' => -14400,
  11754. 'ANAST' => 46800,
  11755. 'ANAT' => 43200,
  11756. 'ART' => -10800,
  11757. 'AZOST' => -3600,
  11758. 'AZST' => 18000,
  11759. 'AZT' => 14400,
  11760. 'BIOT' => 21600,
  11761. 'BIT' => -43200,
  11762. 'BOT' => -14400,
  11763. 'BRST' => -7200,
  11764. 'BRT' => -10800,
  11765. 'BST' => 3600,
  11766. 'BTT' => 21600,
  11767. 'CAST' => 18000,
  11768. 'CAT' => 7200,
  11769. 'CCT' => 23400,
  11770. 'CDT' => -18000,
  11771. 'CEDT' => 7200,
  11772. 'CET' => 3600,
  11773. 'CGST' => -7200,
  11774. 'CGT' => -10800,
  11775. 'CHADT' => 49500,
  11776. 'CHAST' => 45900,
  11777. 'CIST' => -28800,
  11778. 'CKT' => -36000,
  11779. 'CLDT' => -10800,
  11780. 'CLST' => -14400,
  11781. 'COT' => -18000,
  11782. 'CST' => -21600,
  11783. 'CVT' => -3600,
  11784. 'CXT' => 25200,
  11785. 'DAVT' => 25200,
  11786. 'DTAT' => 36000,
  11787. 'EADT' => -18000,
  11788. 'EAST' => -21600,
  11789. 'EAT' => 10800,
  11790. 'ECT' => -18000,
  11791. 'EDT' => -14400,
  11792. 'EEST' => 10800,
  11793. 'EET' => 7200,
  11794. 'EGT' => -3600,
  11795. 'EKST' => 21600,
  11796. 'EST' => -18000,
  11797. 'FJT' => 43200,
  11798. 'FKDT' => -10800,
  11799. 'FKST' => -14400,
  11800. 'FNT' => -7200,
  11801. 'GALT' => -21600,
  11802. 'GEDT' => 14400,
  11803. 'GEST' => 10800,
  11804. 'GFT' => -10800,
  11805. 'GILT' => 43200,
  11806. 'GIT' => -32400,
  11807. 'GST' => 14400,
  11808. 'GST' => -7200,
  11809. 'GYT' => -14400,
  11810. 'HAA' => -10800,
  11811. 'HAC' => -18000,
  11812. 'HADT' => -32400,
  11813. 'HAE' => -14400,
  11814. 'HAP' => -25200,
  11815. 'HAR' => -21600,
  11816. 'HAST' => -36000,
  11817. 'HAT' => -9000,
  11818. 'HAY' => -28800,
  11819. 'HKST' => 28800,
  11820. 'HMT' => 18000,
  11821. 'HNA' => -14400,
  11822. 'HNC' => -21600,
  11823. 'HNE' => -18000,
  11824. 'HNP' => -28800,
  11825. 'HNR' => -25200,
  11826. 'HNT' => -12600,
  11827. 'HNY' => -32400,
  11828. 'IRDT' => 16200,
  11829. 'IRKST' => 32400,
  11830. 'IRKT' => 28800,
  11831. 'IRST' => 12600,
  11832. 'JFDT' => -10800,
  11833. 'JFST' => -14400,
  11834. 'JST' => 32400,
  11835. 'KGST' => 21600,
  11836. 'KGT' => 18000,
  11837. 'KOST' => 39600,
  11838. 'KOVST' => 28800,
  11839. 'KOVT' => 25200,
  11840. 'KRAST' => 28800,
  11841. 'KRAT' => 25200,
  11842. 'KST' => 32400,
  11843. 'LHDT' => 39600,
  11844. 'LHST' => 37800,
  11845. 'LINT' => 50400,
  11846. 'LKT' => 21600,
  11847. 'MAGST' => 43200,
  11848. 'MAGT' => 39600,
  11849. 'MAWT' => 21600,
  11850. 'MDT' => -21600,
  11851. 'MESZ' => 7200,
  11852. 'MEZ' => 3600,
  11853. 'MHT' => 43200,
  11854. 'MIT' => -34200,
  11855. 'MNST' => 32400,
  11856. 'MSDT' => 14400,
  11857. 'MSST' => 10800,
  11858. 'MST' => -25200,
  11859. 'MUT' => 14400,
  11860. 'MVT' => 18000,
  11861. 'MYT' => 28800,
  11862. 'NCT' => 39600,
  11863. 'NDT' => -9000,
  11864. 'NFT' => 41400,
  11865. 'NMIT' => 36000,
  11866. 'NOVST' => 25200,
  11867. 'NOVT' => 21600,
  11868. 'NPT' => 20700,
  11869. 'NRT' => 43200,
  11870. 'NST' => -12600,
  11871. 'NUT' => -39600,
  11872. 'NZDT' => 46800,
  11873. 'NZST' => 43200,
  11874. 'OMSST' => 25200,
  11875. 'OMST' => 21600,
  11876. 'PDT' => -25200,
  11877. 'PET' => -18000,
  11878. 'PETST' => 46800,
  11879. 'PETT' => 43200,
  11880. 'PGT' => 36000,
  11881. 'PHOT' => 46800,
  11882. 'PHT' => 28800,
  11883. 'PKT' => 18000,
  11884. 'PMDT' => -7200,
  11885. 'PMST' => -10800,
  11886. 'PONT' => 39600,
  11887. 'PST' => -28800,
  11888. 'PWT' => 32400,
  11889. 'PYST' => -10800,
  11890. 'PYT' => -14400,
  11891. 'RET' => 14400,
  11892. 'ROTT' => -10800,
  11893. 'SAMST' => 18000,
  11894. 'SAMT' => 14400,
  11895. 'SAST' => 7200,
  11896. 'SBT' => 39600,
  11897. 'SCDT' => 46800,
  11898. 'SCST' => 43200,
  11899. 'SCT' => 14400,
  11900. 'SEST' => 3600,
  11901. 'SGT' => 28800,
  11902. 'SIT' => 28800,
  11903. 'SRT' => -10800,
  11904. 'SST' => -39600,
  11905. 'SYST' => 10800,
  11906. 'SYT' => 7200,
  11907. 'TFT' => 18000,
  11908. 'THAT' => -36000,
  11909. 'TJT' => 18000,
  11910. 'TKT' => -36000,
  11911. 'TMT' => 18000,
  11912. 'TOT' => 46800,
  11913. 'TPT' => 32400,
  11914. 'TRUT' => 36000,
  11915. 'TVT' => 43200,
  11916. 'TWT' => 28800,
  11917. 'UYST' => -7200,
  11918. 'UYT' => -10800,
  11919. 'UZT' => 18000,
  11920. 'VET' => -14400,
  11921. 'VLAST' => 39600,
  11922. 'VLAT' => 36000,
  11923. 'VOST' => 21600,
  11924. 'VUT' => 39600,
  11925. 'WAST' => 7200,
  11926. 'WAT' => 3600,
  11927. 'WDT' => 32400,
  11928. 'WEST' => 3600,
  11929. 'WFT' => 43200,
  11930. 'WIB' => 25200,
  11931. 'WIT' => 32400,
  11932. 'WITA' => 28800,
  11933. 'WKST' => 18000,
  11934. 'WST' => 28800,
  11935. 'YAKST' => 36000,
  11936. 'YAKT' => 32400,
  11937. 'YAPT' => 36000,
  11938. 'YEKST' => 21600,
  11939. 'YEKT' => 18000,
  11940. );
  11941. /**
  11942. * Cached PCRE for SimplePie_Parse_Date::$day
  11943. *
  11944. * @access protected
  11945. * @var string
  11946. */
  11947. var $day_pcre;
  11948. /**
  11949. * Cached PCRE for SimplePie_Parse_Date::$month
  11950. *
  11951. * @access protected
  11952. * @var string
  11953. */
  11954. var $month_pcre;
  11955. /**
  11956. * Array of user-added callback methods
  11957. *
  11958. * @access private
  11959. * @var array
  11960. */
  11961. var $built_in = array();
  11962. /**
  11963. * Array of user-added callback methods
  11964. *
  11965. * @access private
  11966. * @var array
  11967. */
  11968. var $user = array();
  11969. /**
  11970. * Create new SimplePie_Parse_Date object, and set self::day_pcre,
  11971. * self::month_pcre, and self::built_in
  11972. *
  11973. * @access private
  11974. */
  11975. function SimplePie_Parse_Date()
  11976. {
  11977. $this->day_pcre = '(' . implode(array_keys($this->day), '|') . ')';
  11978. $this->month_pcre = '(' . implode(array_keys($this->month), '|') . ')';
  11979. static $cache;
  11980. if (!isset($cache[get_class($this)]))
  11981. {
  11982. $all_methods = get_class_methods($this);
  11983. foreach ($all_methods as $method)
  11984. {
  11985. if (strtolower(substr($method, 0, 5)) === 'date_')
  11986. {
  11987. $cache[get_class($this)][] = $method;
  11988. }
  11989. }
  11990. }
  11991. foreach ($cache[get_class($this)] as $method)
  11992. {
  11993. $this->built_in[] = $method;
  11994. }
  11995. }
  11996. /**
  11997. * Get the object
  11998. *
  11999. * @access public
  12000. */
  12001. function get()
  12002. {
  12003. static $object;
  12004. if (!$object)
  12005. {
  12006. $object = new SimplePie_Parse_Date;
  12007. }
  12008. return $object;
  12009. }
  12010. /**
  12011. * Parse a date
  12012. *
  12013. * @final
  12014. * @access public
  12015. * @param string $date Date to parse
  12016. * @return int Timestamp corresponding to date string, or false on failure
  12017. */
  12018. function parse($date)
  12019. {
  12020. foreach ($this->user as $method)
  12021. {
  12022. if (($returned = call_user_func($method, $date)) !== false)
  12023. {
  12024. return $returned;
  12025. }
  12026. }
  12027. foreach ($this->built_in as $method)
  12028. {
  12029. if (($returned = call_user_func(array(&$this, $method), $date)) !== false)
  12030. {
  12031. return $returned;
  12032. }
  12033. }
  12034. return false;
  12035. }
  12036. /**
  12037. * Add a callback method to parse a date
  12038. *
  12039. * @final
  12040. * @access public
  12041. * @param callback $callback
  12042. */
  12043. function add_callback($callback)
  12044. {
  12045. if (is_callable($callback))
  12046. {
  12047. $this->user[] = $callback;
  12048. }
  12049. else
  12050. {
  12051. trigger_error('User-supplied function must be a valid callback', E_USER_WARNING);
  12052. }
  12053. }
  12054. /**
  12055. * Parse a superset of W3C-DTF (allows hyphens and colons to be omitted, as
  12056. * well as allowing any of upper or lower case "T", horizontal tabs, or
  12057. * spaces to be used as the time seperator (including more than one))
  12058. *
  12059. * @access protected
  12060. * @return int Timestamp
  12061. */
  12062. function date_w3cdtf($date)
  12063. {
  12064. static $pcre;
  12065. if (!$pcre)
  12066. {
  12067. $year = '([0-9]{4})';
  12068. $month = $day = $hour = $minute = $second = '([0-9]{2})';
  12069. $decimal = '([0-9]*)';
  12070. $zone = '(?:(Z)|([+\-])([0-9]{1,2}):?([0-9]{1,2}))';
  12071. $pcre = '/^' . $year . '(?:-?' . $month . '(?:-?' . $day . '(?:[Tt\x09\x20]+' . $hour . '(?::?' . $minute . '(?::?' . $second . '(?:.' . $decimal . ')?)?)?' . $zone . ')?)?)?$/';
  12072. }
  12073. if (preg_match($pcre, $date, $match))
  12074. {
  12075. /*
  12076. Capturing subpatterns:
  12077. 1: Year
  12078. 2: Month
  12079. 3: Day
  12080. 4: Hour
  12081. 5: Minute
  12082. 6: Second
  12083. 7: Decimal fraction of a second
  12084. 8: Zulu
  12085. 9: Timezone ±
  12086. 10: Timezone hours
  12087. 11: Timezone minutes
  12088. */
  12089. // Fill in empty matches
  12090. for ($i = count($match); $i <= 3; $i++)
  12091. {
  12092. $match[$i] = '1';
  12093. }
  12094. for ($i = count($match); $i <= 7; $i++)
  12095. {
  12096. $match[$i] = '0';
  12097. }
  12098. // Numeric timezone
  12099. if (isset($match[9]) && $match[9] !== '')
  12100. {
  12101. $timezone = $match[10] * 3600;
  12102. $timezone += $match[11] * 60;
  12103. if ($match[9] === '-')
  12104. {
  12105. $timezone = 0 - $timezone;
  12106. }
  12107. }
  12108. else
  12109. {
  12110. $timezone = 0;
  12111. }
  12112. // Convert the number of seconds to an integer, taking decimals into account
  12113. $second = round($match[6] + $match[7] / pow(10, strlen($match[7])));
  12114. return gmmktime($match[4], $match[5], $second, $match[2], $match[3], $match[1]) - $timezone;
  12115. }
  12116. else
  12117. {
  12118. return false;
  12119. }
  12120. }
  12121. /**
  12122. * Remove RFC822 comments
  12123. *
  12124. * @access protected
  12125. * @param string $data Data to strip comments from
  12126. * @return string Comment stripped string
  12127. */
  12128. function remove_rfc2822_comments($string)
  12129. {
  12130. $string = (string) $string;
  12131. $position = 0;
  12132. $length = strlen($string);
  12133. $depth = 0;
  12134. $output = '';
  12135. while ($position < $length && ($pos = strpos($string, '(', $position)) !== false)
  12136. {
  12137. $output .= substr($string, $position, $pos - $position);
  12138. $position = $pos + 1;
  12139. if ($string[$pos - 1] !== '\\')
  12140. {
  12141. $depth++;
  12142. while ($depth && $position < $length)
  12143. {
  12144. $position += strcspn($string, '()', $position);
  12145. if ($string[$position - 1] === '\\')
  12146. {
  12147. $position++;
  12148. continue;
  12149. }
  12150. elseif (isset($string[$position]))
  12151. {
  12152. switch ($string[$position])
  12153. {
  12154. case '(':
  12155. $depth++;
  12156. break;
  12157. case ')':
  12158. $depth--;
  12159. break;
  12160. }
  12161. $position++;
  12162. }
  12163. else
  12164. {
  12165. break;
  12166. }
  12167. }
  12168. }
  12169. else
  12170. {
  12171. $output .= '(';
  12172. }
  12173. }
  12174. $output .= substr($string, $position);
  12175. return $output;
  12176. }
  12177. /**
  12178. * Parse RFC2822's date format
  12179. *
  12180. * @access protected
  12181. * @return int Timestamp
  12182. */
  12183. function date_rfc2822($date)
  12184. {
  12185. static $pcre;
  12186. if (!$pcre)
  12187. {
  12188. $wsp = '[\x09\x20]';
  12189. $fws = '(?:' . $wsp . '+|' . $wsp . '*(?:\x0D\x0A' . $wsp . '+)+)';
  12190. $optional_fws = $fws . '?';
  12191. $day_name = $this->day_pcre;
  12192. $month = $this->month_pcre;
  12193. $day = '([0-9]{1,2})';
  12194. $hour = $minute = $second = '([0-9]{2})';
  12195. $year = '([0-9]{2,4})';
  12196. $num_zone = '([+\-])([0-9]{2})([0-9]{2})';
  12197. $character_zone = '([A-Z]{1,5})';
  12198. $zone = '(?:' . $num_zone . '|' . $character_zone . ')';
  12199. $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';
  12200. }
  12201. if (preg_match($pcre, $this->remove_rfc2822_comments($date), $match))
  12202. {
  12203. /*
  12204. Capturing subpatterns:
  12205. 1: Day name
  12206. 2: Day
  12207. 3: Month
  12208. 4: Year
  12209. 5: Hour
  12210. 6: Minute
  12211. 7: Second
  12212. 8: Timezone ±
  12213. 9: Timezone hours
  12214. 10: Timezone minutes
  12215. 11: Alphabetic timezone
  12216. */
  12217. // Find the month number
  12218. $month = $this->month[strtolower($match[3])];
  12219. // Numeric timezone
  12220. if ($match[8] !== '')
  12221. {
  12222. $timezone = $match[9] * 3600;
  12223. $timezone += $match[10] * 60;
  12224. if ($match[8] === '-')
  12225. {
  12226. $timezone = 0 - $timezone;
  12227. }
  12228. }
  12229. // Character timezone
  12230. elseif (isset($this->timezone[strtoupper($match[11])]))
  12231. {
  12232. $timezone = $this->timezone[strtoupper($match[11])];
  12233. }
  12234. // Assume everything else to be -0000
  12235. else
  12236. {
  12237. $timezone = 0;
  12238. }
  12239. // Deal with 2/3 digit years
  12240. if ($match[4] < 50)
  12241. {
  12242. $match[4] += 2000;
  12243. }
  12244. elseif ($match[4] < 1000)
  12245. {
  12246. $match[4] += 1900;
  12247. }
  12248. // Second is optional, if it is empty set it to zero
  12249. if ($match[7] !== '')
  12250. {
  12251. $second = $match[7];
  12252. }
  12253. else
  12254. {
  12255. $second = 0;
  12256. }
  12257. return gmmktime($match[5], $match[6], $second, $month, $match[2], $match[4]) - $timezone;
  12258. }
  12259. else
  12260. {
  12261. return false;
  12262. }
  12263. }
  12264. /**
  12265. * Parse RFC850's date format
  12266. *
  12267. * @access protected
  12268. * @return int Timestamp
  12269. */
  12270. function date_rfc850($date)
  12271. {
  12272. static $pcre;
  12273. if (!$pcre)
  12274. {
  12275. $space = '[\x09\x20]+';
  12276. $day_name = $this->day_pcre;
  12277. $month = $this->month_pcre;
  12278. $day = '([0-9]{1,2})';
  12279. $year = $hour = $minute = $second = '([0-9]{2})';
  12280. $zone = '([A-Z]{1,5})';
  12281. $pcre = '/^' . $day_name . ',' . $space . $day . '-' . $month . '-' . $year . $space . $hour . ':' . $minute . ':' . $second . $space . $zone . '$/i';
  12282. }
  12283. if (preg_match($pcre, $date, $match))
  12284. {
  12285. /*
  12286. Capturing subpatterns:
  12287. 1: Day name
  12288. 2: Day
  12289. 3: Month
  12290. 4: Year
  12291. 5: Hour
  12292. 6: Minute
  12293. 7: Second
  12294. 8: Timezone
  12295. */
  12296. // Month
  12297. $month = $this->month[strtolower($match[3])];
  12298. // Character timezone
  12299. if (isset($this->timezone[strtoupper($match[8])]))
  12300. {
  12301. $timezone = $this->timezone[strtoupper($match[8])];
  12302. }
  12303. // Assume everything else to be -0000
  12304. else
  12305. {
  12306. $timezone = 0;
  12307. }
  12308. // Deal with 2 digit year
  12309. if ($match[4] < 50)
  12310. {
  12311. $match[4] += 2000;
  12312. }
  12313. else
  12314. {
  12315. $match[4] += 1900;
  12316. }
  12317. return gmmktime($match[5], $match[6], $match[7], $month, $match[2], $match[4]) - $timezone;
  12318. }
  12319. else
  12320. {
  12321. return false;
  12322. }
  12323. }
  12324. /**
  12325. * Parse C99's asctime()'s date format
  12326. *
  12327. * @access protected
  12328. * @return int Timestamp
  12329. */
  12330. function date_asctime($date)
  12331. {
  12332. static $pcre;
  12333. if (!$pcre)
  12334. {
  12335. $space = '[\x09\x20]+';
  12336. $wday_name = $this->day_pcre;
  12337. $mon_name = $this->month_pcre;
  12338. $day = '([0-9]{1,2})';
  12339. $hour = $sec = $min = '([0-9]{2})';
  12340. $year = '([0-9]{4})';
  12341. $terminator = '\x0A?\x00?';
  12342. $pcre = '/^' . $wday_name . $space . $mon_name . $space . $day . $space . $hour . ':' . $min . ':' . $sec . $space . $year . $terminator . '$/i';
  12343. }
  12344. if (preg_match($pcre, $date, $match))
  12345. {
  12346. /*
  12347. Capturing subpatterns:
  12348. 1: Day name
  12349. 2: Month
  12350. 3: Day
  12351. 4: Hour
  12352. 5: Minute
  12353. 6: Second
  12354. 7: Year
  12355. */
  12356. $month = $this->month[strtolower($match[2])];
  12357. return gmmktime($match[4], $match[5], $match[6], $month, $match[3], $match[7]);
  12358. }
  12359. else
  12360. {
  12361. return false;
  12362. }
  12363. }
  12364. /**
  12365. * Parse dates using strtotime()
  12366. *
  12367. * @access protected
  12368. * @return int Timestamp
  12369. */
  12370. function date_strtotime($date)
  12371. {
  12372. $strtotime = strtotime($date);
  12373. if ($strtotime === -1 || $strtotime === false)
  12374. {
  12375. return false;
  12376. }
  12377. else
  12378. {
  12379. return $strtotime;
  12380. }
  12381. }
  12382. }
  12383. /**
  12384. * Content-type sniffing
  12385. *
  12386. * @package SimplePie
  12387. */
  12388. class SimplePie_Content_Type_Sniffer
  12389. {
  12390. /**
  12391. * File object
  12392. *
  12393. * @var SimplePie_File
  12394. * @access private
  12395. */
  12396. var $file;
  12397. /**
  12398. * Create an instance of the class with the input file
  12399. *
  12400. * @access public
  12401. * @param SimplePie_Content_Type_Sniffer $file Input file
  12402. */
  12403. function SimplePie_Content_Type_Sniffer($file)
  12404. {
  12405. $this->file = $file;
  12406. }
  12407. /**
  12408. * Get the Content-Type of the specified file
  12409. *
  12410. * @access public
  12411. * @return string Actual Content-Type
  12412. */
  12413. function get_type()
  12414. {
  12415. if (isset($this->file->headers['content-type']))
  12416. {
  12417. if (!isset($this->file->headers['content-encoding'])
  12418. && ($this->file->headers['content-type'] === 'text/plain'
  12419. || $this->file->headers['content-type'] === 'text/plain; charset=ISO-8859-1'
  12420. || $this->file->headers['content-type'] === 'text/plain; charset=iso-8859-1'))
  12421. {
  12422. return $this->text_or_binary();
  12423. }
  12424. if (($pos = strpos($this->file->headers['content-type'], ';')) !== false)
  12425. {
  12426. $official = substr($this->file->headers['content-type'], 0, $pos);
  12427. }
  12428. else
  12429. {
  12430. $official = $this->file->headers['content-type'];
  12431. }
  12432. $official = strtolower($official);
  12433. if ($official === 'unknown/unknown'
  12434. || $official === 'application/unknown')
  12435. {
  12436. return $this->unknown();
  12437. }
  12438. elseif (substr($official, -4) === '+xml'
  12439. || $official === 'text/xml'
  12440. || $official === 'application/xml')
  12441. {
  12442. return $official;
  12443. }
  12444. elseif (substr($official, 0, 6) === 'image/')
  12445. {
  12446. if ($return = $this->image())
  12447. {
  12448. return $return;
  12449. }
  12450. else
  12451. {
  12452. return $official;
  12453. }
  12454. }
  12455. elseif ($official === 'text/html')
  12456. {
  12457. return $this->feed_or_html();
  12458. }
  12459. else
  12460. {
  12461. return $official;
  12462. }
  12463. }
  12464. else
  12465. {
  12466. return $this->unknown();
  12467. }
  12468. }
  12469. /**
  12470. * Sniff text or binary
  12471. *
  12472. * @access private
  12473. * @return string Actual Content-Type
  12474. */
  12475. function text_or_binary()
  12476. {
  12477. if (substr($this->file->body, 0, 2) === "\xFE\xFF"
  12478. || substr($this->file->body, 0, 2) === "\xFF\xFE"
  12479. || substr($this->file->body, 0, 4) === "\x00\x00\xFE\xFF"
  12480. || substr($this->file->body, 0, 3) === "\xEF\xBB\xBF")
  12481. {
  12482. return 'text/plain';
  12483. }
  12484. elseif (preg_match('/[\x00-\x08\x0E-\x1A\x1C-\x1F]/', $this->file->body))
  12485. {
  12486. return 'application/octect-stream';
  12487. }
  12488. else
  12489. {
  12490. return 'text/plain';
  12491. }
  12492. }
  12493. /**
  12494. * Sniff unknown
  12495. *
  12496. * @access private
  12497. * @return string Actual Content-Type
  12498. */
  12499. function unknown()
  12500. {
  12501. $ws = strspn($this->file->body, "\x09\x0A\x0B\x0C\x0D\x20");
  12502. if (strtolower(substr($this->file->body, $ws, 14)) === '<!doctype html'
  12503. || strtolower(substr($this->file->body, $ws, 5)) === '<html'
  12504. || strtolower(substr($this->file->body, $ws, 7)) === '<script')
  12505. {
  12506. return 'text/html';
  12507. }
  12508. elseif (substr($this->file->body, 0, 5) === '%PDF-')
  12509. {
  12510. return 'application/pdf';
  12511. }
  12512. elseif (substr($this->file->body, 0, 11) === '%!PS-Adobe-')
  12513. {
  12514. return 'application/postscript';
  12515. }
  12516. elseif (substr($this->file->body, 0, 6) === 'GIF87a'
  12517. || substr($this->file->body, 0, 6) === 'GIF89a')
  12518. {
  12519. return 'image/gif';
  12520. }
  12521. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  12522. {
  12523. return 'image/png';
  12524. }
  12525. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  12526. {
  12527. return 'image/jpeg';
  12528. }
  12529. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  12530. {
  12531. return 'image/bmp';
  12532. }
  12533. else
  12534. {
  12535. return $this->text_or_binary();
  12536. }
  12537. }
  12538. /**
  12539. * Sniff images
  12540. *
  12541. * @access private
  12542. * @return string Actual Content-Type
  12543. */
  12544. function image()
  12545. {
  12546. if (substr($this->file->body, 0, 6) === 'GIF87a'
  12547. || substr($this->file->body, 0, 6) === 'GIF89a')
  12548. {
  12549. return 'image/gif';
  12550. }
  12551. elseif (substr($this->file->body, 0, 8) === "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A")
  12552. {
  12553. return 'image/png';
  12554. }
  12555. elseif (substr($this->file->body, 0, 3) === "\xFF\xD8\xFF")
  12556. {
  12557. return 'image/jpeg';
  12558. }
  12559. elseif (substr($this->file->body, 0, 2) === "\x42\x4D")
  12560. {
  12561. return 'image/bmp';
  12562. }
  12563. else
  12564. {
  12565. return false;
  12566. }
  12567. }
  12568. /**
  12569. * Sniff HTML
  12570. *
  12571. * @access private
  12572. * @return string Actual Content-Type
  12573. */
  12574. function feed_or_html()
  12575. {
  12576. $len = strlen($this->file->body);
  12577. $pos = strspn($this->file->body, "\x09\x0A\x0D\x20");
  12578. while ($pos < $len)
  12579. {
  12580. switch ($this->file->body[$pos])
  12581. {
  12582. case "\x09":
  12583. case "\x0A":
  12584. case "\x0D":
  12585. case "\x20":
  12586. $pos += strspn($this->file->body, "\x09\x0A\x0D\x20", $pos);
  12587. continue 2;
  12588. case '<':
  12589. $pos++;
  12590. break;
  12591. default:
  12592. return 'text/html';
  12593. }
  12594. if (substr($this->file->body, $pos, 3) === '!--')
  12595. {
  12596. $pos += 3;
  12597. if ($pos < $len && ($pos = strpos($this->file->body, '-->', $pos)) !== false)
  12598. {
  12599. $pos += 3;
  12600. }
  12601. else
  12602. {
  12603. return 'text/html';
  12604. }
  12605. }
  12606. elseif (substr($this->file->body, $pos, 1) === '!')
  12607. {
  12608. if ($pos < $len && ($pos = strpos($this->file->body, '>', $pos)) !== false)
  12609. {
  12610. $pos++;
  12611. }
  12612. else
  12613. {
  12614. return 'text/html';
  12615. }
  12616. }
  12617. elseif (substr($this->file->body, $pos, 1) === '?')
  12618. {
  12619. if ($pos < $len && ($pos = strpos($this->file->body, '?>', $pos)) !== false)
  12620. {
  12621. $pos += 2;
  12622. }
  12623. else
  12624. {
  12625. return 'text/html';
  12626. }
  12627. }
  12628. elseif (substr($this->file->body, $pos, 3) === 'rss'
  12629. || substr($this->file->body, $pos, 7) === 'rdf:RDF')
  12630. {
  12631. return 'application/rss+xml';
  12632. }
  12633. elseif (substr($this->file->body, $pos, 4) === 'feed')
  12634. {
  12635. return 'application/atom+xml';
  12636. }
  12637. else
  12638. {
  12639. return 'text/html';
  12640. }
  12641. }
  12642. return 'text/html';
  12643. }
  12644. }
  12645. /**
  12646. * Parses the XML Declaration
  12647. *
  12648. * @package SimplePie
  12649. */
  12650. class SimplePie_XML_Declaration_Parser
  12651. {
  12652. /**
  12653. * XML Version
  12654. *
  12655. * @access public
  12656. * @var string
  12657. */
  12658. var $version = '1.0';
  12659. /**
  12660. * Encoding
  12661. *
  12662. * @access public
  12663. * @var string
  12664. */
  12665. var $encoding = 'UTF-8';
  12666. /**
  12667. * Standalone
  12668. *
  12669. * @access public
  12670. * @var bool
  12671. */
  12672. var $standalone = false;
  12673. /**
  12674. * Current state of the state machine
  12675. *
  12676. * @access private
  12677. * @var string
  12678. */
  12679. var $state = 'before_version_name';
  12680. /**
  12681. * Input data
  12682. *
  12683. * @access private
  12684. * @var string
  12685. */
  12686. var $data = '';
  12687. /**
  12688. * Input data length (to avoid calling strlen() everytime this is needed)
  12689. *
  12690. * @access private
  12691. * @var int
  12692. */
  12693. var $data_length = 0;
  12694. /**
  12695. * Current position of the pointer
  12696. *
  12697. * @var int
  12698. * @access private
  12699. */
  12700. var $position = 0;
  12701. /**
  12702. * Create an instance of the class with the input data
  12703. *
  12704. * @access public
  12705. * @param string $data Input data
  12706. */
  12707. function SimplePie_XML_Declaration_Parser($data)
  12708. {
  12709. $this->data = $data;
  12710. $this->data_length = strlen($this->data);
  12711. }
  12712. /**
  12713. * Parse the input data
  12714. *
  12715. * @access public
  12716. * @return bool true on success, false on failure
  12717. */
  12718. function parse()
  12719. {
  12720. while ($this->state && $this->state !== 'emit' && $this->has_data())
  12721. {
  12722. $state = $this->state;
  12723. $this->$state();
  12724. }
  12725. $this->data = '';
  12726. if ($this->state === 'emit')
  12727. {
  12728. return true;
  12729. }
  12730. else
  12731. {
  12732. $this->version = '';
  12733. $this->encoding = '';
  12734. $this->standalone = '';
  12735. return false;
  12736. }
  12737. }
  12738. /**
  12739. * Check whether there is data beyond the pointer
  12740. *
  12741. * @access private
  12742. * @return bool true if there is further data, false if not
  12743. */
  12744. function has_data()
  12745. {
  12746. return (bool) ($this->position < $this->data_length);
  12747. }
  12748. /**
  12749. * Advance past any whitespace
  12750. *
  12751. * @return int Number of whitespace characters passed
  12752. */
  12753. function skip_whitespace()
  12754. {
  12755. $whitespace = strspn($this->data, "\x09\x0A\x0D\x20", $this->position);
  12756. $this->position += $whitespace;
  12757. return $whitespace;
  12758. }
  12759. /**
  12760. * Read value
  12761. */
  12762. function get_value()
  12763. {
  12764. $quote = substr($this->data, $this->position, 1);
  12765. if ($quote === '"' || $quote === "'")
  12766. {
  12767. $this->position++;
  12768. $len = strcspn($this->data, $quote, $this->position);
  12769. if ($this->has_data())
  12770. {
  12771. $value = substr($this->data, $this->position, $len);
  12772. $this->position += $len + 1;
  12773. return $value;
  12774. }
  12775. }
  12776. return false;
  12777. }
  12778. function before_version_name()
  12779. {
  12780. if ($this->skip_whitespace())
  12781. {
  12782. $this->state = 'version_name';
  12783. }
  12784. else
  12785. {
  12786. $this->state = false;
  12787. }
  12788. }
  12789. function version_name()
  12790. {
  12791. if (substr($this->data, $this->position, 7) === 'version')
  12792. {
  12793. $this->position += 7;
  12794. $this->skip_whitespace();
  12795. $this->state = 'version_equals';
  12796. }
  12797. else
  12798. {
  12799. $this->state = false;
  12800. }
  12801. }
  12802. function version_equals()
  12803. {
  12804. if (substr($this->data, $this->position, 1) === '=')
  12805. {
  12806. $this->position++;
  12807. $this->skip_whitespace();
  12808. $this->state = 'version_value';
  12809. }
  12810. else
  12811. {
  12812. $this->state = false;
  12813. }
  12814. }
  12815. function version_value()
  12816. {
  12817. if ($this->version = $this->get_value())
  12818. {
  12819. $this->skip_whitespace();
  12820. if ($this->has_data())
  12821. {
  12822. $this->state = 'encoding_name';
  12823. }
  12824. else
  12825. {
  12826. $this->state = 'emit';
  12827. }
  12828. }
  12829. else
  12830. {
  12831. $this->state = 'standalone_name';
  12832. }
  12833. }
  12834. function encoding_name()
  12835. {
  12836. if (substr($this->data, $this->position, 8) === 'encoding')
  12837. {
  12838. $this->position += 8;
  12839. $this->skip_whitespace();
  12840. $this->state = 'encoding_equals';
  12841. }
  12842. else
  12843. {
  12844. $this->state = false;
  12845. }
  12846. }
  12847. function encoding_equals()
  12848. {
  12849. if (substr($this->data, $this->position, 1) === '=')
  12850. {
  12851. $this->position++;
  12852. $this->skip_whitespace();
  12853. $this->state = 'encoding_value';
  12854. }
  12855. else
  12856. {
  12857. $this->state = false;
  12858. }
  12859. }
  12860. function encoding_value()
  12861. {
  12862. if ($this->encoding = $this->get_value())
  12863. {
  12864. $this->skip_whitespace();
  12865. if ($this->has_data())
  12866. {
  12867. $this->state = 'standalone_name';
  12868. }
  12869. else
  12870. {
  12871. $this->state = 'emit';
  12872. }
  12873. }
  12874. else
  12875. {
  12876. $this->state = false;
  12877. }
  12878. }
  12879. function standalone_name()
  12880. {
  12881. if (substr($this->data, $this->position, 10) === 'standalone')
  12882. {
  12883. $this->position += 10;
  12884. $this->skip_whitespace();
  12885. $this->state = 'standalone_equals';
  12886. }
  12887. else
  12888. {
  12889. $this->state = false;
  12890. }
  12891. }
  12892. function standalone_equals()
  12893. {
  12894. if (substr($this->data, $this->position, 1) === '=')
  12895. {
  12896. $this->position++;
  12897. $this->skip_whitespace();
  12898. $this->state = 'standalone_value';
  12899. }
  12900. else
  12901. {
  12902. $this->state = false;
  12903. }
  12904. }
  12905. function standalone_value()
  12906. {
  12907. if ($standalone = $this->get_value())
  12908. {
  12909. switch ($standalone)
  12910. {
  12911. case 'yes':
  12912. $this->standalone = true;
  12913. break;
  12914. case 'no':
  12915. $this->standalone = false;
  12916. break;
  12917. default:
  12918. $this->state = false;
  12919. return;
  12920. }
  12921. $this->skip_whitespace();
  12922. if ($this->has_data())
  12923. {
  12924. $this->state = false;
  12925. }
  12926. else
  12927. {
  12928. $this->state = 'emit';
  12929. }
  12930. }
  12931. else
  12932. {
  12933. $this->state = false;
  12934. }
  12935. }
  12936. }
  12937. class SimplePie_Locator
  12938. {
  12939. var $useragent;
  12940. var $timeout;
  12941. var $file;
  12942. var $local = array();
  12943. var $elsewhere = array();
  12944. var $file_class = 'SimplePie_File';
  12945. var $cached_entities = array();
  12946. var $http_base;
  12947. var $base;
  12948. var $base_location = 0;
  12949. var $checked_feeds = 0;
  12950. var $max_checked_feeds = 10;
  12951. var $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer';
  12952. function SimplePie_Locator(&$file, $timeout = 10, $useragent = null, $file_class = 'SimplePie_File', $max_checked_feeds = 10, $content_type_sniffer_class = 'SimplePie_Content_Type_Sniffer')
  12953. {
  12954. $this->file =& $file;
  12955. $this->file_class = $file_class;
  12956. $this->useragent = $useragent;
  12957. $this->timeout = $timeout;
  12958. $this->max_checked_feeds = $max_checked_feeds;
  12959. $this->content_type_sniffer_class = $content_type_sniffer_class;
  12960. }
  12961. function find($type = SIMPLEPIE_LOCATOR_ALL, &$working)
  12962. {
  12963. if ($this->is_feed($this->file))
  12964. {
  12965. return $this->file;
  12966. }
  12967. if ($this->file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  12968. {
  12969. $sniffer = new $this->content_type_sniffer_class($this->file);
  12970. if ($sniffer->get_type() !== 'text/html')
  12971. {
  12972. return null;
  12973. }
  12974. }
  12975. if ($type & ~SIMPLEPIE_LOCATOR_NONE)
  12976. {
  12977. $this->get_base();
  12978. }
  12979. if ($type & SIMPLEPIE_LOCATOR_AUTODISCOVERY && $working = $this->autodiscovery())
  12980. {
  12981. return $working[0];
  12982. }
  12983. if ($type & (SIMPLEPIE_LOCATOR_LOCAL_EXTENSION | SIMPLEPIE_LOCATOR_LOCAL_BODY | SIMPLEPIE_LOCATOR_REMOTE_EXTENSION | SIMPLEPIE_LOCATOR_REMOTE_BODY) && $this->get_links())
  12984. {
  12985. if ($type & SIMPLEPIE_LOCATOR_LOCAL_EXTENSION && $working = $this->extension($this->local))
  12986. {
  12987. return $working;
  12988. }
  12989. if ($type & SIMPLEPIE_LOCATOR_LOCAL_BODY && $working = $this->body($this->local))
  12990. {
  12991. return $working;
  12992. }
  12993. if ($type & SIMPLEPIE_LOCATOR_REMOTE_EXTENSION && $working = $this->extension($this->elsewhere))
  12994. {
  12995. return $working;
  12996. }
  12997. if ($type & SIMPLEPIE_LOCATOR_REMOTE_BODY && $working = $this->body($this->elsewhere))
  12998. {
  12999. return $working;
  13000. }
  13001. }
  13002. return null;
  13003. }
  13004. function is_feed(&$file)
  13005. {
  13006. if ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE)
  13007. {
  13008. $sniffer = new $this->content_type_sniffer_class($file);
  13009. $sniffed = $sniffer->get_type();
  13010. if (in_array($sniffed, array('application/rss+xml', 'application/rdf+xml', 'text/rdf', 'application/atom+xml', 'text/xml', 'application/xml')))
  13011. {
  13012. return true;
  13013. }
  13014. else
  13015. {
  13016. return false;
  13017. }
  13018. }
  13019. elseif ($file->method & SIMPLEPIE_FILE_SOURCE_LOCAL)
  13020. {
  13021. return true;
  13022. }
  13023. else
  13024. {
  13025. return false;
  13026. }
  13027. }
  13028. function get_base()
  13029. {
  13030. $this->http_base = $this->file->url;
  13031. $this->base = $this->http_base;
  13032. $elements = SimplePie_Misc::get_element('base', $this->file->body);
  13033. foreach ($elements as $element)
  13034. {
  13035. if ($element['attribs']['href']['data'] !== '')
  13036. {
  13037. $this->base = SimplePie_Misc::absolutize_url(trim($element['attribs']['href']['data']), $this->http_base);
  13038. $this->base_location = $element['offset'];
  13039. break;
  13040. }
  13041. }
  13042. }
  13043. function autodiscovery()
  13044. {
  13045. $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));
  13046. $done = array();
  13047. $feeds = array();
  13048. foreach ($links as $link)
  13049. {
  13050. if ($this->checked_feeds === $this->max_checked_feeds)
  13051. {
  13052. break;
  13053. }
  13054. if (isset($link['attribs']['href']['data']) && isset($link['attribs']['rel']['data']))
  13055. {
  13056. $rel = array_unique(SimplePie_Misc::space_seperated_tokens(strtolower($link['attribs']['rel']['data'])));
  13057. if ($this->base_location < $link['offset'])
  13058. {
  13059. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  13060. }
  13061. else
  13062. {
  13063. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  13064. }
  13065. 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]))
  13066. {
  13067. $this->checked_feeds++;
  13068. $feed = new $this->file_class($href, $this->timeout, 5, null, $this->useragent);
  13069. 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))
  13070. {
  13071. $feeds[$href] = $feed;
  13072. }
  13073. }
  13074. $done[] = $href;
  13075. }
  13076. }
  13077. if (!empty($feeds))
  13078. {
  13079. return array_values($feeds);
  13080. }
  13081. else
  13082. {
  13083. return null;
  13084. }
  13085. }
  13086. function get_links()
  13087. {
  13088. $links = SimplePie_Misc::get_element('a', $this->file->body);
  13089. foreach ($links as $link)
  13090. {
  13091. if (isset($link['attribs']['href']['data']))
  13092. {
  13093. $href = trim($link['attribs']['href']['data']);
  13094. $parsed = SimplePie_Misc::parse_url($href);
  13095. if ($parsed['scheme'] === '' || preg_match('/^(http(s)|feed)?$/i', $parsed['scheme']))
  13096. {
  13097. if ($this->base_location < $link['offset'])
  13098. {
  13099. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->base);
  13100. }
  13101. else
  13102. {
  13103. $href = SimplePie_Misc::absolutize_url(trim($link['attribs']['href']['data']), $this->http_base);
  13104. }
  13105. $current = SimplePie_Misc::parse_url($this->file->url);
  13106. if ($parsed['authority'] === '' || $parsed['authority'] === $current['authority'])
  13107. {
  13108. $this->local[] = $href;
  13109. }
  13110. else
  13111. {
  13112. $this->elsewhere[] = $href;
  13113. }
  13114. }
  13115. }
  13116. }
  13117. $this->local = array_unique($this->local);
  13118. $this->elsewhere = array_unique($this->elsewhere);
  13119. if (!empty($this->local) || !empty($this->elsewhere))
  13120. {
  13121. return true;
  13122. }
  13123. return null;
  13124. }
  13125. function extension(&$array)
  13126. {
  13127. foreach ($array as $key => $value)
  13128. {
  13129. if ($this->checked_feeds === $this->max_checked_feeds)
  13130. {
  13131. break;
  13132. }
  13133. if (in_array(strtolower(strrchr($value, '.')), array('.rss', '.rdf', '.atom', '.xml')))
  13134. {
  13135. $this->checked_feeds++;
  13136. $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
  13137. 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))
  13138. {
  13139. return $feed;
  13140. }
  13141. else
  13142. {
  13143. unset($array[$key]);
  13144. }
  13145. }
  13146. }
  13147. return null;
  13148. }
  13149. function body(&$array)
  13150. {
  13151. foreach ($array as $key => $value)
  13152. {
  13153. if ($this->checked_feeds === $this->max_checked_feeds)
  13154. {
  13155. break;
  13156. }
  13157. if (preg_match('/(rss|rdf|atom|xml)/i', $value))
  13158. {
  13159. $this->checked_feeds++;
  13160. $feed = new $this->file_class($value, $this->timeout, 5, null, $this->useragent);
  13161. 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))
  13162. {
  13163. return $feed;
  13164. }
  13165. else
  13166. {
  13167. unset($array[$key]);
  13168. }
  13169. }
  13170. }
  13171. return null;
  13172. }
  13173. }
  13174. class SimplePie_Parser
  13175. {
  13176. var $error_code;
  13177. var $error_string;
  13178. var $current_line;
  13179. var $current_column;
  13180. var $current_byte;
  13181. var $separator = ' ';
  13182. var $namespace = array('');
  13183. var $element = array('');
  13184. var $xml_base = array('');
  13185. var $xml_base_explicit = array(false);
  13186. var $xml_lang = array('');
  13187. var $data = array();
  13188. var $datas = array(array());
  13189. var $current_xhtml_construct = -1;
  13190. var $encoding;
  13191. function parse(&$data, $encoding)
  13192. {
  13193. // Use UTF-8 if we get passed US-ASCII, as every US-ASCII character is a UTF-8 character
  13194. if (strtoupper($encoding) === 'US-ASCII')
  13195. {
  13196. $this->encoding = 'UTF-8';
  13197. }
  13198. else
  13199. {
  13200. $this->encoding = $encoding;
  13201. }
  13202. // Strip BOM:
  13203. // UTF-32 Big Endian BOM
  13204. if (substr($data, 0, 4) === "\x00\x00\xFE\xFF")
  13205. {
  13206. $data = substr($data, 4);
  13207. }
  13208. // UTF-32 Little Endian BOM
  13209. elseif (substr($data, 0, 4) === "\xFF\xFE\x00\x00")
  13210. {
  13211. $data = substr($data, 4);
  13212. }
  13213. // UTF-16 Big Endian BOM
  13214. elseif (substr($data, 0, 2) === "\xFE\xFF")
  13215. {
  13216. $data = substr($data, 2);
  13217. }
  13218. // UTF-16 Little Endian BOM
  13219. elseif (substr($data, 0, 2) === "\xFF\xFE")
  13220. {
  13221. $data = substr($data, 2);
  13222. }
  13223. // UTF-8 BOM
  13224. elseif (substr($data, 0, 3) === "\xEF\xBB\xBF")
  13225. {
  13226. $data = substr($data, 3);
  13227. }
  13228. if (substr($data, 0, 5) === '<?xml' && strspn(substr($data, 5, 1), "\x09\x0A\x0D\x20") && ($pos = strpos($data, '?>')) !== false)
  13229. {
  13230. $declaration = new SimplePie_XML_Declaration_Parser(substr($data, 5, $pos - 5));
  13231. if ($declaration->parse())
  13232. {
  13233. $data = substr($data, $pos + 2);
  13234. $data = '<?xml version="' . $declaration->version . '" encoding="' . $encoding . '" standalone="' . (($declaration->standalone) ? 'yes' : 'no') . '"?>' . $data;
  13235. }
  13236. else
  13237. {
  13238. $this->error_string = 'SimplePie bug! Please report this!';
  13239. return false;
  13240. }
  13241. }
  13242. $return = true;
  13243. static $xml_is_sane = null;
  13244. if ($xml_is_sane === null)
  13245. {
  13246. $parser_check = xml_parser_create();
  13247. xml_parse_into_struct($parser_check, '<foo>&amp;</foo>', $values);
  13248. xml_parser_free($parser_check);
  13249. $xml_is_sane = isset($values[0]['value']);
  13250. }
  13251. // Create the parser
  13252. if ($xml_is_sane)
  13253. {
  13254. $xml = xml_parser_create_ns($this->encoding, $this->separator);
  13255. xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
  13256. xml_parser_set_option($xml, XML_OPTION_CASE_FOLDING, 0);
  13257. xml_set_object($xml, $this);
  13258. xml_set_character_data_handler($xml, 'cdata');
  13259. xml_set_element_handler($xml, 'tag_open', 'tag_close');
  13260. // Parse!
  13261. if (!xml_parse($xml, $data, true))
  13262. {
  13263. $this->error_code = xml_get_error_code($xml);
  13264. $this->error_string = xml_error_string($this->error_code);
  13265. $return = false;
  13266. }
  13267. $this->current_line = xml_get_current_line_number($xml);
  13268. $this->current_column = xml_get_current_column_number($xml);
  13269. $this->current_byte = xml_get_current_byte_index($xml);
  13270. xml_parser_free($xml);
  13271. return $return;
  13272. }
  13273. else
  13274. {
  13275. libxml_clear_errors();
  13276. $xml = new XMLReader();
  13277. $xml->xml($data);
  13278. while (@$xml->read())
  13279. {
  13280. switch ($xml->nodeType)
  13281. {
  13282. case constant('XMLReader::END_ELEMENT'):
  13283. if ($xml->namespaceURI !== '')
  13284. {
  13285. $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
  13286. }
  13287. else
  13288. {
  13289. $tagName = $xml->localName;
  13290. }
  13291. $this->tag_close(null, $tagName);
  13292. break;
  13293. case constant('XMLReader::ELEMENT'):
  13294. $empty = $xml->isEmptyElement;
  13295. if ($xml->namespaceURI !== '')
  13296. {
  13297. $tagName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
  13298. }
  13299. else
  13300. {
  13301. $tagName = $xml->localName;
  13302. }
  13303. $attributes = array();
  13304. while ($xml->moveToNextAttribute())
  13305. {
  13306. if ($xml->namespaceURI !== '')
  13307. {
  13308. $attrName = "{$xml->namespaceURI}{$this->separator}{$xml->localName}";
  13309. }
  13310. else
  13311. {
  13312. $attrName = $xml->localName;
  13313. }
  13314. $attributes[$attrName] = $xml->value;
  13315. }
  13316. $this->tag_open(null, $tagName, $attributes);
  13317. if ($empty)
  13318. {
  13319. $this->tag_close(null, $tagName);
  13320. }
  13321. break;
  13322. case constant('XMLReader::TEXT'):
  13323. case constant('XMLReader::CDATA'):
  13324. $this->cdata(null, $xml->value);
  13325. break;
  13326. }
  13327. }
  13328. if ($error = libxml_get_last_error())
  13329. {
  13330. $this->error_code = $error->code;
  13331. $this->error_string = $error->message;
  13332. $this->current_line = $error->line;
  13333. $this->current_column = $error->column;
  13334. return false;
  13335. }
  13336. else
  13337. {
  13338. return true;
  13339. }
  13340. }
  13341. }
  13342. function get_error_code()
  13343. {
  13344. return $this->error_code;
  13345. }
  13346. function get_error_string()
  13347. {
  13348. return $this->error_string;
  13349. }
  13350. function get_current_line()
  13351. {
  13352. return $this->current_line;
  13353. }
  13354. function get_current_column()
  13355. {
  13356. return $this->current_column;
  13357. }
  13358. function get_current_byte()
  13359. {
  13360. return $this->current_byte;
  13361. }
  13362. function get_data()
  13363. {
  13364. return $this->data;
  13365. }
  13366. function tag_open($parser, $tag, $attributes)
  13367. {
  13368. list($this->namespace[], $this->element[]) = $this->split_ns($tag);
  13369. $attribs = array();
  13370. foreach ($attributes as $name => $value)
  13371. {
  13372. list($attrib_namespace, $attribute) = $this->split_ns($name);
  13373. $attribs[$attrib_namespace][$attribute] = $value;
  13374. }
  13375. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['base']))
  13376. {
  13377. $this->xml_base[] = SimplePie_Misc::absolutize_url($attribs[SIMPLEPIE_NAMESPACE_XML]['base'], end($this->xml_base));
  13378. $this->xml_base_explicit[] = true;
  13379. }
  13380. else
  13381. {
  13382. $this->xml_base[] = end($this->xml_base);
  13383. $this->xml_base_explicit[] = end($this->xml_base_explicit);
  13384. }
  13385. if (isset($attribs[SIMPLEPIE_NAMESPACE_XML]['lang']))
  13386. {
  13387. $this->xml_lang[] = $attribs[SIMPLEPIE_NAMESPACE_XML]['lang'];
  13388. }
  13389. else
  13390. {
  13391. $this->xml_lang[] = end($this->xml_lang);
  13392. }
  13393. if ($this->current_xhtml_construct >= 0)
  13394. {
  13395. $this->current_xhtml_construct++;
  13396. if (end($this->namespace) === SIMPLEPIE_NAMESPACE_XHTML)
  13397. {
  13398. $this->data['data'] .= '<' . end($this->element);
  13399. if (isset($attribs['']))
  13400. {
  13401. foreach ($attribs[''] as $name => $value)
  13402. {
  13403. $this->data['data'] .= ' ' . $name . '="' . htmlspecialchars($value, ENT_COMPAT, $this->encoding) . '"';
  13404. }
  13405. }
  13406. $this->data['data'] .= '>';
  13407. }
  13408. }
  13409. else
  13410. {
  13411. $this->datas[] =& $this->data;
  13412. $this->data =& $this->data['child'][end($this->namespace)][end($this->element)][];
  13413. $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));
  13414. 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')
  13415. || (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'))
  13416. {
  13417. $this->current_xhtml_construct = 0;
  13418. }
  13419. }
  13420. }
  13421. function cdata($parser, $cdata)
  13422. {
  13423. if ($this->current_xhtml_construct >= 0)
  13424. {
  13425. $this->data['data'] .= htmlspecialchars($cdata, ENT_QUOTES, $this->encoding);
  13426. }
  13427. else
  13428. {
  13429. $this->data['data'] .= $cdata;
  13430. }
  13431. }
  13432. function tag_close($parser, $tag)
  13433. {
  13434. if ($this->current_xhtml_construct >= 0)
  13435. {
  13436. $this->current_xhtml_construct--;
  13437. 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')))
  13438. {
  13439. $this->data['data'] .= '</' . end($this->element) . '>';
  13440. }
  13441. }
  13442. if ($this->current_xhtml_construct === -1)
  13443. {
  13444. $this->data =& $this->datas[count($this->datas) - 1];
  13445. array_pop($this->datas);
  13446. }
  13447. array_pop($this->element);
  13448. array_pop($this->namespace);
  13449. array_pop($this->xml_base);
  13450. array_pop($this->xml_base_explicit);
  13451. array_pop($this->xml_lang);
  13452. }
  13453. function split_ns($string)
  13454. {
  13455. static $cache = array();
  13456. if (!isset($cache[$string]))
  13457. {
  13458. if ($pos = strpos($string, $this->separator))
  13459. {
  13460. static $separator_length;
  13461. if (!$separator_length)
  13462. {
  13463. $separator_length = strlen($this->separator);
  13464. }
  13465. $namespace = substr($string, 0, $pos);
  13466. $local_name = substr($string, $pos + $separator_length);
  13467. if (strtolower($namespace) === SIMPLEPIE_NAMESPACE_ITUNES)
  13468. {
  13469. $namespace = SIMPLEPIE_NAMESPACE_ITUNES;
  13470. }
  13471. // Normalize the Media RSS namespaces
  13472. if ($namespace === SIMPLEPIE_NAMESPACE_MEDIARSS_WRONG)
  13473. {
  13474. $namespace = SIMPLEPIE_NAMESPACE_MEDIARSS;
  13475. }
  13476. $cache[$string] = array($namespace, $local_name);
  13477. }
  13478. else
  13479. {
  13480. $cache[$string] = array('', $string);
  13481. }
  13482. }
  13483. return $cache[$string];
  13484. }
  13485. }
  13486. /**
  13487. * @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
  13488. */
  13489. class SimplePie_Sanitize
  13490. {
  13491. // Private vars
  13492. var $base;
  13493. // Options
  13494. var $remove_div = true;
  13495. var $image_handler = '';
  13496. var $strip_htmltags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style');
  13497. var $encode_instead_of_strip = false;
  13498. var $strip_attributes = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc');
  13499. var $strip_comments = false;
  13500. var $output_encoding = 'UTF-8';
  13501. var $enable_cache = true;
  13502. var $cache_location = './cache';
  13503. var $cache_name_function = 'md5';
  13504. var $cache_class = 'SimplePie_Cache';
  13505. var $file_class = 'SimplePie_File';
  13506. var $timeout = 10;
  13507. var $useragent = '';
  13508. var $force_fsockopen = false;
  13509. var $replace_url_attributes = array(
  13510. 'a' => 'href',
  13511. 'area' => 'href',
  13512. 'blockquote' => 'cite',
  13513. 'del' => 'cite',
  13514. 'form' => 'action',
  13515. 'img' => array('longdesc', 'src'),
  13516. 'input' => 'src',
  13517. 'ins' => 'cite',
  13518. 'q' => 'cite'
  13519. );
  13520. function remove_div($enable = true)
  13521. {
  13522. $this->remove_div = (bool) $enable;
  13523. }
  13524. function set_image_handler($page = false)
  13525. {
  13526. if ($page)
  13527. {
  13528. $this->image_handler = (string) $page;
  13529. }
  13530. else
  13531. {
  13532. $this->image_handler = false;
  13533. }
  13534. }
  13535. function pass_cache_data($enable_cache = true, $cache_location = './cache', $cache_name_function = 'md5', $cache_class = 'SimplePie_Cache')
  13536. {
  13537. if (isset($enable_cache))
  13538. {
  13539. $this->enable_cache = (bool) $enable_cache;
  13540. }
  13541. if ($cache_location)
  13542. {
  13543. $this->cache_location = (string) $cache_location;
  13544. }
  13545. if ($cache_name_function)
  13546. {
  13547. $this->cache_name_function = (string) $cache_name_function;
  13548. }
  13549. if ($cache_class)
  13550. {
  13551. $this->cache_class = (string) $cache_class;
  13552. }
  13553. }
  13554. function pass_file_data($file_class = 'SimplePie_File', $timeout = 10, $useragent = '', $force_fsockopen = false)
  13555. {
  13556. if ($file_class)
  13557. {
  13558. $this->file_class = (string) $file_class;
  13559. }
  13560. if ($timeout)
  13561. {
  13562. $this->timeout = (string) $timeout;
  13563. }
  13564. if ($useragent)
  13565. {
  13566. $this->useragent = (string) $useragent;
  13567. }
  13568. if ($force_fsockopen)
  13569. {
  13570. $this->force_fsockopen = (string) $force_fsockopen;
  13571. }
  13572. }
  13573. function strip_htmltags($tags = array('base', 'blink', 'body', 'doctype', 'embed', 'font', 'form', 'frame', 'frameset', 'html', 'iframe', 'input', 'marquee', 'meta', 'noscript', 'object', 'param', 'script', 'style'))
  13574. {
  13575. if ($tags)
  13576. {
  13577. if (is_array($tags))
  13578. {
  13579. $this->strip_htmltags = $tags;
  13580. }
  13581. else
  13582. {
  13583. $this->strip_htmltags = explode(',', $tags);
  13584. }
  13585. }
  13586. else
  13587. {
  13588. $this->strip_htmltags = false;
  13589. }
  13590. }
  13591. function encode_instead_of_strip($encode = false)
  13592. {
  13593. $this->encode_instead_of_strip = (bool) $encode;
  13594. }
  13595. function strip_attributes($attribs = array('bgsound', 'class', 'expr', 'id', 'style', 'onclick', 'onerror', 'onfinish', 'onmouseover', 'onmouseout', 'onfocus', 'onblur', 'lowsrc', 'dynsrc'))
  13596. {
  13597. if ($attribs)
  13598. {
  13599. if (is_array($attribs))
  13600. {
  13601. $this->strip_attributes = $attribs;
  13602. }
  13603. else
  13604. {
  13605. $this->strip_attributes = explode(',', $attribs);
  13606. }
  13607. }
  13608. else
  13609. {
  13610. $this->strip_attributes = false;
  13611. }
  13612. }
  13613. function strip_comments($strip = false)
  13614. {
  13615. $this->strip_comments = (bool) $strip;
  13616. }
  13617. function set_output_encoding($encoding = 'UTF-8')
  13618. {
  13619. $this->output_encoding = (string) $encoding;
  13620. }
  13621. /**
  13622. * Set element/attribute key/value pairs of HTML attributes
  13623. * containing URLs that need to be resolved relative to the feed
  13624. *
  13625. * @access public
  13626. * @since 1.0
  13627. * @param array $element_attribute Element/attribute key/value pairs
  13628. */
  13629. 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'))
  13630. {
  13631. $this->replace_url_attributes = (array) $element_attribute;
  13632. }
  13633. function sanitize($data, $type, $base = '')
  13634. {
  13635. $data = trim($data);
  13636. if ($data !== '' || $type & SIMPLEPIE_CONSTRUCT_IRI)
  13637. {
  13638. if ($type & SIMPLEPIE_CONSTRUCT_MAYBE_HTML)
  13639. {
  13640. 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))
  13641. {
  13642. $type |= SIMPLEPIE_CONSTRUCT_HTML;
  13643. }
  13644. else
  13645. {
  13646. $type |= SIMPLEPIE_CONSTRUCT_TEXT;
  13647. }
  13648. }
  13649. if ($type & SIMPLEPIE_CONSTRUCT_BASE64)
  13650. {
  13651. $data = base64_decode($data);
  13652. }
  13653. if ($type & SIMPLEPIE_CONSTRUCT_XHTML)
  13654. {
  13655. if ($this->remove_div)
  13656. {
  13657. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '', $data);
  13658. $data = preg_replace('/<\/div>$/', '', $data);
  13659. }
  13660. else
  13661. {
  13662. $data = preg_replace('/^<div' . SIMPLEPIE_PCRE_XML_ATTRIBUTE . '>/', '<div>', $data);
  13663. }
  13664. }
  13665. if ($type & (SIMPLEPIE_CONSTRUCT_HTML | SIMPLEPIE_CONSTRUCT_XHTML))
  13666. {
  13667. // Strip comments
  13668. if ($this->strip_comments)
  13669. {
  13670. $data = SimplePie_Misc::strip_comments($data);
  13671. }
  13672. // Strip out HTML tags and attributes that might cause various security problems.
  13673. // Based on recommendations by Mark Pilgrim at:
  13674. // http://diveintomark.org/archives/2003/06/12/how_to_consume_rss_safely
  13675. if ($this->strip_htmltags)
  13676. {
  13677. foreach ($this->strip_htmltags as $tag)
  13678. {
  13679. $pcre = "/<($tag)" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . "(>(.*)<\/$tag" . SIMPLEPIE_PCRE_HTML_ATTRIBUTE . '>|(\/)?>)/siU';
  13680. while (preg_match($pcre, $data))
  13681. {
  13682. $data = preg_replace_callback($pcre, array(&$this, 'do_strip_htmltags'), $data);
  13683. }
  13684. }
  13685. }
  13686. if ($this->strip_attributes)
  13687. {
  13688. foreach ($this->strip_attributes as $attrib)
  13689. {
  13690. $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);
  13691. }
  13692. }
  13693. // Replace relative URLs
  13694. $this->base = $base;
  13695. foreach ($this->replace_url_attributes as $element => $attributes)
  13696. {
  13697. $data = $this->replace_urls($data, $element, $attributes);
  13698. }
  13699. // If image handling (caching, etc.) is enabled, cache and rewrite all the image tags.
  13700. if (isset($this->image_handler) && ((string) $this->image_handler) !== '' && $this->enable_cache)
  13701. {
  13702. $images = SimplePie_Misc::get_element('img', $data);
  13703. foreach ($images as $img)
  13704. {
  13705. if (isset($img['attribs']['src']['data']))
  13706. {
  13707. $image_url = call_user_func($this->cache_name_function, $img['attribs']['src']['data']);
  13708. $cache = call_user_func(array($this->cache_class, 'create'), $this->cache_location, $image_url, 'spi');
  13709. if ($cache->load())
  13710. {
  13711. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  13712. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  13713. }
  13714. else
  13715. {
  13716. $file = new $this->file_class($img['attribs']['src']['data'], $this->timeout, 5, array('X-FORWARDED-FOR' => $_SERVER['REMOTE_ADDR']), $this->useragent, $this->force_fsockopen);
  13717. $headers = $file->headers;
  13718. if ($file->success && ($file->method & SIMPLEPIE_FILE_SOURCE_REMOTE === 0 || ($file->status_code === 200 || $file->status_code > 206 && $file->status_code < 300)))
  13719. {
  13720. if ($cache->save(array('headers' => $file->headers, 'body' => $file->body)))
  13721. {
  13722. $img['attribs']['src']['data'] = $this->image_handler . $image_url;
  13723. $data = str_replace($img['full'], SimplePie_Misc::element_implode($img), $data);
  13724. }
  13725. else
  13726. {
  13727. trigger_error("$this->cache_location is not writeable", E_USER_WARNING);
  13728. }
  13729. }
  13730. }
  13731. }
  13732. }
  13733. }
  13734. // Having (possibly) taken stuff out, there may now be whitespace at the beginning/end of the data
  13735. $data = trim($data);
  13736. }
  13737. if ($type & SIMPLEPIE_CONSTRUCT_IRI)
  13738. {
  13739. $data = SimplePie_Misc::absolutize_url($data, $base);
  13740. }
  13741. if ($type & (SIMPLEPIE_CONSTRUCT_TEXT | SIMPLEPIE_CONSTRUCT_IRI))
  13742. {
  13743. $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
  13744. }
  13745. if ($this->output_encoding !== 'UTF-8')
  13746. {
  13747. $data = SimplePie_Misc::change_encoding($data, 'UTF-8', $this->output_encoding);
  13748. }
  13749. }
  13750. return $data;
  13751. }
  13752. function replace_urls($data, $tag, $attributes)
  13753. {
  13754. if (!is_array($this->strip_htmltags) || !in_array($tag, $this->strip_htmltags))
  13755. {
  13756. $elements = SimplePie_Misc::get_element($tag, $data);
  13757. foreach ($elements as $element)
  13758. {
  13759. if (is_array($attributes))
  13760. {
  13761. foreach ($attributes as $attribute)
  13762. {
  13763. if (isset($element['attribs'][$attribute]['data']))
  13764. {
  13765. $element['attribs'][$attribute]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attribute]['data'], $this->base);
  13766. $new_element = SimplePie_Misc::element_implode($element);
  13767. $data = str_replace($element['full'], $new_element, $data);
  13768. $element['full'] = $new_element;
  13769. }
  13770. }
  13771. }
  13772. elseif (isset($element['attribs'][$attributes]['data']))
  13773. {
  13774. $element['attribs'][$attributes]['data'] = SimplePie_Misc::absolutize_url($element['attribs'][$attributes]['data'], $this->base);
  13775. $data = str_replace($element['full'], SimplePie_Misc::element_implode($element), $data);
  13776. }
  13777. }
  13778. }
  13779. return $data;
  13780. }
  13781. function do_strip_htmltags($match)
  13782. {
  13783. if ($this->encode_instead_of_strip)
  13784. {
  13785. if (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13786. {
  13787. $match[1] = htmlspecialchars($match[1], ENT_COMPAT, 'UTF-8');
  13788. $match[2] = htmlspecialchars($match[2], ENT_COMPAT, 'UTF-8');
  13789. return "&lt;$match[1]$match[2]&gt;$match[3]&lt;/$match[1]&gt;";
  13790. }
  13791. else
  13792. {
  13793. return htmlspecialchars($match[0], ENT_COMPAT, 'UTF-8');
  13794. }
  13795. }
  13796. elseif (isset($match[4]) && !in_array(strtolower($match[1]), array('script', 'style')))
  13797. {
  13798. return $match[4];
  13799. }
  13800. else
  13801. {
  13802. return '';
  13803. }
  13804. }
  13805. }
  13806. ?>