RSS WordPress SimplePie claiming valid URL as invalid - wordpress

I'm trying to load a RSS feed with Wordpress's built-in SimplePie.
include_once(ABSPATH . WPINC . '/feed.php');
$rssURL = 'http://missionstkitts.blogspot.com//feeds/posts/default';
$rss = fetch_feed($rssURL);
To debug, I used print_r($rss); and I get a WordPress error object:
WP_Error Object
(
[errors] => Array
(
[simplepie-error] => Array
(
[0] => WP HTTP Error: A valid URL was not provided.
)
)
[error_data] => Array
(
)
)
But, frustratingly, if I print $rssURL and then copy and paste it it goes straight to the correct feed. What is going on?

Since this is the first hit in google, probably worth me adding this possible solution:
For our instance - an intranet site, pulling an rss feed from another internal page, which in-turn resolves to an RFC1918 private address the feed was being blocked by Wordpress's URL checker for security reasons.
The easiest fix in my instance was to add the following to functions.php, but this does have security implications so be sure you understand it before you add it:
add_filter( 'http_request_args', function( $args ) {
$args['reject_unsafe_urls'] = false;
return $args;
} );
Further discussion and more information at - https://core.trac.wordpress.org/ticket/24646

By adding preg_match for specific urls we can minimize the amount of parsed unsafed urls:
function http_request_local( $args, $url ) {
if ( preg_match('/xml|rss|feed/', $url) ){
$args['reject_unsafe_urls'] = false;
}
return $args;
}
add_filter( 'http_request_args', 'http_request_local', 5, 2 );

So, while the above answers work, I think that there's a way to do this that is better to make sure that you're limiting the scope of where you're making the URL request to instead of allowing everything to go. So I'm proving the following information to anyone who stumbles across this just in case it helps.
This answer is useful if the resulting calls are to internal servers cross-communicating on private IPs but are still publicly accessible.
The snippet below is to be run on the site that's calling the RSS feed. The site that is providing the feed does not need this.
add_filter('http_request_host_is_external', function($bool, $host, $url){
if($url === 'https://www.example.com/news/feed/' && $host === 'www.example.com'){
return true;
}
}, 10, 3);

Related

Wordpress function cannot call submit_button() as it ends with "undefinied function"

i am a real very newbie in coding and in Wordpress. Trying my first test plugin to understand basics. I am able to define plugin, register it, so I can see it in plugins, activate it.
My later goal is to be able to create custom form, save user-specific data to new DB table, and then enable reading/editing it.
I tried to follow the instructions from gmazzap placed here: https://wordpress.stackexchange.com/questions/113936/simple-form-that-saves-to-database
I just am having following error from WP in time of trying to display preview of new screen having a shortcode [userform] in it:
*Fatal error: Uncaught Error: Call to undefined function submit_button() in /data/web/virtuals/131178/virtual/www/subdom/test/system/wp-content/themes/twentytwentythree-child/functions.php:14
*
My functions.php of my theme now looks like this:
<?php
add_action('init', function() {
add_shortcode('userform', 'print_user_form');
});
function print_user_form() {
echo '<form method="POST">';
wp_nonce_field('user_info', 'user_info_nonce', true, true);
?>
All your form inputs (name, email, phone) goes here.
<?php
submit_button('Send Data');
echo '</form>';
}
add_action('template_redirect', function() {
if ( ( is_single() || is_page() ) &&
isset($_POST['user_info_nonce']) &&
wp_verify_nonce($_POST['user_info_nonce'], 'user_info')
) {
// you should do the validation before save data in db.
// I will not write the validation function, is out of scope of this answer
$pass_validation = validate_user_data($_POST);
if ( $pass_validation ) {
$data = array(
'name' => $_POST['name'],
'email' => $_POST['email'],
'phone' => $_POST['phone'],
);
global $wpdb;
// if you have followed my suggestion to name your table using wordpress prefix
$table_name = $wpdb->prefix . 'my_custom_table';
// next line will insert the data
$wpdb->insert($table_name, $data, '%s');
// if you want to retrieve the ID value for the just inserted row use
$rowid = $wpdb->insert_id;
// after we insert we have to redirect user
// I sugest you to cretae another page and title it "Thank You"
// if you do so:
$redirect_page = get_page_by_title('Thank You') ? : get_queried_object();
// previous line if page titled 'Thank You' is not found set the current page
// as the redirection page. Next line get the url of redirect page:
$redirect_url = get_permalink( $redirect_page );
// now redirect
wp_safe_redirect( $redirect_url );
// and stop php
exit();
}
}
});
Note: I have not got to DB exercise, point of my question is submit_button.
As indicated in the error, the code on line 1 points to non identified function:
submit_button('Send Data');
I understood from other discussions submit_button should be core function of WP, so I should be able to call it "directly", without the need of a definition.
I tried following:
originally had very similar code within the plugin, moved to functions.php
reinstalled core of WordPress version 6.1.1
tried several different Themes (as it looked this worked for other users, I tried "classic" and "twentytwentythree" )
And still no little step further, still having same issue with error described above. What I am doing wrong?
If someone would confirm this is WP core installation issue, I am ready to reinstall WP from scratch, just trying to save some time, if there might be other cause.
Thank you for any suggestions.

Headless Wordpress, Is there a way to access data in wp_options table as REST endpoint?

Wordpress has an awesome REST API interface.
https://developer.wordpress.org/rest-api/reference/
But the content in wp_options table seems to be missing REST support. Is there a way to access the content in wp_otions table as REST endpoint via plugins?. Thanks.
There is the settings endpoint, but it only contains a surprisingly limited amount of them it seems.
This is something you could very easily do yourself though. I'm not sure if any plugins do it, but I also wouldn't recommend a plugin for something that can be done with less than 20 lines of code.
You just need to register a route using register_rest_route() on the rest_api_init hook, and pass it a callback function. You can drop code like this in your functions.php file or create a Must Use Plugin and drop the code in there, either way.
add_action( 'rest_api_init', function () {
register_rest_route( 'my-custom-route/v1', '/opt/', array(
'methods' => 'GET',
'callback' => 'get_rest_option',
//'permission_callback' => function () {
// return current_user_can( 'administrator' );
//}
) );
} );
function get_rest_option( $data ) {
return get_option( $data['option_name'] );
}
The above will give you access to whatever option you want by accessing:
/wp-json/my-custom-route/v1/opt/?option_name=siteurl
I went ahead and dropped an example on a site of mine:
https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=blogname
https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=siteurl
However, this will potentially expose anything in your options table. I went ahead and commented out the permission_callback so that any person, signed in or not, can access it. However, I also added a check like this:
function get_rest_option( $data ) {
if( $data['option_name'] === 'siteurl' || $data['option_name'] === 'blogname' ){
return get_option( $data['option_name'] );
} else {
return 'Unauthorized. Use `siteurl` or `blogname`';
}
}
You can see that home will fail: https://xhynk.com/content-mask/wp-json/my-custom-route/v1/opt/?option_name=home
I would recommend adding in a valid array of options, or using the permission_callback in order to lock it down a bit. You could even have an access key instead, and keep that key secret. Either way, be aware of the security implications of exposing your entire wp_options table, and take some sort of preventative measure!

WP Rest API get post by slug with special characters (ex: !&')

I have posts with slugs with special characters. One of them is the following:
http://localhost/wp-json/wp/v2/posts?slug=my-post!
Unfortunately, WP REST API not showing the content since it has (!) within the slug.
Is there any solution you guys would recommend?
I have found the solution (at least for my case), not sure if it'll work for you but may indicate you the way to go. We need to tap into the function used to sanitize the slugs, as I said in my comment, by default is wp_parse_slug_list. Looking at the code the function that actually sanitizes the slug is sanitize_title.
Looking at the source code, wp_parse_slug_list calls sanitize_title with only one argument, which means that the context used is save. This means that, for posts that were already saved without being sanitized by this function, the slug won't match and the post will be inaccessible through the API. The solution is to change the sanitizing function slightly by adding a filter:
add_filter('rest_post_collection_params', function($query_params) {
$query_params['slug']['sanitize_callback'] = 'sanitize_rest_api_slug';
return $query_params;
}, 20, 1);
function sanitize_rest_api_slug( $list ) {
if ( ! is_array( $list ) ) {
$list = preg_split( '/[\s,]+/', $list );
}
foreach ( $list as $key => $value ) {
$list[ $key ] = sanitize_title( $value, '', 'query' );
}
return array_unique( $list );
}
The filter is actually being applied on the function get_collection_params() on the class-wp-rest-posts-controller class, but if you look at the source code, the filter has a variable depending on the post_type, so if you have another special kind of posts defined (besides post) you need to add/change a filter for that kind as well.
I hope this helps somebody else like me, even if it's too late for your issue.

How to correctly add meta values as search keys using Wordpress REST API?

I currently have this a meta fields that are registered to the post, and another post type.
I was able to register the metafields correctly and I am able to do a POST for me articles through REST API.
What I am trying to figure out now is how can I add the meta key fields as search keys when I try to do a GET request through the rest API.
I searched through google but I am getting outdated resources.
I currently have this code:
$this->post_types = array ( 'post', 'events' );
foreach( $this->post_types as $field ) {
add_filter("rest_" . $field . "_query", function ($args, $query) {
$args["meta_query"] = "event_id";
$args["meta_query"] = "event_date";
return $args;
}, 10, 2);
}
But when I try to search using: /wp-json/wp/v2/events?filter[meta_query][event_id]=15432 I am getting incorrect results.
Is there something in my code that I missed? Thanks in advance for any help.

Hide WordPress Rest API endpoints definition

I want to hide the definition of endpoints in a WordPress rest api... in the case of https://www.wpwhitesecurity.com/wp-json I want to return a 404 or an empty array, but not the list of endpoints of the site.
Some idea?
Thanks!
From version 4.4.0 exists the hook rest_index, the documentation in https://developer.wordpress.org/reference/hooks/rest_index/ describes :
This contains the data describing the API. This includes information
about supported authentication schemes, supported namespaces, routes
available on the API, and a small amount of data about the site.
The next code is working perfectly as I needed :
function my_site_rest_index( $response ){
return array();
}
add_filter('rest_index', 'my_site_rest_index');
function chuck_disable_rest_endpoints( $access ) {
if( ! is_user_logged_in() ) {
return new WP_Error( 'rest_cannot_access', __( 'Only logged users are able to call REST API.', 'disable-json-api' ), array( 'status' => rest_authorization_required_code() ) );
}return $access;
}
add_filter( 'rest_authentication_errors', 'chuck_disable_rest_endpoints' );
This will return that only logged users can access to API

Resources