Skip to content

Commit 895203b

Browse files
committed
Feeds: Don't attempt to generate RSS feeds for invalid feed URLs such as wp-content/feed.
Props stevenkword, JRGould, lyubomir_popov, johnbillion Fixes #30210 git-svn-id: https://develop.svn.wordpress.org/trunk@38929 602fd350-edb4-49c9-b593-d223f7449a82
1 parent ad25902 commit 895203b

2 files changed

Lines changed: 232 additions & 3 deletions

File tree

src/wp-includes/functions.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1213,6 +1213,18 @@ function bool_from_yn( $yn ) {
12131213
function do_feed() {
12141214
global $wp_query;
12151215

1216+
// Determine if we are looking at the main comment feed
1217+
$is_main_comments_feed = ( $wp_query->is_comment_feed() && ! $wp_query->is_singular() );
1218+
1219+
/*
1220+
* Check the queried object for the existence of posts if it is not a feed for an archive,
1221+
* search result, or main comments. By checking for the absense of posts we can prevent rendering the feed
1222+
* templates at invalid endpoints. e.g.) /wp-content/plugins/feed/
1223+
*/
1224+
if ( ! $wp_query->have_posts() && ! ( $wp_query->is_archive() || $wp_query->is_search() || $is_main_comments_feed ) ) {
1225+
wp_die( __( 'ERROR: This is not a valid feed.' ), '', array( 'response' => 404 ) );
1226+
}
1227+
12161228
$feed = get_query_var( 'feed' );
12171229

12181230
// Remove the pad, if present.

tests/phpunit/tests/feed/rss2.php

Lines changed: 220 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Tests_Feeds_RSS2 extends WP_UnitTestCase {
1212
static $user_id;
1313
static $posts;
1414
static $category;
15+
static $post_date;
1516

1617
/**
1718
* Setup a new user and attribute some posts.
@@ -25,16 +26,20 @@ public static function wpSetUpBeforeClass( $factory ) {
2526
) );
2627

2728
// Create a taxonomy
28-
self::$category = self::factory()->category->create_and_get( array(
29-
'name' => 'Test Category',
30-
'slug' => 'test-cat',
29+
self::$category = $factory->category->create_and_get( array(
30+
'name' => 'Foo Category',
31+
'slug' => 'foo',
3132
) );
3233

34+
// Set a predictable time for testing date archives.
35+
self::$post_date = '2003-05-27 10:07:53';
36+
3337
$count = get_option( 'posts_per_rss' ) + 1;
3438

3539
// Create a few posts
3640
self::$posts = $factory->post->create_many( $count, array(
3741
'post_author' => self::$user_id,
42+
'post_date' => self::$post_date,
3843
'post_content' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec velit massa, ultrices eu est suscipit, mattis posuere est. Donec vitae purus lacus. Cras vitae odio odio.',
3944
'post_excerpt' => 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
4045
) );
@@ -55,6 +60,9 @@ public function setUp() {
5560
$this->excerpt_only = get_option( 'rss_use_excerpt' );
5661
// this seems to break something
5762
update_option( 'use_smilies', false );
63+
64+
$this->set_permalink_structure( '/%year%/%monthnum%/%day%/%postname%/' );
65+
create_initial_taxonomies();
5866
}
5967

6068
/**
@@ -250,4 +258,213 @@ function test_items_comments_closed() {
250258
remove_filter( 'comments_open', '__return_false' );
251259
}
252260

261+
/*
262+
* Check to make sure we are rendering feed templates for the home feed.
263+
* e.g. https://example.com/feed/
264+
*
265+
* @ticket 30210
266+
*/
267+
function test_valid_home_feed_endpoint() {
268+
// An example of a valid home feed endpoint.
269+
$this->go_to( 'feed/' );
270+
271+
// Verify the query object is a feed.
272+
$this->assertQueryTrue( 'is_feed' );
273+
274+
// Queries performed on valid feed endpoints should contain posts.
275+
$this->assertTrue( have_posts() );
276+
277+
// Check to see if we have the expected XML output from the feed template.
278+
$feed = $this->do_rss2();
279+
280+
$xml = xml_to_array( $feed );
281+
282+
// Get the <rss> child element of <xml>.
283+
$rss = xml_find( $xml, 'rss' );
284+
285+
// There should only be one <rss> child element.
286+
$this->assertEquals( 1, count( $rss ) );
287+
}
288+
289+
/*
290+
* Check to make sure we are rendering feed templates for the taxonomy feeds.
291+
* e.g. https://example.com/category/foo/feed/
292+
*
293+
* @ticket 30210
294+
*/
295+
function test_valid_taxonomy_feed_endpoint() {
296+
// An example of an valid taxonomy feed endpoint.
297+
$this->go_to( 'category/foo/feed/' );
298+
299+
// Verify the query object is a feed.
300+
$this->assertQueryTrue( 'is_feed', 'is_archive', 'is_category' );
301+
302+
// Queries performed on valid feed endpoints should contain posts.
303+
$this->assertTrue( have_posts() );
304+
305+
// Check to see if we have the expected XML output from the feed template.
306+
$feed = $this->do_rss2();
307+
308+
$xml = xml_to_array( $feed );
309+
310+
// Get the <rss> child element of <xml>.
311+
$rss = xml_find( $xml, 'rss' );
312+
313+
// There should only be one <rss> child element.
314+
$this->assertEquals( 1, count( $rss ) );
315+
}
316+
317+
/*
318+
* Check to make sure we are rendering feed templates for the main comment feed.
319+
* e.g. https://example.com/comments/feed/
320+
*
321+
* @ticket 30210
322+
*/
323+
function test_valid_main_comment_feed_endpoint() {
324+
// Generate a bunch of comments
325+
foreach ( self::$posts as $post ) {
326+
self::factory()->comment->create_post_comments( $post, 3 );
327+
}
328+
329+
// An example of an valid main comment feed endpoint.
330+
$this->go_to( 'comments/feed/' );
331+
332+
// Verify the query object is a feed.
333+
$this->assertQueryTrue( 'is_feed', 'is_comment_feed' );
334+
335+
// Queries performed on valid feed endpoints should contain comments.
336+
$this->assertTrue( have_comments() );
337+
338+
// Check to see if we have the expected XML output from the feed template.
339+
$feed = $this->do_rss2();
340+
341+
$xml = xml_to_array( $feed );
342+
343+
// Get the <rss> child element of <xml>.
344+
$rss = xml_find( $xml, 'rss' );
345+
346+
// There should only be one <rss> child element.
347+
$this->assertEquals( 1, count( $rss ) );
348+
}
349+
350+
/*
351+
* Check to make sure we are rendering feed templates for the date archive feeds.
352+
* e.g. https://example.com/2003/05/27/feed/
353+
*
354+
* @ticket 30210
355+
*/
356+
function test_valid_archive_feed_endpoint() {
357+
// An example of an valid date archive feed endpoint.
358+
$this->go_to( '2003/05/27/feed/' );
359+
360+
// Verify the query object is a feed.
361+
$this->assertQueryTrue( 'is_feed', 'is_archive', 'is_day', 'is_date' );
362+
363+
// Queries performed on valid feed endpoints should contain posts.
364+
$this->assertTrue( have_posts() );
365+
366+
// Check to see if we have the expected XML output from the feed template.
367+
$feed = $this->do_rss2();
368+
369+
$xml = xml_to_array( $feed );
370+
371+
// Get the <rss> child element of <xml>.
372+
$rss = xml_find( $xml, 'rss' );
373+
374+
// There should only be one <rss> child element.
375+
$this->assertEquals( 1, count( $rss ) );
376+
}
377+
378+
/*
379+
* Check to make sure we are rendering feed templates for single post comment feeds.
380+
* e.g. https://example.com/2003/05/27/post-name/feed/
381+
*
382+
* @ticket 30210
383+
*/
384+
function test_valid_single_post_comment_feed_endpoint() {
385+
// An example of an valid date archive feed endpoint.
386+
$this->go_to( get_post_comments_feed_link( self::$posts[0] ) );
387+
388+
// Verify the query object is a feed.
389+
$this->assertQueryTrue( 'is_feed', 'is_comment_feed', 'is_single', 'is_singular' );
390+
391+
// Queries performed on valid feed endpoints should contain posts.
392+
$this->assertTrue( have_posts() );
393+
394+
// Check to see if we have the expected XML output from the feed template.
395+
$feed = $this->do_rss2();
396+
397+
$xml = xml_to_array( $feed );
398+
399+
// Get the <rss> child element of <xml>.
400+
$rss = xml_find( $xml, 'rss' );
401+
402+
// There should only be one <rss> child element.
403+
$this->assertEquals( 1, count( $rss ) );
404+
}
405+
406+
/*
407+
* Check to make sure we are rendering feed templates for the search archive feeds.
408+
* e.g. https://example.com/?s=Lorem&feed=rss
409+
*
410+
* @ticket 30210
411+
*/
412+
function test_valid_search_feed_endpoint() {
413+
// An example of an valid search feed endpoint
414+
$this->go_to( '?s=Lorem&feed=rss' );
415+
416+
// Verify the query object is a feed.
417+
$this->assertQueryTrue( 'is_feed', 'is_search' );
418+
419+
// Queries performed on valid feed endpoints should contain posts.
420+
$this->assertTrue( have_posts() );
421+
422+
// Check to see if we have the expected XML output from the feed template.
423+
$feed = $this->do_rss2();
424+
425+
$xml = xml_to_array( $feed );
426+
427+
// Get the <rss> child element of <xml>.
428+
$rss = xml_find( $xml, 'rss' );
429+
430+
// There should only be one <rss> child element.
431+
$this->assertEquals( 1, count( $rss ) );
432+
}
433+
434+
/*
435+
* Check to make sure we are not rendering feed templates for invalid feed endpoints.
436+
* e.g. https://example.com/wp-content/feed/
437+
*
438+
* @ticket 30210
439+
*/
440+
function test_invalid_feed_endpoint() {
441+
// An example of an invalid feed endpoint
442+
$this->go_to( 'wp-content/feed/' );
443+
444+
// Queries performed on invalid feed endpoints should never contain posts.
445+
$this->assertFalse( have_posts() );
446+
447+
// This is the assertion. Once the exception is thrown in do_feed, execution stops, preventing futher assertions.
448+
$this->setExpectedException( 'WPDieException', 'ERROR: This is not a valid feed.' );
449+
do_feed();
450+
}
451+
452+
/*
453+
* Make sure the requested feed is registered before rendering the requested template.
454+
*
455+
* @ticket 30210
456+
*/
457+
function test_nonexistent_feeds() {
458+
global $wp_rewrite;
459+
$badfeed = 'badfeed';
460+
461+
$this->assertNotContains( $badfeed, $wp_rewrite->feeds );
462+
463+
$this->go_to( '/?feed=' . $badfeed );
464+
465+
// This is the assertion. Once the exception is thrown in do_feed, execution stops, preventing futher assertions.
466+
$this->setExpectedException( 'WPDieException', 'ERROR: This is not a valid feed template.' );
467+
do_feed();
468+
}
469+
253470
}

0 commit comments

Comments
 (0)