Updating a post without escaping ampersands?

That is correct, the updating in the Admin section does not change the & to & while the wp_update_post() function (which can be found under /wp-includes/post.php on line 3772) does but only when the user does not have the capability unfiltered_html, let me explain how I found this out, and what I recommend.

I did some tracing into this and found out that wp_update_post() calls wp_insert_post() internally as shown on line 3820

return wp_insert_post( $postarr, $wp_error );

wp_insert_post() calls sanitize_post() on line 3227

$postarr = sanitize_post( $postarr, 'db' );

Then on line 2176, this filter changes the & to &

$value = apply_filters( "{$field_no_prefix}_save_pre", $value );

In particular there is a filter called content_save_pre or in my case title_save_pre since I am facing the same issue with the title.

Now, onto the Admin page which uses /wp-admin/post.php

You can see the actual save is on line 205

$post_id = edit_post();

And edit_post() function can be found under /wp-admin/includes/post.php on line 208

function edit_post( $post_data = null ) {

The actual update is being done on line 382

$success = wp_update_post( $post_data );

Which shows that WordPress uses the same wp_update_post() function internally.

Turns out that there is a filter named ‘wp_filter_kses’ which is not being used by WordPress Admin that is making all the difference. Although you can remove it by using:

remove_filter('content_save_pre', 'wp_filter_kses');

or in my case

remove_filter('title_save_pre', 'wp_filter_kses');

Or as @rinogo mentioned, you can use kses_remove_filters() to remove all kses filters.

However, these filters are set by /wp-includes/kses.php on line 1934 after it checks if the user has the capability of “unfiltered_html”

    if ( ! current_user_can( 'unfiltered_html' ) ) {
    kses_init_filters();
    }

If kses_init_filters() gets called, then the user who is trying to update the post is not trusted enough and does not have the proper capability.

I would recommend that authentication gets handled properly rather than removing the filters.

Leave a Comment