janboddez / share-on-mastodon

Easily share WordPress posts on Mastodon.
https://jan.boddez.net/wordpress/share-on-mastodon
GNU General Public License v3.0
39 stars 5 forks source link

Less strict URL input field? #46

Closed janboddez closed 1 year ago

janboddez commented 1 year ago

See https://wordpress.org/support/topic/poor-at-detecting-valid-urls/

Works for me, though: image

janboddez commented 1 year ago

We could accept text input rather than a URL, and, if needed, add the https:// server-side

KevinGimbel commented 1 year ago

Hey there! What is the format supposed to be? I tried setting up the plugin but it won't allow my Mastodon instance URL which is on.nerdcultu.re - it always says its an invalid URL no matter if I add http://, https://, or leave it empty.

janboddez commented 1 year ago

@KevinGimbel Is this in your browser, i.e., the browser's built-in URL validation? Or do you get the error after having submitted the form?

KevinGimbel commented 1 year ago

After submitting the form the error shows

janboddez commented 1 year ago

@KevinGimbel So, in your case, it should be https://on.nerdcultu.re.

If server-side validation fails, that would indicate WordPress core's wp_http_validate_url() (whose purpose is to "validate a URL for safe use in the HTTP API," which is what we use to call Mastodon's API) can somehow not handle it.

Now this function is a lot more strict than, e.g., PHP's filter_var(). Looking at its source code, it seems that, e.g., it calls gethostbyname() and then returns false if that fails. And so on.

One thing you could try is replace this line with if ( true ) {, for instance, see if it then works. If so, the function was clearly too strict (for whatever reason, figuring out exactly why would take a few more steps ...): https://github.com/janboddez/share-on-mastodon/blob/336ee87ff001edeee335e51379e107c3ce4658a6/includes/class-options-handler.php#L128

The issue is changes like this get overwritten with each plugin update, and I can't just not validate the URL because that would potentially open up the plugin to vulnerabilities. But we could try and find an alternative for WordPress's built-in URL validation.

If it still doesn't work, clearly WordPress's HTTP functions really can't connect to your instance's API and we have a different problem.

KevinGimbel commented 1 year ago

@janboddez with the changes you suggested it works.

Before that even if I used https://on.nerdcultu.re/ as URL it wasn't working. 🤔

I understand that validation is needed, maybe using another validation function could solve the problem. It seems the WordPress one is too strict or falsely.

janboddez commented 1 year ago

@KevinGimbel Are you also able to actually syndicate to your Mastodon instance? I mean, does the plugin do what it is supposed to do?

Looking at wp_http_validate_url(), it could be one of several checks that fail. There's also this comment in its source that might have to do with it:

// If host appears local, reject unless specifically allowed.

Since you're on a subdomain, I guess PHP could somehow return a local IP address, causing the check to fail.

What you could try to overcome that, is add something like this to your theme's functions.php or (better, yet) a so-called must-use plugin:

add_filter( 'http_request_host_is_external', function( $value, $host, $url ) {
  if ( 'on.nerdcultu.re' === $host ) { // I think this is how it works; hope it's clear what I'm going for here.
    return true;
  }

  return $value;
}, 10, 3 );

This change, if it works, would also survive plugin updates and is thus preferred over the other "hack." (Just a heads up: I was not able to actually test this bit of code ...)

KevinGimbel commented 1 year ago

Since you're on a subdomain, I guess PHP could somehow return a local IP address, causing the check to fail.

That's it. My WordPress site and my Mastodon instance are on the same host.

Adding your code works, thank you!

add_filter( 'http_request_host_is_external', function( $value, $host, $url ) {
  if ( 'on.nerdcultu.re' === $host ) {
    return true;
  }

  return $value;
}, 10, 3 );
janboddez commented 1 year ago

One thing some people get wrong is they add their user profile rather than the instance's base URL. We can leverage wp_parse_url() to sanitize these and atore what we expect. Something like what https://developer.wordpress.org/reference/functions/strip_fragment_from_url/ does

janboddez commented 1 year ago

Addressed in 787d931959f0b61759a8a0088dc77076391521f1.