Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ads.txt file exists check from backend side #131

Conversation

sksaju
Copy link
Member

@sksaju sksaju commented Mar 6, 2023

Description of the Change

This PR fixes the #48 issue, by adding ads.txt file check from the backend side

Closes #

How to test the Change

  • Put an ads.txt in the root of a MS instance
  • Set up domain mapping for a subsite
  • Go to the ads.txt edit screen on the subsite
  • See notice that an existing ads.txt file was found

Changelog Entry

Added - ads.txt file exists check from backend side

Credits

Props @sksaju, @mmcachran, @peterwilsoncc, @dinhtungdu, @helen, @jeffpaul.

Checklist:

  • I agree to follow this project's Code of Conduct.
  • I have updated the documentation accordingly.
  • I have added tests to cover my change.
  • All new and existing tests pass.

@jeffpaul jeffpaul added this to the 1.5.0 milestone Mar 6, 2023
@jeffpaul jeffpaul linked an issue Mar 6, 2023 that may be closed by this pull request
inc/admin.php Outdated
@@ -269,6 +269,14 @@ function settings_screen( $post_id, $strings, $args ) {
}
?>
<div class="wrap">
<?php if ( file_exists( ABSPATH . '/ads.txt' ) ) { ?>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check won't work I'm afraid.

ABSPATH points to the directory of the WordPress install, which isn't necessarily the same as the root directory of the website. See this guide for running wordpress in a subdirectory.

To use my site as an example, this would check for /path/to/files/wp/ads.txt rather than /path/to/files/ads.txt.

I think there would be some weirdness around multisite installs too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that makes sense, I'll try to fix the issue

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a quick comment with some pseudo code on the original issue #48 (comment)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@peterwilsoncc I'm trying to check the file following your suggestions but somehow when I try to get the file via wp_remote_request request I'm getting empty headers data, I've pushed the latest changes on this branch, could you take a look, please? Thanks

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unable to reproduce an error with empty headers, this is what I am seeing in xdebug using the file_exists line as a break point.

Screen Shot 2023-04-03 at 1 49 55 pm

Copy link
Member Author

@sksaju sksaju Apr 26, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @peterwilsoncc I was able to test header data today

This is the header response from ads.txt file
Screenshot 2023-04-26 at 8 56 17 PM

and this from adstxt post type
Screenshot 2023-04-26 at 8 56 30 PM

Can we check the file with the Content-Length and/or ETag properties as these are not present in the post-type response? although I don't have much experience with online server file systems, I think these might help to differentiate between file response and post-type response! please let me know your feedback. Thanks

@jeffpaul
Copy link
Member

@sksaju there appears to be a merge conflict, mind resolving that and letting us know if this is ready for re-review? Thanks!

@jeffpaul
Copy link
Member

@peterwilsoncc back to you for review here

Copy link
Contributor

@peterwilsoncc peterwilsoncc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added some notes inline. I'm not sure why the E2E tests are failing.

inc/admin.php Outdated
Comment on lines 530 to 533
// Get the headers of the response
$headers = wp_remote_retrieve_headers( $response );
$content_type = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
$file_exist = strpos( $content_type, 'application/octet-stream' ) !== false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While testing, I was getting a false report here (I had an ads.txt file but it wasn't detected).

How about the adding header( 'X-Ads-Txt-Generator: https://wordpress.org/plugins/ads-txt/' ); to the output in the main file (both for ads.txt and for app-ads.txt) and then checking for the header:

Suggested change
// Get the headers of the response
$headers = wp_remote_retrieve_headers( $response );
$content_type = isset( $headers['content-type'] ) ? $headers['content-type'] : '';
$file_exist = strpos( $content_type, 'application/octet-stream' ) !== false;
// Check the ads.txt generator header.
$headers = wp_remote_retrieve_headers( $response );
$generator = isset( $headers['X-Ads-Txt-Generator'] ) ? $headers['X-Ads-Txt-Generator'] : '';
$file_exist = 'https://wordpress.org/plugins/ads-txt/' !== $generator;

The generator header would need to be included regardless of whether the post exists or not, so probably right after the get_option() check in each block.

inc/admin.php Outdated
function adstxts_check_for_existing_file() {
$home_url_parsed = wp_parse_url( home_url() );
if ( empty( $home_url_parsed['path'] ) ) {
$response = wp_remote_request( home_url( '/ads.txt' ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need something here (and in the JS) to determine whether the check should be for ads.txt or app-ads.txt .

You can probably include something in the admin_enqueue_scripts() function within this file based on the hook -- whether it contains app-adstxt or not.

To be secure you should send it in the form is_appstxt: true|false and modify the URL check based on the true false statement. Don't use the variable home_url( $passed_value ) as someone could modify that to a random file name, such as .env or similar.

* @return void
*/
function adstxts_check_for_existing_file() {
$home_url_parsed = wp_parse_url( home_url() );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Security: This will need both a nonce and a capability check, similar to that used in the save function:

ads-txt/inc/save.php

Lines 19 to 20 in dc18245

current_user_can( ADS_TXT_MANAGE_CAPABILITY ) || die;
check_admin_referer( 'adstxt_save' );

Comment on lines +543 to +545

// Make sure to exit
wp_die();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wp_send_json() exits.

Suggested change
// Make sure to exit
wp_die();

Comment on lines +275 to +280
<div class="notice notice-error adstxt-notice existing-adstxt" style="display: none;">
<p><strong><?php echo esc_html( $strings['existing'] ); ?></strong></p>
<p><?php echo esc_html( $strings['precedence'] ); ?></p>

<p><?php echo esc_html_e( 'Removed the existing file but are still seeing this warning?', 'ads-txt' ); ?> <a class="ads-txt-rerun-check" href="#"><?php echo esc_html_e( 'Re-run the check now', 'ads-txt' ); ?></a> <span class="spinner" style="float:none;margin:-2px 5px 0"></span></p>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow up: it's the presence of this that is causing the tests to fail. I pushed a fix in 5d9f27d

Copy link
Contributor

@peterwilsoncc peterwilsoncc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me, thank you for your patience during the review process.

Testing notes:

  • identical content in a real file and the generated version show the warning
  • different content in a real file and the generated version show the warning
  • the generated file includes the custom header
  • file not found errors include the custom header
  • accounts for built in Multisite domain mapping

@peterwilsoncc peterwilsoncc merged commit da31148 into develop Jun 5, 2023
@peterwilsoncc peterwilsoncc deleted the fix/adstxt-file-detection-does-not-take-mapped-domains-into-account branch June 5, 2023 01:50
@dkotter dkotter modified the milestones: 1.5.0, 1.4.3 Jun 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ads.txt file detection does not take mapped domains into account
4 participants