HTMLawed strips class attribute

Elgg 2.3.7

We use extended_tinymce and embed plugins. When we add an image, TinyMCE add  class="elgg-photo"  to the img tag. After save the class attribute disappeared. Also when we add some class attribute to p or div tags they disappear after save.

It seems that HTMLawed strips class attribute.

How to add class attribute and other tags to HTMLawed?

Thanks

  • On Elgg 2 it might not be that easy to change the behaviour of htmlawed regarding the class attribute. You could use the 'config', 'htmlawed' plugin hook to alter the config array used by htmlawed. But for the class attribute I believe this would only give the option to either fully allow or fully deny its usage (and it might be a security issue to fully allow it).

    The upcoming Elgg 3 will also support the secondary config array of htmlawed (the $spec array) that allows to define more specific rules for the usage of html attributes, e.g. allow only specific classes. The readme of htmlawed has some info about that (http://www.bioinformatics.org/phplabware/internal_utilities/htmLawed/htmLawed_README.htm). But as I said, this will be possible only starting with Elgg 3 with usage of the newly introduced 'spec', 'htmlawed' plugin hook.

  • Thank you iionly,

    I do not understand why "class" attribute is not safe. Could you please explain.

    The following code snippet is taken from htmlawed plugin mod/htmlawed/start.php 

    $htmlawed_config = array(
    // seems to handle about everything we need.
    'safe' => true,
     
    // remove comments/CDATA instead of converting to text
    'comment' => 1,
    'cdata' => 1,
     
    'deny_attribute' => 'class, on*',
    'hook_tag' => 'htmlawed_tag_post_processor',
     
    'schemes' => '*:http,https,ftp,news,mailto,rtsp,teamspeak,gopher,mms,callto',
    // apparent this doesn't work.
    // 'style:color,cursor,text-align,font-size,font-weight,font-style,border,margin,padding,float'
    );
    "class" attribute is stripped by 'deny_attribute' => 'class, on*' which also strips scriptable on* attributes like onclick. In order to allow "class" it should be changed to 'deny_attribute' => on*'.
    So, I have to override the start.php. I'm not sure I know how to do it.
     
  • You wouldn't have to override start.php (which isn't possible anyway). At this point in start.php the default config values for filtering are set. Afterwards the 'config', 'htmlawed' plugin hook is triggered. By registering a plugin hook callback function for this plugin hook you can change the config in your callback function. For example, the Extended Tinymce plugin does this to allow for some more styles. Just check out start.php of extended_tinymce to see how it's done and you could change the value of deny_attribute to allow the class attribute. I don't know what will happen if you allow it. Maybe "no safe" is not the best term here. People might not be able to add bad code (though not sure even about that). But I don't know if it could happen that the site layout gets broken or what would happen if some non-existing class is referred.

  • Thank you - I'll try it.

    In order to overcome the possible problems that you mentioned and to check other ideas I'd like change the text that goes in and out of the htmlawed. Could you please give me the code for these hooks. I'm still a beginner :)

    Thank you

  • The hook that triggered for filtering the input is the 'validate', 'input' plugin hook defined in start.php of the htmlawed plugin. I think I don't understand what you want to try. The input you make on the site is the input that goes into the htmlawed validate hook and the text that is saved (and then shown on the site) is the text that comes out of the validate hook. With the extended_tinymce plugin (logged in as admin) you could view the raw "html code" before posting and then again after submitting (e.g. edit the blog entry/comment) to see the difference.

    If you would want to manipulate the input before and after the htmlawed filtering happens, you would need to register two plugin hook callback functions for the 'validate', 'input' plugin hook. The "before" callback would have to be registered with priority 1 (like the htmlawed_filter_tags callback function in start.php of htmlawed) and the plugin you define the callback function would have to be below the htmlawed plugin to have a chance to get called before the htmlawed function (callback functions get called in ascending priority; 500 is the default priority if not set; htmlawed uses priority 1 to increase the chance to filter first - I don't know if a priority value smaller than 1 is allowed; if two plugin hook callback functions have the same priority the plugin loaded first goes first).

  • Thank you iionly.

    What I want to do is to implement a feature to embed videos in TinyMCE (blogs, pages, comments, etc.). I've implemented a similar approach in another project with HTMLpurifier.

    1. Paste the video link in TinyMCE
    2. Use 'BeforeSetContent' to create the standard embed iframe (e.g. YouTube).
    3. Before the content goes to HTMLawed replace the iframe with "legal" markdown, e.g. [[youtube:video_id]].
      We can do this with jquey when the "send" is clicked or with a php hook before it goes to htmlawed (preferable).
    4. At the output of htmlawed replace the markdown with the standad embed iframe.

    I'd very much appreciate if you write the the hooks. I'll fill them with the script.

  • It's too late for me today to start with putting some code together.

    Just some remark about your proposed approach. Unfortunately, I think it won't work. The reason (the same reason why the add video by embedding option of izap Videos also no longer works as it did on older Elgg 1.x versions) is that the filtering is not only done during processing of input but also on processing the output of longtext text fields (e.g. the content of blogs, pages, descriptions etc.). That's done in the output/longtext.php view where the filter_tags() function sanitizes the text (this function then calls the htmlawed filter function via the 'validate', 'input' hook). Filterering is done by default is you don't explicitely turn of filtering in code where you make use of the output/longtext view. So, restoring the input after htmlawed has done it's job won't be enough as the same filtering happens again each time someone views the output.

    Some plugins seem to handle this by using the 'view', '<viewname>' plugin hook. With this plugin hook you can alter the output of a view before it gets displayed (and I guess after htmlawed filtered the output already or it would make no sense). The Embed Extender plugin does this (https://elgg.org/plugins/787632). Also, the hypeEmbed plugin (https://elgg.org/plugins/2641523) most likely does something like this if I interpret the description correctly. I haven't tried these plugins yet, so I can't say from own experience how it works (Embed Extender is unlikely to work on recent versions of Elgg anyway without modifications). The hypeEmbed plugin says that "other registered object types" could also get embedded. Maybe this means that it could also work with iZAP Videos.

  • hype Embed uses BBCode approach.
    In 3.0, I have made the output filtering hookable, so it should be easier.

  • What I want to do is to implement a feature to embed videos in TinyMCE (blogs, pages, comments, etc.)

    We've creates a plugin called oEmbed which automatically transforms supported urls into embed code. For example if a user pastes a YouTube url into the editor, in the output (not during input) this url is then replaced by the youtube embed code en you get the video player.

    This works on all url's which support the oEmbed standard (eg Twitter, facebook, imagur, etc)

    Link to the plugin: https://github.com/ColdTrick/oembed/releases

  • Thank you guys for your help. It is very much appreciated.

    So far the oEmbed meets most of my expectations. I had good experience with YouTube, FaceBook, Vimeo and dailymotion.

    Question

    Different videos standards have different sizes. Is there a way to make the sizes (almost) the same? 

    Thank you very much