Make WordPress Core

Opened 11 years ago

Closed 11 years ago

Last modified 11 years ago

#25294 closed defect (bug) (fixed)

Changeset 25323 causes AJAX errors in WP Admin

Reported by: needle's profile needle Owned by:
Milestone: 3.7 Priority: normal
Severity: major Version: 3.6.1
Component: General Keywords: reporter-feedback
Focuses: Cc:

Description

It seems that changeset [25323] causes "Call to undefined function wp_validate_redirect()" errors in WP Admin where AJAX is used. On my test install, widgets cannot be added, for example.

Attachments (2)

25294.diff (391 bytes) - added by nacin 11 years ago.
A patch for Hotfix that tries (but could fail) to define wp_validate_redirect() first.
25294.2.diff (518 bytes) - added by nacin 11 years ago.
A patch for core.

Download all attachments as: .zip

Change History (27)

#1 @dd32
11 years ago

  • Keywords reporter-feedback added

I'm seeing no issues with ajax requests, and adding a widget works for me under trunk.

wp_validate_redirect() is included in wp-includes/pluggable.php, and as a result, should be loaded for all requests, including admin ajax calls.

This sounds like it could be potentially plugin related (calling wp_get_referer() on inclusion for example), Can you duplicate it with a new install, or with all plugins deactivated?

#2 @needle
11 years ago

@dd32: It's frustrating because I cannot replicate this in trunk either - but I can confirm that downgrading to WP 3.6 on all sites which are affected by this removes the fatal error.

#4 @needle
11 years ago

Further investigation... @dd32, you're right, the error does seem to be due to plugins that call wp_get_referer() on init. Presumably pluggable.php is not yet included when a plugin's code is first run, which would account for the difference in behaviour. Given the number of reports of this error, it would seem that some kind of defensive measures need to be taken.

#5 @dd32
11 years ago

Calling it on the init action, or even the plugins_loaded action would be fine, but calling it before then - when a plugin is included, is not.

I was able to duplicate this with both the Advanced Custom Fields AND Admin in English plugins loaded.
ACF by itself seems fine, but when Admin In English is also loaded, ACF calls get_locale() on include, which causes Admin In English to call wp_get_referer() on the locale filter before pluggable.php has been included.

Obviously this is going to affect a few other plugins though.

Why wp_validate_redirect() is in pluggable.php though is really debatable.. (but it's there, so too late to move it)

#6 @needle
11 years ago

Sorry for the confusion... that was what I meant to say - that the plugins I've identified call wp_get_referer() when they are first included, not via the callback from the init (or any other) action. Moreover, the plugins can't include the file themselves, since it is included with require() in wp_settings.php. Oh dear!

/me goes off to notify plugin authors

#7 @nacin
11 years ago

  • Milestone changed from Awaiting Review to 3.6.2

@nacin
11 years ago

A patch for Hotfix that tries (but could fail) to define wp_validate_redirect() first.

@nacin
11 years ago

A patch for core.

#8 @nacin
11 years ago

25294.diff is a patch for Hotfix. Unfortunately we are at the mercy of the load order here, which is alphabetical unless otherwise filtered.

25294.2.diff is a patch for core. I'm going to bump the branch to 3.6.2-alpha and get this in, now.

#9 @nacin
11 years ago

In 25399:

Return false from wp_get_referer() if it is called before wp_validate_redirect() is defined.

see #25294.

#10 @nacin
11 years ago

In 25400:

Return false from wp_get_original_referer() if it is called before wp_validate_redirect() is defined.

see #25294.

#11 @nacin
11 years ago

In 25401:

Return false from wp_get_referer() and wp_get_original_referer() if called before wp_validate_redirect() is defined.

Merges [25399] and [25400] to the 3.6 branch.
see #25294.

#12 @nacin
11 years ago

This build now works: http://wordpress.org/nightly-builds/wordpress-3.6-latest.zip.

You simply need wp-includes/functions.php out of that zip. (Also wp-includes/version.php, ideally.)

To update from the dashboard to this version, you can download the WordPress Beta Tester plugin. Then go to Tools → Beta Testing and ensure that Point release nightlies is chosen (it's the default). At that point when you "update" you will update to 3.6.2-alpha. If you then deactivate the WordPress Beta Tester plugin, you'll simply get stable releases from there on out. (As in, once 3.6.2 is out, you will be asked to update to it.)

#13 follow-up: @nacin
11 years ago

*Please, please* alert plugin authors to fix their stuff. Doing *anything* before plugins_loaded or init is *bad* and *wrong*.

If you find an affected plugin, please feel free to report it here.

#14 in reply to: ↑ 13 @Ipstenu
11 years ago

Replying to nacin:

*Please, please* alert plugin authors to fix their stuff. Doing *anything* before plugins_loaded or init is *bad* and *wrong*.

Posted to make/plugins, Nacin.

http://cl.ly/image/2z3n2J1E1L0W

#15 follow-up: @crashnet
11 years ago

Version 0, edited 11 years ago by crashnet (next)

#16 in reply to: ↑ 15 @nacin
11 years ago

Replying to crashnet:

I nailed it. The plugin is http://wordpress.org/plugins/admin-in-english/

I've alerted the author.

#17 @nacin
11 years ago

Here's what's happening:

  • Admin in English attaches a filter to the locale filter that causes a call to wp_get_referer() whenever get_locale() is called. This is perfectly reasonable and done properly (more on that in a moment). It is trying to change which locale to load, after all.
  • Another plugin (well, probably many plugins) is calling get_locale() too early, probably to immediately load its textdomain. Because a plugin (in this case, Admin in English) may be filtering get_locale() to change functionality, calling this function before plugins_loaded is a bad, bad idea. If a plugin needs to load their textdomain, they should wait until *at least* plugins_loaded. Ideally, though, you should wait until after WordPress sets up its own locale (because why not?). The call to load_default_textdomain() and the initialization of $wp_locale occurs after all of this. The next hook that follows it is after_setup_theme, or you can just wait until init. (I could go for an setup_locale hook, probably.)

So, two ways to prevent this:

  • The only thing a plugin should be doing on inclusion is add_action() and add_filter(). Admin in English is doing this. This would have prevented other plugins from causing problems.
  • Even better, the only thing a plugin should be doing on inclusion is one add_action(), to plugins_loaded (or, if they can get away with it, init), and then attach all other hooks then. If Admin in English were doing this, this also would have been avoided.

#18 @nacin
11 years ago

This issue doesn't require two plugins, it should be noted.

No reports of this yet, but a single plugin calling wp_get_referer() before plugins_loaded would trigger a fatal error here. Or calling a function that calls wp_get_referer(), which isauth_redirect(), check_admin_referer(), wp_referer_field(), wp_original_referer_field(), and wp_nonce_ays(). (And, one of those functions can be called by wp_nonce_field().)

#19 @crashnet
11 years ago

I was able to stop the problem after disabling admin in english, but FYI I also have WPML active (which makes "admin in english" redundant - i only forgot to delete it).

thanks @nacin

Last edited 11 years ago by crashnet (previous) (diff)

#20 @needle
11 years ago

I've also alerted the plugin authors of the plugin I am using, which uses wp_get_referer() when included to test whether AJAX calls to wp-admin/admin-ajax.php are actually called from the admin screens or from the front-end. It should be simple enough to delay this until plugins_loaded. Thanks for the hotfix, @nacin

#21 @nbachiyski
11 years ago

I moved adding the filter to plugins_loaded and this fixed it for me.

The update is in the new Admin in English version 1.2.1. Could you, guys, please test to confirm it works?

#22 @DrewAPicture
11 years ago

Maybe related: #25296

#23 @crashnet
11 years ago

I can confirm this solved the issue, at least in my situation. Thanks.

#24 @johnbillion
11 years ago

  • Resolution set to fixed
  • Status changed from new to closed

#25 @nacin
11 years ago

  • Milestone changed from 3.6.2 to 3.7
Note: See TracTickets for help on using tickets.