Diff: STRATO-apps/wordpress_03/app/wp-includes/rss.php

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