PageRenderTime 31ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/wp-includes/rss.php

https://gitlab.com/VTTE/sitios-vtte
PHP | 954 lines | 658 code | 121 blank | 175 comment | 163 complexity | c21d6d86e75bef00fa6c4a0ec5e1ca3b MD5 | raw file
  1. <?php
  2. /**
  3. * MagpieRSS: a simple RSS integration tool
  4. *
  5. * A compiled file for RSS syndication
  6. *
  7. * @author Kellan Elliott-McCrea <kellan@protest.net>
  8. * @version 0.51
  9. * @license GPL
  10. *
  11. * @package External
  12. * @subpackage MagpieRSS
  13. * @deprecated 3.0.0 Use SimplePie instead.
  14. */
  15. /**
  16. * Deprecated. Use SimplePie (class-simplepie.php) instead.
  17. */
  18. _deprecated_file( basename( __FILE__ ), '3.0.0', WPINC . '/class-simplepie.php' );
  19. /**
  20. * Fires before MagpieRSS is loaded, to optionally replace it.
  21. *
  22. * @since 2.3.0
  23. * @deprecated 3.0.0
  24. */
  25. do_action( 'load_feed_engine' );
  26. /** RSS feed constant. */
  27. define('RSS', 'RSS');
  28. define('ATOM', 'Atom');
  29. define('MAGPIE_USER_AGENT', 'WordPress/' . $GLOBALS['wp_version']);
  30. class MagpieRSS {
  31. var $parser;
  32. var $current_item = array(); // item currently being parsed
  33. var $items = array(); // collection of parsed items
  34. var $channel = array(); // hash of channel fields
  35. var $textinput = array();
  36. var $image = array();
  37. var $feed_type;
  38. var $feed_version;
  39. // parser variables
  40. var $stack = array(); // parser stack
  41. var $inchannel = false;
  42. var $initem = false;
  43. var $incontent = false; // if in Atom <content mode="xml"> field
  44. var $intextinput = false;
  45. var $inimage = false;
  46. var $current_field = '';
  47. var $current_namespace = false;
  48. //var $ERROR = "";
  49. var $_CONTENT_CONSTRUCTS = array('content', 'summary', 'info', 'title', 'tagline', 'copyright');
  50. /**
  51. * PHP5 constructor.
  52. */
  53. function __construct( $source ) {
  54. # Check if PHP xml isn't compiled
  55. #
  56. if ( ! function_exists('xml_parser_create') ) {
  57. return trigger_error( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." );
  58. }
  59. $parser = xml_parser_create();
  60. $this->parser = $parser;
  61. # pass in parser, and a reference to this object
  62. # set up handlers
  63. #
  64. xml_set_object( $this->parser, $this );
  65. xml_set_element_handler($this->parser,
  66. 'feed_start_element', 'feed_end_element' );
  67. xml_set_character_data_handler( $this->parser, 'feed_cdata' );
  68. $status = xml_parse( $this->parser, $source );
  69. if (! $status ) {
  70. $errorcode = xml_get_error_code( $this->parser );
  71. if ( $errorcode != XML_ERROR_NONE ) {
  72. $xml_error = xml_error_string( $errorcode );
  73. $error_line = xml_get_current_line_number($this->parser);
  74. $error_col = xml_get_current_column_number($this->parser);
  75. $errormsg = "$xml_error at line $error_line, column $error_col";
  76. $this->error( $errormsg );
  77. }
  78. }
  79. xml_parser_free( $this->parser );
  80. $this->normalize();
  81. }
  82. /**
  83. * PHP4 constructor.
  84. */
  85. public function MagpieRSS( $source ) {
  86. self::__construct( $source );
  87. }
  88. function feed_start_element($p, $element, &$attrs) {
  89. $el = $element = strtolower($element);
  90. $attrs = array_change_key_case($attrs, CASE_LOWER);
  91. // check for a namespace, and split if found
  92. $ns = false;
  93. if ( strpos( $element, ':' ) ) {
  94. list($ns, $el) = explode( ':', $element, 2);
  95. }
  96. if ( $ns and $ns != 'rdf' ) {
  97. $this->current_namespace = $ns;
  98. }
  99. # if feed type isn't set, then this is first element of feed
  100. # identify feed from root element
  101. #
  102. if (!isset($this->feed_type) ) {
  103. if ( $el == 'rdf' ) {
  104. $this->feed_type = RSS;
  105. $this->feed_version = '1.0';
  106. }
  107. elseif ( $el == 'rss' ) {
  108. $this->feed_type = RSS;
  109. $this->feed_version = $attrs['version'];
  110. }
  111. elseif ( $el == 'feed' ) {
  112. $this->feed_type = ATOM;
  113. $this->feed_version = $attrs['version'];
  114. $this->inchannel = true;
  115. }
  116. return;
  117. }
  118. if ( $el == 'channel' )
  119. {
  120. $this->inchannel = true;
  121. }
  122. elseif ($el == 'item' or $el == 'entry' )
  123. {
  124. $this->initem = true;
  125. if ( isset($attrs['rdf:about']) ) {
  126. $this->current_item['about'] = $attrs['rdf:about'];
  127. }
  128. }
  129. // if we're in the default namespace of an RSS feed,
  130. // record textinput or image fields
  131. elseif (
  132. $this->feed_type == RSS and
  133. $this->current_namespace == '' and
  134. $el == 'textinput' )
  135. {
  136. $this->intextinput = true;
  137. }
  138. elseif (
  139. $this->feed_type == RSS and
  140. $this->current_namespace == '' and
  141. $el == 'image' )
  142. {
  143. $this->inimage = true;
  144. }
  145. # handle atom content constructs
  146. elseif ( $this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
  147. {
  148. // avoid clashing w/ RSS mod_content
  149. if ($el == 'content' ) {
  150. $el = 'atom_content';
  151. }
  152. $this->incontent = $el;
  153. }
  154. // if inside an Atom content construct (e.g. content or summary) field treat tags as text
  155. elseif ($this->feed_type == ATOM and $this->incontent )
  156. {
  157. // if tags are inlined, then flatten
  158. $attrs_str = join(' ',
  159. array_map(array('MagpieRSS', 'map_attrs'),
  160. array_keys($attrs),
  161. array_values($attrs) ) );
  162. $this->append_content( "<$element $attrs_str>" );
  163. array_unshift( $this->stack, $el );
  164. }
  165. // Atom support many links per containging element.
  166. // Magpie treats link elements of type rel='alternate'
  167. // as being equivalent to RSS's simple link element.
  168. //
  169. elseif ($this->feed_type == ATOM and $el == 'link' )
  170. {
  171. if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' )
  172. {
  173. $link_el = 'link';
  174. }
  175. else {
  176. $link_el = 'link_' . $attrs['rel'];
  177. }
  178. $this->append($link_el, $attrs['href']);
  179. }
  180. // set stack[0] to current element
  181. else {
  182. array_unshift($this->stack, $el);
  183. }
  184. }
  185. function feed_cdata ($p, $text) {
  186. if ($this->feed_type == ATOM and $this->incontent)
  187. {
  188. $this->append_content( $text );
  189. }
  190. else {
  191. $current_el = join('_', array_reverse($this->stack));
  192. $this->append($current_el, $text);
  193. }
  194. }
  195. function feed_end_element ($p, $el) {
  196. $el = strtolower($el);
  197. if ( $el == 'item' or $el == 'entry' )
  198. {
  199. $this->items[] = $this->current_item;
  200. $this->current_item = array();
  201. $this->initem = false;
  202. }
  203. elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'textinput' )
  204. {
  205. $this->intextinput = false;
  206. }
  207. elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'image' )
  208. {
  209. $this->inimage = false;
  210. }
  211. elseif ($this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) )
  212. {
  213. $this->incontent = false;
  214. }
  215. elseif ($el == 'channel' or $el == 'feed' )
  216. {
  217. $this->inchannel = false;
  218. }
  219. elseif ($this->feed_type == ATOM and $this->incontent ) {
  220. // balance tags properly
  221. // note: This may not actually be necessary
  222. if ( $this->stack[0] == $el )
  223. {
  224. $this->append_content("</$el>");
  225. }
  226. else {
  227. $this->append_content("<$el />");
  228. }
  229. array_shift( $this->stack );
  230. }
  231. else {
  232. array_shift( $this->stack );
  233. }
  234. $this->current_namespace = false;
  235. }
  236. function concat (&$str1, $str2="") {
  237. if (!isset($str1) ) {
  238. $str1="";
  239. }
  240. $str1 .= $str2;
  241. }
  242. function append_content($text) {
  243. if ( $this->initem ) {
  244. $this->concat( $this->current_item[ $this->incontent ], $text );
  245. }
  246. elseif ( $this->inchannel ) {
  247. $this->concat( $this->channel[ $this->incontent ], $text );
  248. }
  249. }
  250. // smart append - field and namespace aware
  251. function append($el, $text) {
  252. if (!$el) {
  253. return;
  254. }
  255. if ( $this->current_namespace )
  256. {
  257. if ( $this->initem ) {
  258. $this->concat(
  259. $this->current_item[ $this->current_namespace ][ $el ], $text);
  260. }
  261. elseif ($this->inchannel) {
  262. $this->concat(
  263. $this->channel[ $this->current_namespace][ $el ], $text );
  264. }
  265. elseif ($this->intextinput) {
  266. $this->concat(
  267. $this->textinput[ $this->current_namespace][ $el ], $text );
  268. }
  269. elseif ($this->inimage) {
  270. $this->concat(
  271. $this->image[ $this->current_namespace ][ $el ], $text );
  272. }
  273. }
  274. else {
  275. if ( $this->initem ) {
  276. $this->concat(
  277. $this->current_item[ $el ], $text);
  278. }
  279. elseif ($this->intextinput) {
  280. $this->concat(
  281. $this->textinput[ $el ], $text );
  282. }
  283. elseif ($this->inimage) {
  284. $this->concat(
  285. $this->image[ $el ], $text );
  286. }
  287. elseif ($this->inchannel) {
  288. $this->concat(
  289. $this->channel[ $el ], $text );
  290. }
  291. }
  292. }
  293. function normalize () {
  294. // if atom populate rss fields
  295. if ( $this->is_atom() ) {
  296. $this->channel['descripton'] = $this->channel['tagline'];
  297. for ( $i = 0; $i < count($this->items); $i++) {
  298. $item = $this->items[$i];
  299. if ( isset($item['summary']) )
  300. $item['description'] = $item['summary'];
  301. if ( isset($item['atom_content']))
  302. $item['content']['encoded'] = $item['atom_content'];
  303. $this->items[$i] = $item;
  304. }
  305. }
  306. elseif ( $this->is_rss() ) {
  307. $this->channel['tagline'] = $this->channel['description'];
  308. for ( $i = 0; $i < count($this->items); $i++) {
  309. $item = $this->items[$i];
  310. if ( isset($item['description']))
  311. $item['summary'] = $item['description'];
  312. if ( isset($item['content']['encoded'] ) )
  313. $item['atom_content'] = $item['content']['encoded'];
  314. $this->items[$i] = $item;
  315. }
  316. }
  317. }
  318. function is_rss () {
  319. if ( $this->feed_type == RSS ) {
  320. return $this->feed_version;
  321. }
  322. else {
  323. return false;
  324. }
  325. }
  326. function is_atom() {
  327. if ( $this->feed_type == ATOM ) {
  328. return $this->feed_version;
  329. }
  330. else {
  331. return false;
  332. }
  333. }
  334. function map_attrs($k, $v) {
  335. return "$k=\"$v\"";
  336. }
  337. function error( $errormsg, $lvl = E_USER_WARNING ) {
  338. // append PHP's error message if track_errors enabled
  339. if ( isset($php_errormsg) ) {
  340. $errormsg .= " ($php_errormsg)";
  341. }
  342. if ( MAGPIE_DEBUG ) {
  343. trigger_error( $errormsg, $lvl);
  344. } else {
  345. error_log( $errormsg, 0);
  346. }
  347. }
  348. }
  349. if ( !function_exists('fetch_rss') ) :
  350. /**
  351. * Build Magpie object based on RSS from URL.
  352. *
  353. * @since 1.5.0
  354. * @package External
  355. * @subpackage MagpieRSS
  356. *
  357. * @param string $url URL to retrieve feed
  358. * @return bool|MagpieRSS false on failure or MagpieRSS object on success.
  359. */
  360. function fetch_rss ($url) {
  361. // initialize constants
  362. init();
  363. if ( !isset($url) ) {
  364. // error("fetch_rss called without a url");
  365. return false;
  366. }
  367. // if cache is disabled
  368. if ( !MAGPIE_CACHE_ON ) {
  369. // fetch file, and parse it
  370. $resp = _fetch_remote_file( $url );
  371. if ( is_success( $resp->status ) ) {
  372. return _response_to_rss( $resp );
  373. }
  374. else {
  375. // error("Failed to fetch $url and cache is off");
  376. return false;
  377. }
  378. }
  379. // else cache is ON
  380. else {
  381. // Flow
  382. // 1. check cache
  383. // 2. if there is a hit, make sure it's fresh
  384. // 3. if cached obj fails freshness check, fetch remote
  385. // 4. if remote fails, return stale object, or error
  386. $cache = new RSSCache( MAGPIE_CACHE_DIR, MAGPIE_CACHE_AGE );
  387. if (MAGPIE_DEBUG and $cache->ERROR) {
  388. debug($cache->ERROR, E_USER_WARNING);
  389. }
  390. $cache_status = 0; // response of check_cache
  391. $request_headers = array(); // HTTP headers to send with fetch
  392. $rss = 0; // parsed RSS object
  393. $errormsg = 0; // errors, if any
  394. if (!$cache->ERROR) {
  395. // return cache HIT, MISS, or STALE
  396. $cache_status = $cache->check_cache( $url );
  397. }
  398. // if object cached, and cache is fresh, return cached obj
  399. if ( $cache_status == 'HIT' ) {
  400. $rss = $cache->get( $url );
  401. if ( isset($rss) and $rss ) {
  402. $rss->from_cache = 1;
  403. if ( MAGPIE_DEBUG > 1) {
  404. debug("MagpieRSS: Cache HIT", E_USER_NOTICE);
  405. }
  406. return $rss;
  407. }
  408. }
  409. // else attempt a conditional get
  410. // set up headers
  411. if ( $cache_status == 'STALE' ) {
  412. $rss = $cache->get( $url );
  413. if ( isset($rss->etag) and $rss->last_modified ) {
  414. $request_headers['If-None-Match'] = $rss->etag;
  415. $request_headers['If-Last-Modified'] = $rss->last_modified;
  416. }
  417. }
  418. $resp = _fetch_remote_file( $url, $request_headers );
  419. if (isset($resp) and $resp) {
  420. if ($resp->status == '304' ) {
  421. // we have the most current copy
  422. if ( MAGPIE_DEBUG > 1) {
  423. debug("Got 304 for $url");
  424. }
  425. // reset cache on 304 (at minutillo insistent prodding)
  426. $cache->set($url, $rss);
  427. return $rss;
  428. }
  429. elseif ( is_success( $resp->status ) ) {
  430. $rss = _response_to_rss( $resp );
  431. if ( $rss ) {
  432. if (MAGPIE_DEBUG > 1) {
  433. debug("Fetch successful");
  434. }
  435. // add object to cache
  436. $cache->set( $url, $rss );
  437. return $rss;
  438. }
  439. }
  440. else {
  441. $errormsg = "Failed to fetch $url. ";
  442. if ( $resp->error ) {
  443. # compensate for Snoopy's annoying habbit to tacking
  444. # on '\n'
  445. $http_error = substr($resp->error, 0, -2);
  446. $errormsg .= "(HTTP Error: $http_error)";
  447. }
  448. else {
  449. $errormsg .= "(HTTP Response: " . $resp->response_code .')';
  450. }
  451. }
  452. }
  453. else {
  454. $errormsg = "Unable to retrieve RSS file for unknown reasons.";
  455. }
  456. // else fetch failed
  457. // attempt to return cached object
  458. if ($rss) {
  459. if ( MAGPIE_DEBUG ) {
  460. debug("Returning STALE object for $url");
  461. }
  462. return $rss;
  463. }
  464. // else we totally failed
  465. // error( $errormsg );
  466. return false;
  467. } // end if ( !MAGPIE_CACHE_ON ) {
  468. } // end fetch_rss()
  469. endif;
  470. /**
  471. * Retrieve URL headers and content using WP HTTP Request API.
  472. *
  473. * @since 1.5.0
  474. * @package External
  475. * @subpackage MagpieRSS
  476. *
  477. * @param string $url URL to retrieve
  478. * @param array $headers Optional. Headers to send to the URL.
  479. * @return Snoopy style response
  480. */
  481. function _fetch_remote_file($url, $headers = "" ) {
  482. $resp = wp_safe_remote_request( $url, array( 'headers' => $headers, 'timeout' => MAGPIE_FETCH_TIME_OUT ) );
  483. if ( is_wp_error($resp) ) {
  484. $error = array_shift($resp->errors);
  485. $resp = new stdClass;
  486. $resp->status = 500;
  487. $resp->response_code = 500;
  488. $resp->error = $error[0] . "\n"; //\n = Snoopy compatibility
  489. return $resp;
  490. }
  491. // Snoopy returns headers unprocessed.
  492. // Also note, WP_HTTP lowercases all keys, Snoopy did not.
  493. $return_headers = array();
  494. foreach ( wp_remote_retrieve_headers( $resp ) as $key => $value ) {
  495. if ( !is_array($value) ) {
  496. $return_headers[] = "$key: $value";
  497. } else {
  498. foreach ( $value as $v )
  499. $return_headers[] = "$key: $v";
  500. }
  501. }
  502. $response = new stdClass;
  503. $response->status = wp_remote_retrieve_response_code( $resp );
  504. $response->response_code = wp_remote_retrieve_response_code( $resp );
  505. $response->headers = $return_headers;
  506. $response->results = wp_remote_retrieve_body( $resp );
  507. return $response;
  508. }
  509. /**
  510. * Retrieve
  511. *
  512. * @since 1.5.0
  513. * @package External
  514. * @subpackage MagpieRSS
  515. *
  516. * @param array $resp
  517. * @return MagpieRSS|bool
  518. */
  519. function _response_to_rss ($resp) {
  520. $rss = new MagpieRSS( $resp->results );
  521. // if RSS parsed successfully
  522. if ( $rss && (!isset($rss->ERROR) || !$rss->ERROR) ) {
  523. // find Etag, and Last-Modified
  524. foreach ( (array) $resp->headers as $h) {
  525. // 2003-03-02 - Nicola Asuni (www.tecnick.com) - fixed bug "Undefined offset: 1"
  526. if (strpos($h, ": ")) {
  527. list($field, $val) = explode(": ", $h, 2);
  528. }
  529. else {
  530. $field = $h;
  531. $val = "";
  532. }
  533. if ( $field == 'etag' ) {
  534. $rss->etag = $val;
  535. }
  536. if ( $field == 'last-modified' ) {
  537. $rss->last_modified = $val;
  538. }
  539. }
  540. return $rss;
  541. } // else construct error message
  542. else {
  543. $errormsg = "Failed to parse RSS file.";
  544. if ($rss) {
  545. $errormsg .= " (" . $rss->ERROR . ")";
  546. }
  547. // error($errormsg);
  548. return false;
  549. } // end if ($rss and !$rss->error)
  550. }
  551. /**
  552. * Set up constants with default values, unless user overrides.
  553. *
  554. * @since 1.5.0
  555. * @package External
  556. * @subpackage MagpieRSS
  557. */
  558. function init () {
  559. if ( defined('MAGPIE_INITALIZED') ) {
  560. return;
  561. }
  562. else {
  563. define('MAGPIE_INITALIZED', 1);
  564. }
  565. if ( !defined('MAGPIE_CACHE_ON') ) {
  566. define('MAGPIE_CACHE_ON', 1);
  567. }
  568. if ( !defined('MAGPIE_CACHE_DIR') ) {
  569. define('MAGPIE_CACHE_DIR', './cache');
  570. }
  571. if ( !defined('MAGPIE_CACHE_AGE') ) {
  572. define('MAGPIE_CACHE_AGE', 60*60); // one hour
  573. }
  574. if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) {
  575. define('MAGPIE_CACHE_FRESH_ONLY', 0);
  576. }
  577. if ( !defined('MAGPIE_DEBUG') ) {
  578. define('MAGPIE_DEBUG', 0);
  579. }
  580. if ( !defined('MAGPIE_USER_AGENT') ) {
  581. $ua = 'WordPress/' . $GLOBALS['wp_version'];
  582. if ( MAGPIE_CACHE_ON ) {
  583. $ua = $ua . ')';
  584. }
  585. else {
  586. $ua = $ua . '; No cache)';
  587. }
  588. define('MAGPIE_USER_AGENT', $ua);
  589. }
  590. if ( !defined('MAGPIE_FETCH_TIME_OUT') ) {
  591. define('MAGPIE_FETCH_TIME_OUT', 2); // 2 second timeout
  592. }
  593. // use gzip encoding to fetch rss files if supported?
  594. if ( !defined('MAGPIE_USE_GZIP') ) {
  595. define('MAGPIE_USE_GZIP', true);
  596. }
  597. }
  598. function is_info ($sc) {
  599. return $sc >= 100 && $sc < 200;
  600. }
  601. function is_success ($sc) {
  602. return $sc >= 200 && $sc < 300;
  603. }
  604. function is_redirect ($sc) {
  605. return $sc >= 300 && $sc < 400;
  606. }
  607. function is_error ($sc) {
  608. return $sc >= 400 && $sc < 600;
  609. }
  610. function is_client_error ($sc) {
  611. return $sc >= 400 && $sc < 500;
  612. }
  613. function is_server_error ($sc) {
  614. return $sc >= 500 && $sc < 600;
  615. }
  616. class RSSCache {
  617. var $BASE_CACHE; // where the cache files are stored
  618. var $MAX_AGE = 43200; // when are files stale, default twelve hours
  619. var $ERROR = ''; // accumulate error messages
  620. /**
  621. * PHP5 constructor.
  622. */
  623. function __construct( $base = '', $age = '' ) {
  624. $this->BASE_CACHE = WP_CONTENT_DIR . '/cache';
  625. if ( $base ) {
  626. $this->BASE_CACHE = $base;
  627. }
  628. if ( $age ) {
  629. $this->MAX_AGE = $age;
  630. }
  631. }
  632. /**
  633. * PHP4 constructor.
  634. */
  635. public function RSSCache( $base = '', $age = '' ) {
  636. self::__construct( $base, $age );
  637. }
  638. /*=======================================================================*\
  639. Function: set
  640. Purpose: add an item to the cache, keyed on url
  641. Input: url from which the rss file was fetched
  642. Output: true on success
  643. \*=======================================================================*/
  644. function set ($url, $rss) {
  645. $cache_option = 'rss_' . $this->file_name( $url );
  646. set_transient($cache_option, $rss, $this->MAX_AGE);
  647. return $cache_option;
  648. }
  649. /*=======================================================================*\
  650. Function: get
  651. Purpose: fetch an item from the cache
  652. Input: url from which the rss file was fetched
  653. Output: cached object on HIT, false on MISS
  654. \*=======================================================================*/
  655. function get ($url) {
  656. $this->ERROR = "";
  657. $cache_option = 'rss_' . $this->file_name( $url );
  658. if ( ! $rss = get_transient( $cache_option ) ) {
  659. $this->debug(
  660. "Cache doesn't contain: $url (cache option: $cache_option)"
  661. );
  662. return 0;
  663. }
  664. return $rss;
  665. }
  666. /*=======================================================================*\
  667. Function: check_cache
  668. Purpose: check a url for membership in the cache
  669. and whether the object is older then MAX_AGE (ie. STALE)
  670. Input: url from which the rss file was fetched
  671. Output: cached object on HIT, false on MISS
  672. \*=======================================================================*/
  673. function check_cache ( $url ) {
  674. $this->ERROR = "";
  675. $cache_option = 'rss_' . $this->file_name( $url );
  676. if ( get_transient($cache_option) ) {
  677. // object exists and is current
  678. return 'HIT';
  679. } else {
  680. // object does not exist
  681. return 'MISS';
  682. }
  683. }
  684. /*=======================================================================*\
  685. Function: serialize
  686. \*=======================================================================*/
  687. function serialize ( $rss ) {
  688. return serialize( $rss );
  689. }
  690. /*=======================================================================*\
  691. Function: unserialize
  692. \*=======================================================================*/
  693. function unserialize ( $data ) {
  694. return unserialize( $data );
  695. }
  696. /*=======================================================================*\
  697. Function: file_name
  698. Purpose: map url to location in cache
  699. Input: url from which the rss file was fetched
  700. Output: a file name
  701. \*=======================================================================*/
  702. function file_name ($url) {
  703. return md5( $url );
  704. }
  705. /*=======================================================================*\
  706. Function: error
  707. Purpose: register error
  708. \*=======================================================================*/
  709. function error ($errormsg, $lvl=E_USER_WARNING) {
  710. // append PHP's error message if track_errors enabled
  711. if ( isset($php_errormsg) ) {
  712. $errormsg .= " ($php_errormsg)";
  713. }
  714. $this->ERROR = $errormsg;
  715. if ( MAGPIE_DEBUG ) {
  716. trigger_error( $errormsg, $lvl);
  717. }
  718. else {
  719. error_log( $errormsg, 0);
  720. }
  721. }
  722. function debug ($debugmsg, $lvl=E_USER_NOTICE) {
  723. if ( MAGPIE_DEBUG ) {
  724. $this->error("MagpieRSS [debug] $debugmsg", $lvl);
  725. }
  726. }
  727. }
  728. if ( !function_exists('parse_w3cdtf') ) :
  729. function parse_w3cdtf ( $date_str ) {
  730. # regex to match wc3dtf
  731. $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/";
  732. if ( preg_match( $pat, $date_str, $match ) ) {
  733. list( $year, $month, $day, $hours, $minutes, $seconds) =
  734. array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[7]);
  735. # calc epoch for current date assuming GMT
  736. $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year);
  737. $offset = 0;
  738. if ( $match[11] == 'Z' ) {
  739. # zulu time, aka GMT
  740. }
  741. else {
  742. list( $tz_mod, $tz_hour, $tz_min ) =
  743. array( $match[8], $match[9], $match[10]);
  744. # zero out the variables
  745. if ( ! $tz_hour ) { $tz_hour = 0; }
  746. if ( ! $tz_min ) { $tz_min = 0; }
  747. $offset_secs = (($tz_hour*60)+$tz_min)*60;
  748. # is timezone ahead of GMT? then subtract offset
  749. #
  750. if ( $tz_mod == '+' ) {
  751. $offset_secs = $offset_secs * -1;
  752. }
  753. $offset = $offset_secs;
  754. }
  755. $epoch = $epoch + $offset;
  756. return $epoch;
  757. }
  758. else {
  759. return -1;
  760. }
  761. }
  762. endif;
  763. if ( !function_exists('wp_rss') ) :
  764. /**
  765. * Display all RSS items in a HTML ordered list.
  766. *
  767. * @since 1.5.0
  768. * @package External
  769. * @subpackage MagpieRSS
  770. *
  771. * @param string $url URL of feed to display. Will not auto sense feed URL.
  772. * @param int $num_items Optional. Number of items to display, default is all.
  773. */
  774. function wp_rss( $url, $num_items = -1 ) {
  775. if ( $rss = fetch_rss( $url ) ) {
  776. echo '<ul>';
  777. if ( $num_items !== -1 ) {
  778. $rss->items = array_slice( $rss->items, 0, $num_items );
  779. }
  780. foreach ( (array) $rss->items as $item ) {
  781. printf(
  782. '<li><a href="%1$s" title="%2$s">%3$s</a></li>',
  783. esc_url( $item['link'] ),
  784. esc_attr( strip_tags( $item['description'] ) ),
  785. esc_html( $item['title'] )
  786. );
  787. }
  788. echo '</ul>';
  789. } else {
  790. _e( 'An error has occurred, which probably means the feed is down. Try again later.' );
  791. }
  792. }
  793. endif;
  794. if ( !function_exists('get_rss') ) :
  795. /**
  796. * Display RSS items in HTML list items.
  797. *
  798. * You have to specify which HTML list you want, either ordered or unordered
  799. * before using the function. You also have to specify how many items you wish
  800. * to display. You can't display all of them like you can with wp_rss()
  801. * function.
  802. *
  803. * @since 1.5.0
  804. * @package External
  805. * @subpackage MagpieRSS
  806. *
  807. * @param string $url URL of feed to display. Will not auto sense feed URL.
  808. * @param int $num_items Optional. Number of items to display, default is all.
  809. * @return bool False on failure.
  810. */
  811. function get_rss ($url, $num_items = 5) { // Like get posts, but for RSS
  812. $rss = fetch_rss($url);
  813. if ( $rss ) {
  814. $rss->items = array_slice($rss->items, 0, $num_items);
  815. foreach ( (array) $rss->items as $item ) {
  816. echo "<li>\n";
  817. echo "<a href='$item[link]' title='$item[description]'>";
  818. echo esc_html($item['title']);
  819. echo "</a><br />\n";
  820. echo "</li>\n";
  821. }
  822. } else {
  823. return false;
  824. }
  825. }
  826. endif;