This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * MagpieRSS: a simple RSS integration tool |
||
4 | * |
||
5 | * A compiled file for RSS syndication |
||
6 | * |
||
7 | * @author Kellan Elliott-McCrea <[email protected]> |
||
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 | return trigger_error( "PHP's XML extension is not available. Please contact your hosting provider to enable PHP's XML extension." ); |
||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||
67 | } |
||
68 | |||
69 | $parser = xml_parser_create(); |
||
70 | |||
71 | $this->parser = $parser; |
||
72 | |||
73 | # pass in parser, and a reference to this object |
||
74 | # set up handlers |
||
75 | # |
||
76 | xml_set_object( $this->parser, $this ); |
||
77 | xml_set_element_handler($this->parser, |
||
78 | 'feed_start_element', 'feed_end_element' ); |
||
79 | |||
80 | xml_set_character_data_handler( $this->parser, '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 | xml_parser_free( $this->parser ); |
||
97 | |||
98 | $this->normalize(); |
||
99 | } |
||
100 | |||
101 | /** |
||
102 | * PHP4 constructor. |
||
103 | */ |
||
104 | public function MagpieRSS( $source ) { |
||
105 | self::__construct( $source ); |
||
106 | } |
||
107 | |||
108 | function feed_start_element($p, $element, &$attrs) { |
||
0 ignored issues
–
show
|
|||
109 | $el = $element = strtolower($element); |
||
110 | $attrs = array_change_key_case($attrs, CASE_LOWER); |
||
111 | |||
112 | // check for a namespace, and split if found |
||
113 | $ns = false; |
||
114 | if ( strpos( $element, ':' ) ) { |
||
115 | list($ns, $el) = explode( ':', $element, 2); |
||
116 | } |
||
117 | if ( $ns and $ns != 'rdf' ) { |
||
118 | $this->current_namespace = $ns; |
||
119 | } |
||
120 | |||
121 | # if feed type isn't set, then this is first element of feed |
||
122 | # identify feed from root element |
||
123 | # |
||
124 | if (!isset($this->feed_type) ) { |
||
125 | if ( $el == 'rdf' ) { |
||
126 | $this->feed_type = RSS; |
||
127 | $this->feed_version = '1.0'; |
||
128 | } |
||
129 | elseif ( $el == 'rss' ) { |
||
130 | $this->feed_type = RSS; |
||
131 | $this->feed_version = $attrs['version']; |
||
132 | } |
||
133 | elseif ( $el == 'feed' ) { |
||
134 | $this->feed_type = ATOM; |
||
135 | $this->feed_version = $attrs['version']; |
||
136 | $this->inchannel = true; |
||
137 | } |
||
138 | return; |
||
139 | } |
||
140 | |||
141 | if ( $el == 'channel' ) |
||
142 | { |
||
143 | $this->inchannel = true; |
||
144 | } |
||
145 | elseif ($el == 'item' or $el == 'entry' ) |
||
146 | { |
||
147 | $this->initem = true; |
||
148 | if ( isset($attrs['rdf:about']) ) { |
||
149 | $this->current_item['about'] = $attrs['rdf:about']; |
||
150 | } |
||
151 | } |
||
152 | |||
153 | // if we're in the default namespace of an RSS feed, |
||
154 | // record textinput or image fields |
||
155 | View Code Duplication | elseif ( |
|
156 | $this->feed_type == RSS and |
||
157 | $this->current_namespace == '' and |
||
158 | $el == 'textinput' ) |
||
159 | { |
||
160 | $this->intextinput = true; |
||
161 | } |
||
162 | |||
163 | View Code Duplication | elseif ( |
|
164 | $this->feed_type == RSS and |
||
165 | $this->current_namespace == '' and |
||
166 | $el == 'image' ) |
||
167 | { |
||
168 | $this->inimage = true; |
||
169 | } |
||
170 | |||
171 | # handle atom content constructs |
||
172 | elseif ( $this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) ) |
||
173 | { |
||
174 | // avoid clashing w/ RSS mod_content |
||
175 | if ($el == 'content' ) { |
||
176 | $el = 'atom_content'; |
||
177 | } |
||
178 | |||
179 | $this->incontent = $el; |
||
180 | |||
181 | } |
||
182 | |||
183 | // if inside an Atom content construct (e.g. content or summary) field treat tags as text |
||
184 | elseif ($this->feed_type == ATOM and $this->incontent ) |
||
185 | { |
||
186 | // if tags are inlined, then flatten |
||
187 | $attrs_str = join(' ', |
||
188 | array_map(array('MagpieRSS', 'map_attrs'), |
||
189 | array_keys($attrs), |
||
190 | array_values($attrs) ) ); |
||
191 | |||
192 | $this->append_content( "<$element $attrs_str>" ); |
||
193 | |||
194 | array_unshift( $this->stack, $el ); |
||
195 | } |
||
196 | |||
197 | // Atom support many links per containging element. |
||
198 | // Magpie treats link elements of type rel='alternate' |
||
199 | // as being equivalent to RSS's simple link element. |
||
200 | // |
||
201 | elseif ($this->feed_type == ATOM and $el == 'link' ) |
||
202 | { |
||
203 | if ( isset($attrs['rel']) and $attrs['rel'] == 'alternate' ) |
||
204 | { |
||
205 | $link_el = 'link'; |
||
206 | } |
||
207 | else { |
||
208 | $link_el = 'link_' . $attrs['rel']; |
||
209 | } |
||
210 | |||
211 | $this->append($link_el, $attrs['href']); |
||
212 | } |
||
213 | // set stack[0] to current element |
||
214 | else { |
||
215 | array_unshift($this->stack, $el); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | function feed_cdata ($p, $text) { |
||
0 ignored issues
–
show
|
|||
220 | |||
221 | if ($this->feed_type == ATOM and $this->incontent) |
||
222 | { |
||
223 | $this->append_content( $text ); |
||
224 | } |
||
225 | else { |
||
226 | $current_el = join('_', array_reverse($this->stack)); |
||
227 | $this->append($current_el, $text); |
||
228 | } |
||
229 | } |
||
230 | |||
231 | function feed_end_element ($p, $el) { |
||
0 ignored issues
–
show
|
|||
232 | $el = strtolower($el); |
||
233 | |||
234 | if ( $el == 'item' or $el == 'entry' ) |
||
235 | { |
||
236 | $this->items[] = $this->current_item; |
||
237 | $this->current_item = array(); |
||
238 | $this->initem = false; |
||
239 | } |
||
240 | View Code Duplication | elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'textinput' ) |
|
241 | { |
||
242 | $this->intextinput = false; |
||
243 | } |
||
244 | View Code Duplication | elseif ($this->feed_type == RSS and $this->current_namespace == '' and $el == 'image' ) |
|
245 | { |
||
246 | $this->inimage = false; |
||
247 | } |
||
248 | elseif ($this->feed_type == ATOM and in_array($el, $this->_CONTENT_CONSTRUCTS) ) |
||
249 | { |
||
250 | $this->incontent = false; |
||
251 | } |
||
252 | elseif ($el == 'channel' or $el == 'feed' ) |
||
253 | { |
||
254 | $this->inchannel = false; |
||
255 | } |
||
256 | elseif ($this->feed_type == ATOM and $this->incontent ) { |
||
257 | // balance tags properly |
||
258 | // note: This may not actually be necessary |
||
259 | if ( $this->stack[0] == $el ) |
||
260 | { |
||
261 | $this->append_content("</$el>"); |
||
262 | } |
||
263 | else { |
||
264 | $this->append_content("<$el />"); |
||
265 | } |
||
266 | |||
267 | array_shift( $this->stack ); |
||
268 | } |
||
269 | else { |
||
270 | array_shift( $this->stack ); |
||
271 | } |
||
272 | |||
273 | $this->current_namespace = false; |
||
274 | } |
||
275 | |||
276 | function concat (&$str1, $str2="") { |
||
277 | if (!isset($str1) ) { |
||
278 | $str1=""; |
||
279 | } |
||
280 | $str1 .= $str2; |
||
281 | } |
||
282 | |||
283 | function append_content($text) { |
||
284 | if ( $this->initem ) { |
||
285 | $this->concat( $this->current_item[ $this->incontent ], $text ); |
||
286 | } |
||
287 | elseif ( $this->inchannel ) { |
||
288 | $this->concat( $this->channel[ $this->incontent ], $text ); |
||
289 | } |
||
290 | } |
||
291 | |||
292 | // smart append - field and namespace aware |
||
293 | function append($el, $text) { |
||
294 | if (!$el) { |
||
295 | return; |
||
296 | } |
||
297 | if ( $this->current_namespace ) |
||
298 | { |
||
299 | if ( $this->initem ) { |
||
300 | $this->concat( |
||
301 | $this->current_item[ $this->current_namespace ][ $el ], $text); |
||
302 | } |
||
303 | elseif ($this->inchannel) { |
||
304 | $this->concat( |
||
305 | $this->channel[ $this->current_namespace][ $el ], $text ); |
||
306 | } |
||
307 | elseif ($this->intextinput) { |
||
308 | $this->concat( |
||
309 | $this->textinput[ $this->current_namespace][ $el ], $text ); |
||
310 | } |
||
311 | elseif ($this->inimage) { |
||
312 | $this->concat( |
||
313 | $this->image[ $this->current_namespace ][ $el ], $text ); |
||
314 | } |
||
315 | } |
||
316 | else { |
||
317 | if ( $this->initem ) { |
||
318 | $this->concat( |
||
319 | $this->current_item[ $el ], $text); |
||
320 | } |
||
321 | elseif ($this->intextinput) { |
||
322 | $this->concat( |
||
323 | $this->textinput[ $el ], $text ); |
||
324 | } |
||
325 | elseif ($this->inimage) { |
||
326 | $this->concat( |
||
327 | $this->image[ $el ], $text ); |
||
328 | } |
||
329 | elseif ($this->inchannel) { |
||
330 | $this->concat( |
||
331 | $this->channel[ $el ], $text ); |
||
332 | } |
||
333 | |||
334 | } |
||
335 | } |
||
336 | |||
337 | function normalize () { |
||
338 | // if atom populate rss fields |
||
339 | if ( $this->is_atom() ) { |
||
0 ignored issues
–
show
The expression
$this->is_atom() of type string|false is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
340 | $this->channel['descripton'] = $this->channel['tagline']; |
||
341 | View Code Duplication | for ( $i = 0; $i < count($this->items); $i++) { |
|
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
342 | $item = $this->items[$i]; |
||
343 | if ( isset($item['summary']) ) |
||
344 | $item['description'] = $item['summary']; |
||
345 | if ( isset($item['atom_content'])) |
||
346 | $item['content']['encoded'] = $item['atom_content']; |
||
347 | |||
348 | $this->items[$i] = $item; |
||
349 | } |
||
350 | } |
||
351 | elseif ( $this->is_rss() ) { |
||
0 ignored issues
–
show
The expression
$this->is_rss() of type string|false is loosely compared to true ; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.
In PHP, under loose comparison (like For '' == false // true
'' == null // true
'ab' == false // false
'ab' == null // false
// It is often better to use strict comparison
'' === false // false
'' === null // false
![]() |
|||
352 | $this->channel['tagline'] = $this->channel['description']; |
||
353 | View Code Duplication | for ( $i = 0; $i < count($this->items); $i++) { |
|
0 ignored issues
–
show
It seems like you are calling the size function
count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.
If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration: for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}
// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
![]() |
|||
354 | $item = $this->items[$i]; |
||
355 | if ( isset($item['description'])) |
||
356 | $item['summary'] = $item['description']; |
||
357 | if ( isset($item['content']['encoded'] ) ) |
||
358 | $item['atom_content'] = $item['content']['encoded']; |
||
359 | |||
360 | $this->items[$i] = $item; |
||
361 | } |
||
362 | } |
||
363 | } |
||
364 | |||
365 | function is_rss () { |
||
366 | if ( $this->feed_type == RSS ) { |
||
367 | return $this->feed_version; |
||
368 | } |
||
369 | else { |
||
370 | return false; |
||
371 | } |
||
372 | } |
||
373 | |||
374 | function is_atom() { |
||
375 | if ( $this->feed_type == ATOM ) { |
||
376 | return $this->feed_version; |
||
377 | } |
||
378 | else { |
||
379 | return false; |
||
380 | } |
||
381 | } |
||
382 | |||
383 | function map_attrs($k, $v) { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
384 | return "$k=\"$v\""; |
||
385 | } |
||
386 | |||
387 | View Code Duplication | function error( $errormsg, $lvl = E_USER_WARNING ) { |
|
388 | // append PHP's error message if track_errors enabled |
||
389 | if ( isset($php_errormsg) ) { |
||
390 | $errormsg .= " ($php_errormsg)"; |
||
391 | } |
||
392 | if ( MAGPIE_DEBUG ) { |
||
393 | 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 bool|MagpieRSS false on failure or MagpieRSS object on success. |
||
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 habbit 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. |
||
0 ignored issues
–
show
Should the type for parameter
$headers not be string|array ? Also, consider making the array more specific, something like array<String> , or String[] .
This check looks for It makes a suggestion as to what type it considers more descriptive. In addition it
looks for parameters that have the generic type Most often this is a case of a parameter that can be null in addition to its declared types. ![]() |
|||
548 | * @return Snoopy style response |
||
0 ignored issues
–
show
|
|||
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 |
||
0 ignored issues
–
show
|
|||
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; |
||
0 ignored issues
–
show
The property
etag does not seem to exist in MagpieRSS .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
612 | } |
||
613 | |||
614 | if ( $field == 'last-modified' ) { |
||
615 | $rss->last_modified = $val; |
||
0 ignored issues
–
show
The property
last_modified does not seem to exist in MagpieRSS .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
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 . ")"; |
||
0 ignored issues
–
show
The property
ERROR does not seem to exist in MagpieRSS .
An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name. If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading. ![]() |
|||
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 | * @package External |
||
638 | * @subpackage MagpieRSS |
||
639 | */ |
||
640 | function init () { |
||
641 | if ( defined('MAGPIE_INITALIZED') ) { |
||
642 | return; |
||
643 | } |
||
644 | else { |
||
645 | define('MAGPIE_INITALIZED', 1); |
||
646 | } |
||
647 | |||
648 | if ( !defined('MAGPIE_CACHE_ON') ) { |
||
649 | define('MAGPIE_CACHE_ON', 1); |
||
650 | } |
||
651 | |||
652 | if ( !defined('MAGPIE_CACHE_DIR') ) { |
||
653 | define('MAGPIE_CACHE_DIR', './cache'); |
||
654 | } |
||
655 | |||
656 | if ( !defined('MAGPIE_CACHE_AGE') ) { |
||
657 | define('MAGPIE_CACHE_AGE', 60*60); // one hour |
||
658 | } |
||
659 | |||
660 | if ( !defined('MAGPIE_CACHE_FRESH_ONLY') ) { |
||
661 | define('MAGPIE_CACHE_FRESH_ONLY', 0); |
||
662 | } |
||
663 | |||
664 | if ( !defined('MAGPIE_DEBUG') ) { |
||
665 | define('MAGPIE_DEBUG', 0); |
||
666 | } |
||
667 | |||
668 | if ( !defined('MAGPIE_USER_AGENT') ) { |
||
669 | $ua = 'WordPress/' . $GLOBALS['wp_version']; |
||
670 | |||
671 | if ( MAGPIE_CACHE_ON ) { |
||
672 | $ua = $ua . ')'; |
||
673 | } |
||
674 | else { |
||
675 | $ua = $ua . '; No cache)'; |
||
676 | } |
||
677 | |||
678 | define('MAGPIE_USER_AGENT', $ua); |
||
679 | } |
||
680 | |||
681 | if ( !defined('MAGPIE_FETCH_TIME_OUT') ) { |
||
682 | define('MAGPIE_FETCH_TIME_OUT', 2); // 2 second timeout |
||
683 | } |
||
684 | |||
685 | // use gzip encoding to fetch rss files if supported? |
||
686 | if ( !defined('MAGPIE_USE_GZIP') ) { |
||
687 | define('MAGPIE_USE_GZIP', true); |
||
688 | } |
||
689 | } |
||
690 | |||
691 | function is_info ($sc) { |
||
692 | return $sc >= 100 && $sc < 200; |
||
693 | } |
||
694 | |||
695 | function is_success ($sc) { |
||
696 | return $sc >= 200 && $sc < 300; |
||
697 | } |
||
698 | |||
699 | function is_redirect ($sc) { |
||
700 | return $sc >= 300 && $sc < 400; |
||
701 | } |
||
702 | |||
703 | function is_error ($sc) { |
||
704 | return $sc >= 400 && $sc < 600; |
||
705 | } |
||
706 | |||
707 | function is_client_error ($sc) { |
||
708 | return $sc >= 400 && $sc < 500; |
||
709 | } |
||
710 | |||
711 | function is_server_error ($sc) { |
||
712 | return $sc >= 500 && $sc < 600; |
||
713 | } |
||
714 | |||
715 | class RSSCache { |
||
716 | var $BASE_CACHE; // where the cache files are stored |
||
717 | var $MAX_AGE = 43200; // when are files stale, default twelve hours |
||
718 | var $ERROR = ''; // accumulate error messages |
||
719 | |||
720 | /** |
||
721 | * PHP5 constructor. |
||
722 | */ |
||
723 | function __construct( $base = '', $age = '' ) { |
||
724 | $this->BASE_CACHE = WP_CONTENT_DIR . '/cache'; |
||
725 | if ( $base ) { |
||
726 | $this->BASE_CACHE = $base; |
||
727 | } |
||
728 | if ( $age ) { |
||
729 | $this->MAX_AGE = $age; |
||
0 ignored issues
–
show
The property
$MAX_AGE was declared of type integer , but $age is of type string . Maybe add a type cast?
This check looks for assignments to scalar types that may be of the wrong type. To ensure the code behaves as expected, it may be a good idea to add an explicit type cast. $answer = 42;
$correct = false;
$correct = (bool) $answer;
![]() |
|||
730 | } |
||
731 | |||
732 | } |
||
733 | |||
734 | /** |
||
735 | * PHP4 constructor. |
||
736 | */ |
||
737 | public function RSSCache( $base = '', $age = '' ) { |
||
738 | self::__construct( $base, $age ); |
||
739 | } |
||
740 | |||
741 | /*=======================================================================*\ |
||
742 | Function: set |
||
743 | Purpose: add an item to the cache, keyed on url |
||
744 | Input: url from which the rss file was fetched |
||
745 | Output: true on success |
||
746 | \*=======================================================================*/ |
||
747 | function set ($url, $rss) { |
||
748 | $cache_option = 'rss_' . $this->file_name( $url ); |
||
749 | |||
750 | set_transient($cache_option, $rss, $this->MAX_AGE); |
||
751 | |||
752 | return $cache_option; |
||
753 | } |
||
754 | |||
755 | /*=======================================================================*\ |
||
756 | Function: get |
||
757 | Purpose: fetch an item from the cache |
||
758 | Input: url from which the rss file was fetched |
||
759 | Output: cached object on HIT, false on MISS |
||
760 | \*=======================================================================*/ |
||
761 | function get ($url) { |
||
762 | $this->ERROR = ""; |
||
763 | $cache_option = 'rss_' . $this->file_name( $url ); |
||
764 | |||
765 | if ( ! $rss = get_transient( $cache_option ) ) { |
||
766 | $this->debug( |
||
767 | "Cache doesn't contain: $url (cache option: $cache_option)" |
||
768 | ); |
||
769 | return 0; |
||
770 | } |
||
771 | |||
772 | return $rss; |
||
773 | } |
||
774 | |||
775 | /*=======================================================================*\ |
||
776 | Function: check_cache |
||
777 | Purpose: check a url for membership in the cache |
||
778 | and whether the object is older then MAX_AGE (ie. STALE) |
||
779 | Input: url from which the rss file was fetched |
||
780 | Output: cached object on HIT, false on MISS |
||
781 | \*=======================================================================*/ |
||
782 | function check_cache ( $url ) { |
||
783 | $this->ERROR = ""; |
||
784 | $cache_option = 'rss_' . $this->file_name( $url ); |
||
785 | |||
786 | if ( get_transient($cache_option) ) { |
||
787 | // object exists and is current |
||
788 | return 'HIT'; |
||
789 | } else { |
||
790 | // object does not exist |
||
791 | return 'MISS'; |
||
792 | } |
||
793 | } |
||
794 | |||
795 | /*=======================================================================*\ |
||
796 | Function: serialize |
||
797 | \*=======================================================================*/ |
||
798 | function serialize ( $rss ) { |
||
799 | return serialize( $rss ); |
||
800 | } |
||
801 | |||
802 | /*=======================================================================*\ |
||
803 | Function: unserialize |
||
804 | \*=======================================================================*/ |
||
805 | function unserialize ( $data ) { |
||
0 ignored issues
–
show
The return type could not be reliably inferred; please add a
@return annotation.
Our type inference engine in quite powerful, but sometimes the code does not
provide enough clues to go by. In these cases we request you to add a ![]() |
|||
806 | return unserialize( $data ); |
||
807 | } |
||
808 | |||
809 | /*=======================================================================*\ |
||
810 | Function: file_name |
||
811 | Purpose: map url to location in cache |
||
812 | Input: url from which the rss file was fetched |
||
813 | Output: a file name |
||
814 | \*=======================================================================*/ |
||
815 | function file_name ($url) { |
||
816 | return md5( $url ); |
||
817 | } |
||
818 | |||
819 | /*=======================================================================*\ |
||
820 | Function: error |
||
821 | Purpose: register error |
||
822 | \*=======================================================================*/ |
||
823 | View Code Duplication | function error ($errormsg, $lvl=E_USER_WARNING) { |
|
824 | // append PHP's error message if track_errors enabled |
||
825 | if ( isset($php_errormsg) ) { |
||
826 | $errormsg .= " ($php_errormsg)"; |
||
827 | } |
||
828 | $this->ERROR = $errormsg; |
||
829 | if ( MAGPIE_DEBUG ) { |
||
830 | trigger_error( $errormsg, $lvl); |
||
831 | } |
||
832 | else { |
||
833 | error_log( $errormsg, 0); |
||
834 | } |
||
835 | } |
||
836 | function debug ($debugmsg, $lvl=E_USER_NOTICE) { |
||
837 | if ( MAGPIE_DEBUG ) { |
||
838 | $this->error("MagpieRSS [debug] $debugmsg", $lvl); |
||
839 | } |
||
840 | } |
||
841 | } |
||
842 | |||
843 | if ( !function_exists('parse_w3cdtf') ) : |
||
844 | function parse_w3cdtf ( $date_str ) { |
||
845 | |||
846 | # regex to match wc3dtf |
||
847 | $pat = "/(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?(?:([-+])(\d{2}):?(\d{2})|(Z))?/"; |
||
848 | |||
849 | if ( preg_match( $pat, $date_str, $match ) ) { |
||
850 | list( $year, $month, $day, $hours, $minutes, $seconds) = |
||
851 | array( $match[1], $match[2], $match[3], $match[4], $match[5], $match[7]); |
||
852 | |||
853 | # calc epoch for current date assuming GMT |
||
854 | $epoch = gmmktime( $hours, $minutes, $seconds, $month, $day, $year); |
||
855 | |||
856 | $offset = 0; |
||
857 | if ( $match[11] == 'Z' ) { |
||
858 | # zulu time, aka GMT |
||
859 | } |
||
860 | else { |
||
861 | list( $tz_mod, $tz_hour, $tz_min ) = |
||
862 | array( $match[8], $match[9], $match[10]); |
||
863 | |||
864 | # zero out the variables |
||
865 | if ( ! $tz_hour ) { $tz_hour = 0; } |
||
866 | if ( ! $tz_min ) { $tz_min = 0; } |
||
867 | |||
868 | $offset_secs = (($tz_hour*60)+$tz_min)*60; |
||
869 | |||
870 | # is timezone ahead of GMT? then subtract offset |
||
871 | # |
||
872 | if ( $tz_mod == '+' ) { |
||
873 | $offset_secs = $offset_secs * -1; |
||
874 | } |
||
875 | |||
876 | $offset = $offset_secs; |
||
877 | } |
||
878 | $epoch = $epoch + $offset; |
||
879 | return $epoch; |
||
880 | } |
||
881 | else { |
||
882 | return -1; |
||
883 | } |
||
884 | } |
||
885 | endif; |
||
886 | |||
887 | if ( !function_exists('wp_rss') ) : |
||
888 | /** |
||
889 | * Display all RSS items in a HTML ordered list. |
||
890 | * |
||
891 | * @since 1.5.0 |
||
892 | * @package External |
||
893 | * @subpackage MagpieRSS |
||
894 | * |
||
895 | * @param string $url URL of feed to display. Will not auto sense feed URL. |
||
896 | * @param int $num_items Optional. Number of items to display, default is all. |
||
897 | */ |
||
898 | function wp_rss( $url, $num_items = -1 ) { |
||
899 | if ( $rss = fetch_rss( $url ) ) { |
||
900 | echo '<ul>'; |
||
901 | |||
902 | if ( $num_items !== -1 ) { |
||
903 | $rss->items = array_slice( $rss->items, 0, $num_items ); |
||
904 | } |
||
905 | |||
906 | foreach ( (array) $rss->items as $item ) { |
||
907 | printf( |
||
908 | '<li><a href="%1$s" title="%2$s">%3$s</a></li>', |
||
909 | esc_url( $item['link'] ), |
||
910 | esc_attr( strip_tags( $item['description'] ) ), |
||
911 | esc_html( $item['title'] ) |
||
912 | ); |
||
913 | } |
||
914 | |||
915 | echo '</ul>'; |
||
916 | } else { |
||
917 | _e( 'An error has occurred, which probably means the feed is down. Try again later.' ); |
||
918 | } |
||
919 | } |
||
920 | endif; |
||
921 | |||
922 | if ( !function_exists('get_rss') ) : |
||
923 | /** |
||
924 | * Display RSS items in HTML list items. |
||
925 | * |
||
926 | * You have to specify which HTML list you want, either ordered or unordered |
||
927 | * before using the function. You also have to specify how many items you wish |
||
928 | * to display. You can't display all of them like you can with wp_rss() |
||
929 | * function. |
||
930 | * |
||
931 | * @since 1.5.0 |
||
932 | * @package External |
||
933 | * @subpackage MagpieRSS |
||
934 | * |
||
935 | * @param string $url URL of feed to display. Will not auto sense feed URL. |
||
936 | * @param int $num_items Optional. Number of items to display, default is all. |
||
937 | * @return bool False on failure. |
||
0 ignored issues
–
show
|
|||
938 | */ |
||
939 | function get_rss ($url, $num_items = 5) { // Like get posts, but for RSS |
||
940 | $rss = fetch_rss($url); |
||
941 | if ( $rss ) { |
||
942 | $rss->items = array_slice($rss->items, 0, $num_items); |
||
943 | foreach ( (array) $rss->items as $item ) { |
||
944 | echo "<li>\n"; |
||
945 | echo "<a href='$item[link]' title='$item[description]'>"; |
||
946 | echo esc_html($item['title']); |
||
947 | echo "</a><br />\n"; |
||
948 | echo "</li>\n"; |
||
949 | } |
||
950 | } else { |
||
951 | return false; |
||
952 | } |
||
953 | } |
||
954 | endif; |
||
955 |