Diff: STRATO-apps/wordpress_03/app/wp-includes/rss.php
Keine Baseline-Datei – Diff nur gegen leer.
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
+