3

I am using wp_cron to auto grab posts from a remote website and save them in my wp db.

NOTICE! I am executing my code from my plugin, not from my template functions.php or somewhere else. I have my own validation of grabbed content to prevent malicious code etc. so turning off security validation in wordpress is not an issue in my case, but be careful if you don't have your own validation of grabbed content. Always validate grabbed values if possible!

I have in my plugin one button to grab posts manually by clicking on this button and it works perfect. Everything is stored as I want in my database. No problem here.

but then I have a wp_cron function that runs for testing purposes every two minutes (if somebody clicks on my page, of course ;) and here is a problem.

Notice that the code is identical, just instead of get_user_id() I set it manualy to 1. that's probably the only change between these two codes.

And the problem is that everything is stored as expected including time, title, slug, (it even grabs and downnload and set the featured image for the post correctly), tags, categories and additional taxonomy too. So that fine.

Only thing that is missing is the body text (content) of the post.

When downloaded from admin manually. It's something like:

<iframe width="650" scrolling="no" height="450" frameborder="0" src="http://example.com/embedframe/3843634"></iframe>

or

<object height="450" width="650" ><param name="movie" ... bla bla bla ... shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash" type="application/x-shockwave-flash" height="450" width="650" /></object> 

So, it is because it is filtered and striped out, I mean object and iframe when not logged in as an admin?

If so, how can I turn it off in my plugin?

Or is it something else?

I really think it's only something with WP security issue, because the code works when performed from admin as admin manually. And the code of the function is the same and all variables are passed in as expected. Just content is not saved.

EDIT:

It's definitely something with the WP security. When I set in my auto cron function content variable manually to "Testing auto save." is is saved normally. But When I set it to <iframe>something</iframe> or <object>blablabal</object> it is NOT.

How to turn this "checking" off, so I can save my code with cron?

Any idea?

4
  • It's definitely something with the WP security. When I set in my auto cron function content variable manualy to "Testing auto save." is is saved normally. But When I set it to <iframe>something</iframe> or <object>blablabal</object> it is not. How to turn this check off, so I can save my code with cron?
    – Derfder
    May 24, 2013 at 9:27
  • You need to insert those posts as admin. Please use the search, this has been discussed before (sorry I'm a little short here). It's basically to hook in there and raise the user-level when this is a cron request - I think it was lowered for some reason so better understand the implications.
    – hakre
    May 24, 2013 at 10:00
  • No, I finally solved it ;) . You need to use remove_filter('content_save_pre', 'wp_filter_post_kses'); remove_filter('content_filtered_save_pre', 'wp_filter_post_kses'); and do wp_insert_post(); and then turn it on if you want to feel protected against some "injection" ;) like add_filter('content_save_pre', 'wp_filter_post_kses'); add_filter('content_filtered_save_pre', 'wp_filter_post_kses');
    – Derfder
    May 24, 2013 at 10:03
  • 1
    Well, that's probably not really sane because you likely will disable as well for comments or so. I dunno specifically, but I can only suggest you really take care of side-effects here.
    – hakre
    May 24, 2013 at 10:05

4 Answers 4

3

Instead of manually removing the safety filters like this, you should simply set the correct user for these processes to be running as.

When you are logged in and running a process manually, you are logged in and thus you have your credentials being used, and your permissions being used. I'm betting you're an administrator on the site. You have permission to post unfiltered_html, meaning that you can post iframes and objects and whatever you like.

When your cron job runs, it doesn't have your credentials. So, it doesn't get those same permissions. Thus, the safety filters get turned on, and things like iframes and such get blocked.

To fix it, you need to change your process not to disable the filters, but to run as you. So find your user ID number in the database, and just before your process to do the import runs, add this code:

wp_set_current_user( 123 );

Where "123" is whatever your user ID number is. Then the code will now be "you" and can do things just like you would do them. Those filters won't take effect because the permissions are correct for the current user.

Note: This isn't any safer, BTW. You're still allowing some remote website to insert possibly dangerous things onto yours. So you're trusting them not to screw you over here. Just bear that in mind. This method is just simpler than manually fiddling around with filters.

2

WARNING !!!

Always make validation of the data you are saving into the database! This answer below assumes that you validate the content of your post inside of your custom function that you trigger via cron!

I find solution to this problem of stripping iframe and object tags.

NOTICE! Put this only in your plugin's function code that is run via wp cron. Don't put it in your function.php in your template or in other places.

// before saving post
remove_filter('content_save_pre', 'wp_filter_post_kses');
remove_filter('content_filtered_save_pre', 'wp_filter_post_kses');

// save code here

// after saving post
add_filter('content_save_pre', 'wp_filter_post_kses');
add_filter('content_filtered_save_pre', 'wp_filter_post_kses');

IMPORTANT! By using the prefix content_ we are limiting the remove filter -> save our data -> add_filter proces to just the content and not commetns, excerpt etc.

17
  • You removed the "security" so I guess you didn't solve much here. Better get some review by others first before suggesting this as a solution.
    – hakre
    May 24, 2013 at 10:05
  • What are you talking about? I am using my own validation in my function.
    – Derfder
    May 24, 2013 at 10:06
  • This is a dangerous fix, and makes your site more unsecure
    – Tom J Nowell
    May 24, 2013 at 10:06
  • @Derfder: Then make that really visible within your answer. E.g. show the action around as code. Keep in mind other users might find this here via google and just copy and paste and really eat the pain. Hence the warning is important.
    – hakre
    May 24, 2013 at 10:07
  • 1
    Then make it clear in your answer, as it currently stands, any person may come across this, go AHA and copy paste, unaware of the consequences
    – Tom J Nowell
    May 24, 2013 at 10:29
0

Use shortcodes, e.g create an iframe shortcode, then you'd be able to do:

[iframe]example.com[/iframe]

Here's code to implement such a shortcode:

add_shortcode('iframe', array('iframe_shortcode', 'shortcode'));
class iframe_shortcode {
    function shortcode($atts, $content=null) {
          extract(shortcode_atts(array(
               'url'      => '',
               'scrolling'      => 'no',
               'width'      => '100%',
               'height'      => '500',
               'frameborder'      => '0',
               'marginheight'      => '0',
          ), $atts));
          if (empty($url)) return '<!-- Iframe: You did not enter a valid URL -->';
     return '<iframe src="'.$url.'" title="" width="'.$width.'" height="'.$height.'" scrolling="'.$scrolling.'" frameborder="'.$frameborder.'" marginheight="'.$marginheight.'"><a href="'.$url.'" target="_blank">'.$url.'</a></iframe>';
    }
}

Usage:

[iframe url="http://wpsnipp.com" width="100" height="100" scrolling="yes" frameborder="1" marginheight="2"]

Source:

http://wpsnipp.com/index.php/functions-php/iframe-shortcode-for-posts-and-pages/

If you need to insert object embeds, then something has gone wrong. Use OEmbed or devise a shortcode

2
  • Tanks, but I have a complex function and I grab also object, and other stuff. my function code is good I think I just needed wp_filter_post_kses to do what I want.
    – Derfder
    May 24, 2013 at 10:10
  • Complex functions are inherently harder to test, and easy to break. Perhaps you should be stripping iframes out of your content before saving it, and replacing them with shortcodes so that you dont compromise your security
    – Tom J Nowell
    May 24, 2013 at 10:17
0

After trying everything, this worked for me:

global $allowedposttags;
$allowedposttags['div'] = array('align' => array (), 'class' => array (), 'id' => array (), 'dir' => array (), 'lang' => array(), 'style' => array (), 'xml:lang' => array() );
$allowedposttags['iframe'] = array('src' => array () );

https://wordpress.org/support/topic/wp_update_post-strips-css-id-attribute?replies=7

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.