Hi guys,
I am using tinyMCE editor. In my textarea, I want to let user type some html like <table></table> and store that in db just like that, <table></table>.
However, what I am getting is:
&lt;table&gt;&lt;/table&gt;
Now, if I go to the edit form for the item that contains that html piece and I update it, what I get in my database is <table></table>.
Can someone please explain how I can store <table> as <table> in one single step?

Hey cereal,
thanks for your reply. I looked in that link, but I am not sure that solves my issue.
What I am having difficulties with is preventin tinyMCE from encoding < and >. However, if you look here http://www.tinymce.com/wiki.php/Configuration:entities you'll see that < and > will ALWAYS be encoded... even if I use the entity_encoding : "raw" option http://www.tinymce.com/wiki.php/Configuration:entity_encoding

perhaps I will have to encode &gt; to > in some filter or something for my code to work. OR, use tinyMCE plugins/toolbars to insert html tags instead of typing them in.
what do you think?

Hmm, I'm not sure about this. By testing I see what you mean, but I also see that if I resubmit the same form, the allowed tags will be converted again:

<!DOCTYPE html>
<html>
    <head>
        <title>TinyMCE</title>
        <script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
        <script type="text/javascript">
            tinymce.init({
                selector: "textarea",
                valid_elements : "a[href|target=_blank],strong,em,div[align],br"
            });
        </script>
    </head>
    <body>

        <h2>Test</h2>
        <form method="post">
            <textarea name="contents"><?php echo array_key_exists('contents', $_POST) ? $_POST['contents']:''; ?></textarea>
            <input type="submit" name="submit" value="send" />
        </form>

        <?php

        if($_POST)
        {
            echo "<h3>POST:</h3><pre>";
            highlight_string($_POST['contents']);
            echo "</pre>";
        }

        ?>

    </body>
</html>

So the first time outputs:

<p>Hello &lt;strong&gt;World&lt;/strong&gt;</p>

The second time:

<p>Hello <strong>World</strong></p>

As expected. If instead you load the code plugin:

tinymce.init({
            selector: "textarea",
            plugins: "code",
            valid_elements : "a[href|target=_blank],strong,em,div[align],br"
        });

You can submit the code throught the Tools > Code tab and it won't be converted to entities. BUT if for example you submit quote or another not whitelisted tag, it will be removed only after the resubmit, not during the first instance.

For now I stop here, hope it helps a bit to understand the problem. I think the best would be to find a method to disable completely this feature of TinyMCE and use HTMLPurifier or another similar library to clean the input.

hi cereal, thanks for your reply.
I am trying to take control of html purification in server side as I am building a whitelist of tags that I want to allow in. As is right now, the encoding of < and > actually prevents AntiSamy to do its job to remove html xss attacks. Any JS attacks are being thwarted allthough the first submition of data allows javascript tags in, but it wrapps their content in [[CDATA... upon the second resubmition, they are removed completely.

Now, letting code in via code tool of tinymce makes things work fine, but using the textarea that first appears to input html tags causes the issue you documented aboe.

I am trying to see what classes the code tool has different than the first textarea and fix the issue... or maybe, I could add an onSubmit listener to my form, to read the content from my first textarea instead of submitting the encoded content of the textarea (sounds confusing because it is).

what do you think?

What about using htmlspecialchars_decode() in your textarea

Docs

Example:

<textarea rows="" cols="" name=""><?php echo htmlspecialchars_decode($data['content']); ?></textarea>
commented: good suggestion! +13

@gabrielcastillo good suggestion, it could be done when the script receives the POST request, decode the input, filter and send back clean data, at that point there's no need to perform it in the textarea. For example:

<?php

    if($_POST)
    {
        $filter['contents'] = htmlspecialchars_decode($_POST['contents']);

        # clean the input
        require './library/HTMLPurifier.includes.php';
        require './library/HTMLPurifier.autoload.php';
        $config = HTMLPurifier_Config::createDefault();
        $config->set('Core.Encoding', 'UTF-8');
        $config->set('HTML.Allowed', 'p,a[href|target],em,strong,div[align],br');
        $config->set('Attr.AllowedFrameTargets', array('_blank'));
        $purifier = new HTMLPurifier($config);

        $data['contents'] = $purifier->purify($filter['contents']);
    }

?>

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
        <title>TinyMCE</title>
        <script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
        <script type="text/javascript">
            tinymce.init({
                selector: "textarea",
                plugins: "code",
                valid_elements : "a[href|target=_blank],strong,em,div[align],br"
            });
        </script>
    </head>
    <body>

        <h2>Test</h2>
        <form method="post">
            <textarea name="contents"><?php echo array_key_exists('contents', $_POST) ? $data['contents']:''; ?></textarea>
            <input type="submit" name="submit" value="send" />
        </form>

        <?php

        if($_POST)
        {
            echo "<h3>POST:</h3><pre>";
            highlight_string($data['contents']);
            echo "</pre>";
        }

        ?>

    </body>
</html>

hi guys,
gabrielcastillo's idea sounds good for consistency... this way, on resubmition, my filter will receive the same input as in the first submition, so my app won't behave differently.
so, consistency issues in app behavior are out of the way now. thanks... I did not think of that :)