1 | <?php |
2 | /** |
3 | * WordPress Feed API |
4 | * |
5 | * Many of the functions used in here belong in The Loop, or The Loop for the |
6 | * Feeds. |
7 | * |
8 | * @package WordPress |
9 | * @subpackage Feed |
10 | */ |
11 | |
12 | /** |
13 | * RSS container for the bloginfo function. |
14 | * |
15 | * You can retrieve anything that you can using the get_bloginfo() function. |
16 | * Everything will be stripped of tags and characters converted, when the values |
17 | * are retrieved for use in the feeds. |
18 | * |
19 | * @package WordPress |
20 | * @subpackage Feed |
21 | * @since 1.5.1 |
22 | * @uses apply_filters() Calls 'get_bloginfo_rss' hook with two parameters. |
23 | * @see get_bloginfo() For the list of possible values to display. |
24 | * |
25 | * @param string $show See get_bloginfo() for possible values. |
26 | * @return string |
27 | */ |
28 | function get_bloginfo_rss($show = '') { |
29 | $info = strip_tags(get_bloginfo($show)); |
30 | return apply_filters('get_bloginfo_rss', convert_chars($info), $show); |
31 | } |
32 | |
33 | /** |
34 | * Display RSS container for the bloginfo function. |
35 | * |
36 | * You can retrieve anything that you can using the get_bloginfo() function. |
37 | * Everything will be stripped of tags and characters converted, when the values |
38 | * are retrieved for use in the feeds. |
39 | * |
40 | * @package WordPress |
41 | * @subpackage Feed |
42 | * @since 0.71 |
43 | * @uses apply_filters() Calls 'bloginfo_rss' hook with two parameters. |
44 | * @see get_bloginfo() For the list of possible values to display. |
45 | * |
46 | * @param string $show See get_bloginfo() for possible values. |
47 | */ |
48 | function bloginfo_rss($show = '') { |
49 | echo apply_filters('bloginfo_rss', get_bloginfo_rss($show), $show); |
50 | } |
51 | |
52 | /** |
53 | * Retrieve the default feed. |
54 | * |
55 | * The default feed is 'rss2', unless a plugin changes it through the |
56 | * 'default_feed' filter. |
57 | * |
58 | * @package WordPress |
59 | * @subpackage Feed |
60 | * @since 2.5 |
61 | * @uses apply_filters() Calls 'default_feed' hook on the default feed string. |
62 | * |
63 | * @return string Default feed, or for example 'rss2', 'atom', etc. |
64 | */ |
65 | function get_default_feed() { |
66 | return apply_filters('default_feed', 'rss2'); |
67 | } |
68 | |
69 | /** |
70 | * Retrieve the blog title for the feed title. |
71 | * |
72 | * @package WordPress |
73 | * @subpackage Feed |
74 | * @since 2.2.0 |
75 | * @uses apply_filters() Calls 'get_wp_title_rss' hook on title. |
76 | * @uses wp_title() See function for $sep parameter usage. |
77 | * |
78 | * @param string $sep Optional.How to separate the title. See wp_title() for more info. |
79 | * @return string Error message on failure or blog title on success. |
80 | */ |
81 | function get_wp_title_rss($sep = '»') { |
82 | $title = wp_title($sep, false); |
83 | if ( is_wp_error( $title ) ) |
84 | return $title->get_error_message(); |
85 | $title = apply_filters('get_wp_title_rss', $title); |
86 | return $title; |
87 | } |
88 | |
89 | /** |
90 | * Display the blog title for display of the feed title. |
91 | * |
92 | * @package WordPress |
93 | * @subpackage Feed |
94 | * @since 2.2.0 |
95 | * @uses apply_filters() Calls 'wp_title_rss' on the blog title. |
96 | * @see wp_title() $sep parameter usage. |
97 | * |
98 | * @param string $sep Optional. |
99 | */ |
100 | function wp_title_rss($sep = '»') { |
101 | echo apply_filters('wp_title_rss', get_wp_title_rss($sep)); |
102 | } |
103 | |
104 | /** |
105 | * Retrieve the current post title for the feed. |
106 | * |
107 | * @package WordPress |
108 | * @subpackage Feed |
109 | * @since 2.0.0 |
110 | * @uses apply_filters() Calls 'the_title_rss' on the post title. |
111 | * |
112 | * @return string Current post title. |
113 | */ |
114 | function get_the_title_rss() { |
115 | $title = get_the_title(); |
116 | $title = apply_filters('the_title_rss', $title); |
117 | return $title; |
118 | } |
119 | |
120 | /** |
121 | * Display the post title in the feed. |
122 | * |
123 | * @package WordPress |
124 | * @subpackage Feed |
125 | * @since 0.71 |
126 | * @uses get_the_title_rss() Used to retrieve current post title. |
127 | */ |
128 | function the_title_rss() { |
129 | echo get_the_title_rss(); |
130 | } |
131 | |
132 | /** |
133 | * Retrieve the post content for feeds. |
134 | * |
135 | * @package WordPress |
136 | * @subpackage Feed |
137 | * @since 2.9.0 |
138 | * @uses apply_filters() Calls 'the_content_feed' on the content before processing. |
139 | * @see get_the_content() |
140 | * |
141 | * @param string $feed_type The type of feed. rss2 | atom | rss | rdf |
142 | */ |
143 | function get_the_content_feed($feed_type = null) { |
144 | if ( !$feed_type ) |
145 | $feed_type = get_default_feed(); |
146 | |
147 | $content = apply_filters('the_content', get_the_content()); |
148 | $content = str_replace(']]>', ']]>', $content); |
149 | return apply_filters('the_content_feed', $content, $feed_type); |
150 | } |
151 | |
152 | /** |
153 | * Display the post content for feeds. |
154 | * |
155 | * @package WordPress |
156 | * @subpackage Feed |
157 | * @since 2.9.0 |
158 | * @uses apply_filters() Calls 'the_content_feed' on the content before processing. |
159 | * @see get_the_content() |
160 | * |
161 | * @param string $feed_type The type of feed. rss2 | atom | rss | rdf |
162 | */ |
163 | function the_content_feed($feed_type = null) { |
164 | echo get_the_content_feed(); |
165 | } |
166 | |
167 | /** |
168 | * Display the post excerpt for the feed. |
169 | * |
170 | * @package WordPress |
171 | * @subpackage Feed |
172 | * @since 0.71 |
173 | * @uses apply_filters() Calls 'the_excerpt_rss' hook on the excerpt. |
174 | */ |
175 | function the_excerpt_rss() { |
176 | $output = get_the_excerpt(); |
177 | echo apply_filters('the_excerpt_rss', $output); |
178 | } |
179 | |
180 | /** |
181 | * Display the permalink to the post for use in feeds. |
182 | * |
183 | * @package WordPress |
184 | * @subpackage Feed |
185 | * @since 2.3.0 |
186 | * @uses apply_filters() Call 'the_permalink_rss' on the post permalink |
187 | */ |
188 | function the_permalink_rss() { |
189 | echo esc_url( apply_filters('the_permalink_rss', get_permalink() )); |
190 | } |
191 | |
192 | /** |
193 | * Outputs the link to the comments for the current post in an xml safe way |
194 | * |
195 | * @since 3.0.0 |
196 | * @return none |
197 | */ |
198 | function comments_link_feed() { |
199 | echo esc_url( get_comments_link() ); |
200 | } |
201 | |
202 | /** |
203 | * Display the feed GUID for the current comment. |
204 | * |
205 | * @package WordPress |
206 | * @subpackage Feed |
207 | * @since unknown |
208 | * |
209 | * @param int|object $comment_id Optional comment object or id. Defaults to global comment object. |
210 | */ |
211 | function comment_guid($comment_id = null) { |
212 | echo esc_url( get_comment_guid($comment_id) ); |
213 | } |
214 | |
215 | /** |
216 | * Retrieve the feed GUID for the current comment. |
217 | * |
218 | * @package WordPress |
219 | * @subpackage Feed |
220 | * @since unknown |
221 | * |
222 | * @param int|object $comment_id Optional comment object or id. Defaults to global comment object. |
223 | * @return bool|string false on failure or guid for comment on success. |
224 | */ |
225 | function get_comment_guid($comment_id = null) { |
226 | $comment = get_comment($comment_id); |
227 | |
228 | if ( !is_object($comment) ) |
229 | return false; |
230 | |
231 | return get_the_guid($comment->comment_post_ID) . '#comment-' . $comment->comment_ID; |
232 | } |
233 | |
234 | /** |
235 | * Display the link to the comments. |
236 | * |
237 | * @since 1.5.0 |
238 | */ |
239 | function comment_link() { |
240 | echo esc_url( get_comment_link() ); |
241 | } |
242 | |
243 | /** |
244 | * Retrieve the current comment author for use in the feeds. |
245 | * |
246 | * @package WordPress |
247 | * @subpackage Feed |
248 | * @since 2.0.0 |
249 | * @uses apply_filters() Calls 'comment_author_rss' hook on comment author. |
250 | * @uses get_comment_author() |
251 | * |
252 | * @return string Comment Author |
253 | */ |
254 | function get_comment_author_rss() { |
255 | return apply_filters('comment_author_rss', get_comment_author() ); |
256 | } |
257 | |
258 | /** |
259 | * Display the current comment author in the feed. |
260 | * |
261 | * @package WordPress |
262 | * @subpackage Feed |
263 | * @since 1.0.0 |
264 | */ |
265 | function comment_author_rss() { |
266 | echo get_comment_author_rss(); |
267 | } |
268 | |
269 | /** |
270 | * Display the current comment content for use in the feeds. |
271 | * |
272 | * @package WordPress |
273 | * @subpackage Feed |
274 | * @since 1.0.0 |
275 | * @uses apply_filters() Calls 'comment_text_rss' filter on comment content. |
276 | * @uses get_comment_text() |
277 | */ |
278 | function comment_text_rss() { |
279 | $comment_text = get_comment_text(); |
280 | $comment_text = apply_filters('comment_text_rss', $comment_text); |
281 | echo $comment_text; | //Cross Site Scripting
|
282 | } |
283 | |
284 | /** |
285 | * Retrieve all of the post categories, formatted for use in feeds. |
286 | * |
287 | * All of the categories for the current post in the feed loop, will be |
288 | * retrieved and have feed markup added, so that they can easily be added to the |
289 | * RSS2, Atom, or RSS1 and RSS0.91 RDF feeds. |
290 | * |
291 | * @package WordPress |
292 | * @subpackage Feed |
293 | * @since 2.1.0 |
294 | * @uses apply_filters() |
295 | * |
296 | * @param string $type Optional, default is the type returned by get_default_feed(). |
297 | * @return string All of the post categories for displaying in the feed. |
298 | */ |
299 | function get_the_category_rss($type = null) { |
300 | if ( empty($type) ) |
301 | $type = get_default_feed(); |
302 | $categories = get_the_category(); |
303 | $tags = get_the_tags(); |
304 | $the_list = ''; |
305 | $cat_names = array(); |
306 | |
307 | $filter = 'rss'; |
308 | if ( 'atom' == $type ) |
309 | $filter = 'raw'; |
310 | |
311 | if ( !empty($categories) ) foreach ( (array) $categories as $category ) { |
312 | $cat_names[] = sanitize_term_field('name', $category->name, $category->term_id, 'category', $filter); |
313 | } |
314 | |
315 | if ( !empty($tags) ) foreach ( (array) $tags as $tag ) { |
316 | $cat_names[] = sanitize_term_field('name', $tag->name, $tag->term_id, 'post_tag', $filter); |
317 | } |
318 | |
319 | $cat_names = array_unique($cat_names); |
320 | |
321 | foreach ( $cat_names as $cat_name ) { |
322 | if ( 'rdf' == $type ) |
323 | $the_list .= "\t\t<dc:subject><![CDATA[$cat_name]]></dc:subject>\n"; |
324 | elseif ( 'atom' == $type ) |
325 | $the_list .= sprintf( '<category scheme="%1$s" term="%2$s" />', esc_attr( apply_filters( 'get_bloginfo_rss', get_bloginfo( 'url' ) ) ), esc_attr( $cat_name ) ); |
326 | else |
327 | $the_list .= "\t\t<category><![CDATA[" . @html_entity_decode( $cat_name, ENT_COMPAT, get_option('blog_charset') ) . "]]></category>\n"; |
328 | } |
329 | |
330 | return apply_filters('the_category_rss', $the_list, $type); |
331 | } |
332 | |
333 | /** |
334 | * Display the post categories in the feed. |
335 | * |
336 | * @package WordPress |
337 | * @subpackage Feed |
338 | * @since 0.71 |
339 | * @see get_the_category_rss() For better explanation. |
340 | * |
341 | * @param string $type Optional, default is the type returned by get_default_feed(). |
342 | */ |
343 | function the_category_rss($type = null) { |
344 | echo get_the_category_rss($type); |
345 | } |
346 | |
347 | /** |
348 | * Display the HTML type based on the blog setting. |
349 | * |
350 | * The two possible values are either 'xhtml' or 'html'. |
351 | * |
352 | * @package WordPress |
353 | * @subpackage Feed |
354 | * @since 2.2.0 |
355 | */ |
356 | function html_type_rss() { |
357 | $type = get_bloginfo('html_type'); |
358 | if (strpos($type, 'xhtml') !== false) |
359 | $type = 'xhtml'; |
360 | else |
361 | $type = 'html'; |
362 | echo $type; | //Cross Site Scripting
|
363 | } |
364 | |
365 | /** |
366 | * Display the rss enclosure for the current post. |
367 | * |
368 | * Uses the global $post to check whether the post requires a password and if |
369 | * the user has the password for the post. If not then it will return before |
370 | * displaying. |
371 | * |
372 | * Also uses the function get_post_custom() to get the post's 'enclosure' |
373 | * metadata field and parses the value to display the enclosure(s). The |
374 | * enclosure(s) consist of enclosure HTML tag(s) with a URI and other |
375 | * attributes. |
376 | * |
377 | * @package WordPress |
378 | * @subpackage Template |
379 | * @since 1.5.0 |
380 | * @uses apply_filters() Calls 'rss_enclosure' hook on rss enclosure. |
381 | * @uses get_post_custom() To get the current post enclosure metadata. |
382 | */ |
383 | function rss_enclosure() { |
384 | if ( post_password_required() ) |
385 | return; |
386 | |
387 | foreach ( (array) get_post_custom() as $key => $val) { |
388 | if ($key == 'enclosure') { |
389 | foreach ( (array) $val as $enc ) { |
390 | $enclosure = explode("\n", $enc); |
391 | |
392 | //only get the the first element eg, audio/mpeg from 'audio/mpeg mpga mp2 mp3' |
393 | $t = preg_split('/[ \t]/', trim($enclosure[2]) ); |
394 | $type = $t[0]; |
395 | |
396 | echo apply_filters('rss_enclosure', '<enclosure url="' . trim(htmlspecialchars($enclosure[0])) . '" length="' . trim($enclosure[1]) . '" type="' . $type . '" />' . "\n"); |
397 | } |
398 | } |
399 | } |
400 | } |
401 | |
402 | /** |
403 | * Display the atom enclosure for the current post. |
404 | * |
405 | * Uses the global $post to check whether the post requires a password and if |
406 | * the user has the password for the post. If not then it will return before |
407 | * displaying. |
408 | * |
409 | * Also uses the function get_post_custom() to get the post's 'enclosure' |
410 | * metadata field and parses the value to display the enclosure(s). The |
411 | * enclosure(s) consist of link HTML tag(s) with a URI and other attributes. |
412 | * |
413 | * @package WordPress |
414 | * @subpackage Template |
415 | * @since 2.2.0 |
416 | * @uses apply_filters() Calls 'atom_enclosure' hook on atom enclosure. |
417 | * @uses get_post_custom() To get the current post enclosure metadata. |
418 | */ |
419 | function atom_enclosure() { |
420 | if ( post_password_required() ) |
421 | return; |
422 | |
423 | foreach ( (array) get_post_custom() as $key => $val ) { |
424 | if ($key == 'enclosure') { |
425 | foreach ( (array) $val as $enc ) { |
426 | $enclosure = split("\n", $enc); |
427 | echo apply_filters('atom_enclosure', '<link href="' . trim(htmlspecialchars($enclosure[0])) . '" rel="enclosure" length="' . trim($enclosure[1]) . '" type="' . trim($enclosure[2]) . '" />' . "\n"); |
428 | } |
429 | } |
430 | } |
431 | } |
432 | |
433 | /** |
434 | * Determine the type of a string of data with the data formatted. |
435 | * |
436 | * Tell whether the type is text, html, or xhtml, per RFC 4287 section 3.1. |
437 | * |
438 | * In the case of WordPress, text is defined as containing no markup, |
439 | * xhtml is defined as "well formed", and html as tag soup (i.e., the rest). |
440 | * |
441 | * Container div tags are added to xhtml values, per section 3.1.1.3. |
442 | * |
443 | * @link http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rfc.section.3.1 |
444 | * |
445 | * @package WordPress |
446 | * @subpackage Feed |
447 | * @since 2.5 |
448 | * |
449 | * @param string $data Input string |
450 | * @return array array(type, value) |
451 | */ |
452 | function prep_atom_text_construct($data) { |
453 | if (strpos($data, '<') === false && strpos($data, '&') === false) { |
454 | return array('text', $data); |
455 | } |
456 | |
457 | $parser = xml_parser_create(); |
458 | xml_parse($parser, '<div>' . $data . '</div>', true); |
459 | $code = xml_get_error_code($parser); |
460 | xml_parser_free($parser); |
461 | |
462 | if (!$code) { |
463 | if (strpos($data, '<') === false) { |
464 | return array('text', $data); |
465 | } else { |
466 | $data = "<div xmlns='http://www.w3.org/1999/xhtml'>$data</div>"; |
467 | return array('xhtml', $data); |
468 | } |
469 | } |
470 | |
471 | if (strpos($data, ']]>') == false) { |
472 | return array('html', "<![CDATA[$data]]>"); |
473 | } else { |
474 | return array('html', htmlspecialchars($data)); |
475 | } |
476 | } |
477 | |
478 | /** |
479 | * Display the link for the currently displayed feed in a XSS safe way. |
480 | * |
481 | * Generate a correct link for the atom:self element. |
482 | * |
483 | * @package WordPress |
484 | * @subpackage Feed |
485 | * @since 2.5 |
486 | */ |
487 | function self_link() { |
488 | $host = @parse_url(home_url()); |
489 | $host = $host['host']; |
490 | echo esc_url( |
491 | 'http' |
492 | . ( (isset($_SERVER['https']) && $_SERVER['https'] == 'on') ? 's' : '' ) . '://' |
493 | . $host |
494 | . stripslashes($_SERVER['REQUEST_URI']) |
495 | ); |
496 | } |
497 | |
498 | /** |
499 | * Return the content type for specified feed type. |
500 | * |
501 | * @package WordPress |
502 | * @subpackage Feed |
503 | * @since 2.8.0 |
504 | */ |
505 | function feed_content_type( $type = '' ) { |
506 | if ( empty($type) ) |
507 | $type = get_default_feed(); |
508 | |
509 | $types = array( |
510 | 'rss' => 'application/rss+xml', |
511 | 'rss2' => 'application/rss+xml', |
512 | 'rss-http' => 'text/xml', |
513 | 'atom' => 'application/atom+xml', |
514 | 'rdf' => 'application/rdf+xml' |
515 | ); |
516 | |
517 | $content_type = ( !empty($types[$type]) ) ? $types[$type] : 'application/octet-stream'; |
518 | |
519 | return apply_filters( 'feed_content_type', $content_type, $type ); |
520 | } |
521 | |
522 | /** |
523 | * Build SimplePie object based on RSS or Atom feed from URL. |
524 | * |
525 | * @since 2.8 |
526 | * |
527 | * @param string $url URL to retrieve feed |
528 | * @return WP_Error|SimplePie WP_Error object on failure or SimplePie object on success |
529 | */ |
530 | function fetch_feed($url) { |
531 | require_once (ABSPATH . WPINC . '/class-feed.php'); |
532 | |
533 | $feed = new SimplePie(); |
534 | $feed->set_feed_url($url); |
535 | $feed->set_cache_class('WP_Feed_Cache'); |
536 | $feed->set_file_class('WP_SimplePie_File'); |
537 | $feed->set_cache_duration(apply_filters('wp_feed_cache_transient_lifetime', 43200, $url)); |
538 | do_action_ref_array( 'wp_feed_options', array( &$feed, $url ) ); |
539 | $feed->init(); |
540 | $feed->handle_content_type(); |
541 | |
542 | if ( $feed->error() ) |
543 | return new WP_Error('simplepie-error', $feed->error()); |
544 | |
545 | return $feed; |
546 | } |
547 | |