6100 comments
2357 subscribers
6266 on Twitter
Subscribe! Feed reader E-mail

Drupal, HTML Purifier, and embedding IFRAMES from YouTube

I know, I know. I shouldn’t allow IFRAMEs at all. But the client’s prospective users were really excited about images and video, and Drupal’s Media module wasn’t going to be quite enough. So I’ve been fighting with CKEditor, IMCE, and HTML Purifier to figure out how to make it easier. I’m hoping that this will be like practically all my other Drupal posts and someone will comment with a much better way to do things right after I describe what I’ve done. =)

First: images. There doesn’t seem to be a cleaner way than the “Browse server” – “Upload” combination using CKEditor and IMCE. I tried using WYSIWYG, TinyMCE and IMCE. I tried ImageBrowser, but I couldn’t get it to work. I tried FCKEditor, which looked promising, but I got tangled in figuring out how to control other parts of it. I’m just going to leave it as CKEditor and IMCE at the moment, and we can come back to that if it turns out to be higher priority than all the other things I’m working on. This is almost certainly my limitation rather than the packages’ limitations, but I don’t have the time to exhaustively tweak this until it’s right. Someday I may finally learn how to make a CKEditor plugin, but it will not be in the final week of this Drupal project.

Next: HTMLPurifier and Youtube. You see, Youtube switched to using IFRAMEs instead of Flash embeds. Allowing IFRAMEs is like allowing people to put arbitrary content on your webpage, because it is. The HTML Purifier folks seem firmly against it because it’s a bad idea, which it also is. But you’ve got to work around what you’ve got to workaround. Based on the Allow iframes thread in the HTMLPurifier forum, this is what I came up with:

Step 1. Create a custom filter in htmlpurifier/library/myiframe.php.

<?php
// Iframe filter that does some primitive whitelisting in a
// somewhat recognizable and tweakable way
class HTMLPurifier_Filter_MyIframe extends HTMLPurifier_Filter
{
  public $name = 'MyIframe';
  public function preFilter($html, $config, $context) {
    $html = preg_replace('/<iframe/i', '<img class="MyIframe"', $html);
    $html = preg_replace('#</iframe>#i', '', $html);
    return $html;
  }
  public function postFilter($html, $config, $context) {
    $post_regex = '#<img class="MyIframe"([^>]+?)>#';
    return preg_replace_callback($post_regex, array($this, 'postFilterCallback'), $html);
  }
  protected function postFilterCallback($matches) {
    // Whitelist the domains we like
    $ok = (preg_match('#src="http://www.youtube.com/#i', $matches[1]));
    if ($ok) {
      return '<iframe ' . $matches[1] . '></iframe>';
    } else {
      return '';
    }
  }
}

Step 2. Include the filter in HTMLPurifier_DefinitionCache_Drupal.php. I don’t know if this is the right place, but I saw it briefly mentioned somewhere.

// ... rest of file
require_once 'myiframe.php';

Step 3. Create the HTML Purifier config file. In this case, I was changing the config for “Filtered HTML”, which had the input format ID of 1. I copied config/sample.php to config/1.php and set the following:

function htmlpurifier_config_1($config) {
  $config->set('HTML.SafeObject', true);
  $config->set('Output.FlashCompat', true);
  $config->set('URI.DisableExternalResources', false);
  $config->set('Filter.Custom', array(new HTMLPurifier_Filter_MyIframe()));
}

Now I can switch to the source view in CKEditor, paste in my IFRAME code from Youtube, and view the results. Mostly. I still need to track down why I sometimes need to refresh the page in order to see it, but this is promising.

2011-08-05 Fri 16:34

Short URL: http://sachachua.com/blog/p/22404
  • http://www.jehzlau-concepts.com/ jehzlau

    Good thing, even if Youtube switched to IFRAMEs, the old embed code still works. I think there’s a better way in Drupal, perhaps replicating the auto-embed featured of WordPress? :)

  • http://sachachua.com Sacha Chua

    jehzlau: Given my client’s target users, I’ll be lucky if I can get most of them to copy the embed code, much less click on the classic embed code checkbox and grab that instead… =) Darn Facebook for raising expectations when it comes to autoembeds! ;)

  • http://www.jehzlau-concepts.com/ jehzlau

    Oh yes… the clients. They don’t care about the embed code as long as they can embed it. Haha! I think even if the embed code includes an external link to a malicious site, they won’t bother. We need to look for a workaround to fix it for them… Geez.. Oh well. :)

  • Arjan

    How about Video filter?

  • MacRonin

    Would this issue/module help tackle the CKEditor MediaEmbed plugin challenge ?

    http://drupal.org/node/872868

    Plus a video on how to configure the mediaembed plugin in ckeditor

    http://jesox.com/posts/how-add-youtube-vimeo-or-any-other-embed-content-ckeditor

  • Joe

    Duuuude… Embedfilter module by KarenS. Then search the issue cue for the iframe patch.

    • http://sachachua.com Sacha Chua

      Can I get that to play nicely with HTMLPurifier without going crazy? Might be useful for future projects. =)

  • Joe

    You would have to get iframes to pass through the HTML Purifier filter. Or just don’t use that behemoth :). Then put the patched Embedfilter after it in the processing order. Embedfilter will then strip all iframes except the ones from the domains that you specify in the mod settings.

  • sbandyopadhyay

    Instead of using a custom filter, you can use what will be included in the next version of HTML purifier: HTML.SafeIframe (http://htmlpurifier.org/phorum/read.php?5,5319).

    As for the issue with needing to refresh the page, are you using Chrome? If so, see here: http://www.rahulsingla.com/blog/2011/06/drupal-and-chrome-refused-to-execute-a-javascript-script-source-code-of-script-found-wi

    I had the same issue, except it was with the iframe instead of the javascript.

    • http://sachachua.com Sacha Chua

      Glad to hear HTML Purifier will support it better next time! Thanks for the Chrome tips too. =)

  • Edward Savage

    This is a very clever solution, but the problem I have with it is that these to necessary attributes are stripped out: frameborder=”0″ allowfullscreen

    Do you have a work-around for that?

  • Edward Savage

    Sacha, I poked around and made some changes to put necessary attributes back in and also added Vimeo support. You can see my code on this Stack Overflow answer: http://stackoverflow.com/a/8581864/244826

  • http://sachachua.com Sacha Chua

    Yay! Thanks for sharing.

  • http://uk.linkedin.com/in/nikosstylianou Nikos Stylianou

    I created this sandbox project which adds a youtube and vimeo button to ckeditor which embeds iframes.
    http://drupal.org/sandbox/thetoast/1438500

  • http://uk.linkedin.com/in/nikosstylianou Nikos Stylianou

    I just read the bit again about how you’re having to refresh the page to see it. Using full html and my sandbox module I saw the same effect.

  • http://gravatar.com/trkest trkest

    I found this was not necessary – this config worked for me:

    http://drupal.org/node/711728#comment-5600344

    toby

  • Sacha Chua

    That’s good to hear. Thanks for the update!

On This Day...

  • 2012: Building MobileOrg for Android — If you want to use your Android device to work with your Org-mode files, there’s MobileOrg and there’s MobileOrg NG. [...]
  • 2010: Long weekend reflections — Long weekends? We don’t pack our bags and travel, or kick our feet up and chill out at our (non-existent) [...]
  • 2009: In-jokes and shared experiences — W- helped me put together some wire shelves for plants. One of the rods was deformed, so he brought out [...]
  • 2009: Weekly review: Week ending August 2, 2009 — From last week’s plans: Do some Facebook strategy consulting Find ways to recognize the contributions people had made to the idea lab [...]
  • 2008: Drupal shell: quickly evaluating PHP statements in a Drupal context — I often find myself needing to variable_set something temporarily, just to try things out. The drush module provides a command-line [...]
  • 2007: Weekly review — This week Send thesis draft to people, really. Done. Check paperwork requirements for post-graduate work permit and start compiling them. Started Revise CASCON paper. Done. Do one [...]
  • 2007: Moving back to PCFinancial — I think I’ll move back to PCFinancial for my banking. I don’t think I’ll need any financial statements for my future [...]
  • 2005: Changing patterns of computing — I managed to leave my laptop at home today! =) That forced me to be productive all day. See how many [...]
  • 2005: On mailing lists — I find it a bit strange that people here like broadcasting their messages by putting everyone in To: or Cc:. I [...]
  • 2004: Philippine comic book blog — http://filipinocomics.blogspot.com E-Mail from Julius Oliveros
  • 2003: Emacs macros — Keyboard macros in Emacs allow me to easily generate the gallery from the pipe-separated values I exported from Gnumeric. Viva open [...]
  • 2003: RSS feed — I think it should be relatively easy to publish an RSS feed of the links from my planner wiki…
  • 2003: Plans — I’m going to try to move my plans up by a year. I suspect I’ll learn more by going to graduate [...]
  • 2003: Experts — I think I’ve a way to deal with my large CS123 class: topic experts. Each group has experts in charge of [...]
  • 2003: Teaching — Holding up. Doing remarkably well, in fact – probably because I’m too busy to do anything else. The sheer magnitude of [...]
  • 2003: Communication — Considering that I tend to text long messages in bursts, it might actually make more sense for me to stay at [...]
  • 2003: Redesign — Using objects in the beginning - graphics right away; bounds and draw promotes object reuse - using objects - implementing methods - expressions - if - loops - [...]
  • 2003: http://www.geocities.com/fanny11sy/featured-projects
  • 2003: JPCS conference — end of august, one way of reviving contact with JPCS. Need a venue for a seminar for the gathering of all [...]
  • 2003: Java patterns — http://www.anupriyo.com/oopfm.shtml

Get the highlights as a PDF!

Stories from my Twenties: Highlights from a Decade of Blogging

Free sample!