Projects : mp-wp : mp-wp_genesis

mp-wp/wp-includes/rss.php

Dir - Raw

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