I'm having lots of problems with a really poor-developed themeforest WP theme, Dignity.
In particular, I have a short code that renders a custom text rotator. Code is pretty straightforward, something like:
[text-rotator customclass="mycssclass"]my text, my text<br />new text[/text-rotator]
The very odd thing is that when the short code is displayed, every HTML tag is removed. They are directly removed, and the content is not touched. For example, for the code above, I will get in output my text, mytextnewtext; without the line break.
How come? Perhaps is a built-in WP filter? I checked through the short code function, but there seems not to be any filter. Here's where the short code is registered:
function dignity_text_rotator($atts, $content = null)
{
extract(shortcode_atts(array("customclass" => '', "fx" => ''), $atts));
//Options
$data_fx = '';
if($fx != '')
{
$data_fx = 'data-fx="'.$fx.'"';
$customclass = $customclass.' animated';
}
if($customclass != '') { $cc = $customclass; } else $cc = '';
//Return content
$html = '<div class="text-rotator '.$cc.'" '.$data_fx.'><span class="rotate">'.do_shortcode($content).'</span></div>';
return $html;
}
Any hint?
Updated: oddly, the problem was in the js script that then reads the text inside the div and creates the actual text-rotator.
In fact, it sanitizes all the html when reading node html by directly removing the HTML tags. To solve this, I had to modify the way the note content is retrieved in the JS script.
Related
we just integrated timber into our acf-gutenberg-block setting, and we love it. ;)
There is one thing that doesnt work.
Our ACF Blocks have prefilled values like a "dummy" headline.
But when a backend user adds a block into the gutenberg view, the get_fields() inside our render_callback function is empty. The user then changes the headline and then get_fields brings up all the fields and their values.
any idea how to fix this problem on the first load of an acf block?
the callback function looks like this (just like the one in the documentation)
function my_acf_block_render_callback($block, $content = '', $is_preview = false)
{
$context = Timber::context();
// Store block values.
$context['block'] = $block;
// Store field values.
$context['fields'] = get_fields();
// Value for detecting editor-view in twig (like is admin())
$context['is_preview'] = $is_preview;
// Render the block.
Timber::render('blocks/' . $block['template-name'] . '.html.twig', $context);
}
cheers,
ToM
In an MVC application I have to use #HTML.TextAreaFor to display some text from a database, the trouble is sometimes that text may have HTML tags within it and I can't see a way to remove those for display only.
Is it possible to do this in the view (maybe with CSS?) without having to strip the tags in the controller first?
EDIT
The data coming from the controller contains html tags which I do not want to remove, I just don't want to display them
Normally I would use #HTML.Raw but it has to work in a #HTML.TextAreaFor control.
If you want to decode Html returned from the Controller you can use the following JavaScript method:
This method decodes "Chris' corner" to "Chris' corner".
var decodeEntities = (function () {
// this prevents any overhead from creating the object each time
var element = document.createElement('div');
function decodeHTMLEntities(str) {
if (str && typeof str === 'string') {
// strip script/html tags
str = str.replace(/<script[^>]*>([\S\s]*?)<\/script>/gmi, '');
str = str.replace(/<\/?\w(?:[^"'>]|"[^"]*"|'[^']*')*>/gmi, '');
element.innerHTML = str;
str = element.textContent;
element.textContent = '';
}
return str;
}
return decodeHTMLEntities;
})();
You can do this by using a razor code in your view.
#Html.Raw(HttpUtility.HtmlDecode(Model.Content))
if I set Model.Content to this string "<strong>This is me</strong><button>click</button>", the code above will render it like HTML code and will have a strong text next to a button as an output like the image below:
There's some nice rich text editors libraries like CK Editor, Quill, or TinyMCE that can display HTML while still maintaining the editor capabilities of being a text editor. All of these libraries have capabilities of being read-only as well if that's necessary.
Example from Quill -
Sorted this by changing TextAreaFor toTextBoxFor and setting a formatted value.
#Html.TextBoxFor(x => Model.MyItem, new { #class = "form-control", #required = "true", Value = Regex.Replace(Model.MyItem, "<.*?>", String.Empty) })
I am not fan of DOMDocument because I believe it is not very good for real world usages. Yet in current project I need to replace all texts in a page (which I don't have access to source code) with other strings (some sort of translation); so I need to use it.
I tried doing this with DOMDocument and I didn't received the expected result. Here is the code I use:
function Translate_DoHTML($body, $replaceArray){
if ($replaceArray && is_array($replaceArray) && count($replaceArray) > 0){
$body2 = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
$doc = new DOMDocument();
$doc->resolveExternals = false;
$doc->substituteEntities = false;
$doc->strictErrorChecking = false;
if (#$doc->loadHTML($body2)){
Translate_DoHTML_Process($doc, $replaceArray);
$body = $doc->saveHTML();
}
}
return $body;
}
function Translate_DoHTML_Process($node, $replaceRules){
if($node->hasChildNodes()) {
$nodes = array();
foreach ($node->childNodes as $childNode)
$nodes[] = $childNode;
foreach ($nodes as $childNode)
if ($childNode instanceof DOMText) {
if (trim($childNode->wholeText)){
$text = str_ireplace(array_keys($replaceRules), array_values($replaceRules), $childNode->wholeText);
$node->replaceChild(new DOMText($text),$childNode);
}
}else
Translate_DoHTML_Process($childNode, $replaceRules);
}
}
And here are the problems:
Escaping attributes: There are data-X attributes in file that become escaped. This is not a major problem but it would be great if I could disable this behavior.
Before DOM:
data-link-content=" <a class="submenuitem" href="
After DOM:
data-link-content=' <a class="submenuitem" href="
Removing of closing tags in javascript:
This is actually the main problem for me here. I don't know for what reason in the world DOMDocument may see any need to remove these tags. But it do. As you can clearly see in below example it remove closing tags in java-script string. It also removed last part of script. It seems like DOMDocument parse the java-script inside. Maybe because there is no CDATA tag? But any way it is HTML and we don't need CDDATA in HTML. I thought CDATA is for xHTML. Also I have no way to add CDDATA here. So can I ask it to not parse script tags?
Before DOM:
<script type="text/javascript"> document.write('<video src="http://x.webm"><p>You will need to Install the latest Flash plugin to view this page properly.</p></video>'); </script>
After DOM:
<script type="text/javascript"> document.write('<video src="http://x.webm"><p>You will need to <a href="http://www.adobe.com/go/getflashplayer" target="_blank">Install the latest Flash plugin to view this page properly.</script>
If there is no way for me to prevent these things, is there any way that I can port this code to SimpleHTMLDOM?
Thanks you very much.
Try this , and replace line content ;
$body2 = mb_convert_encoding($body, 'HTML-ENTITIES', "UTF-8");
to ;
$body2 = convertor($body);
and insert in your code ;
function convertor($ToConvert)
{
$FromConvert = html_entity_decode($ToConvert,ENT_QUOTES,'ISO-8859-1');
$Convert = mb_convert_encoding($FromConvert, "ISO-8859-1", "UTF-8");
return ltrim($Convert);
}
But use the right encoding in the context.
Have a nice day.
Based on my search, reason of the second problem is actually what "Alex" told us in this question: DOM parser that allows HTML5-style </ in <script> tag
But based on their research there is no good parser out there capable of understanding today's HTML. Also, html5lib's last update was 2 years ago and it failed to work in real world situations based on my tests.
So I had only one way to solve the second problem. RegEx. Here is the code I use:
function Translate_DoHTML_GetScripts($body){
$res = array();
if (preg_match_all('/<script\b[^>]*>([\s\S]*?)<\/script>/m', $body, $matches) && is_array($matches) && isset($matches[0])){
foreach ($matches[0] as $key => $match)
$res["<!-- __SCRIPTBUGFIXER_PLACEHOLDER".$key."__ -->"] = $match;
$body = str_ireplace(array_values($res), array_keys($res), $body);
}
return array('Body' => $body, 'Scripts' => $res);
}
function Translate_DoHTML_SetScripts($body, $scripts){
return str_ireplace(array_keys($scripts), array_values($scripts), $body);
}
Using above two functions I will remove any script from HTML so I can use DomDocument to do my works. Then again at the end, I will add them back exactly where they were.
Yet I am not sure if regex is fast enough for this.
And don't tell me to not use RegEx for HTML. I know that HTML is not a regular language and so on; but if you read the problem your self, you will suggest the same approach.
I've created a page where I have two input textareas and I add CKeditor (ver. 4) to both of them.
The first editor works fine, I've set config.allowedContent = true; in the config.js to stop stripping tags like <script> and everything works as expected.
I have another editor right below it, same settings, same setup, I just changed the ID of the textarea field. It works when I submit normal text, but as soon as I add a <script> tag, for example, and press the submit button of the form in which the editors are in it seems to reload the page, doesn't submit any data and firebug tells me that the server returns 403.
I tried isolating the editor, adding personal configuration. Nothing. The first textarea works like a charm, second one returns 403 if the text has unsafe tags in it.
My setup is as follows, I'm using this ckeditor helper to insert the editors where I need. Page is created with CodeIgniter as you guessed.
I got a config.js file in ckeditor folder.
I'm using a regular form, nothing fancy about it. It looks like this
<form action="http://domain.com/admin/articles/edit/47" method="post">
<div id="cke_ckeditor_en_container">
<textarea cols="75" rows="7" id="ckeditor_en" name="text_en" class="input-text is-col-text"><?php echo set_value('text_en', isset($text_en) ? htmlspecialchars_decode($text_en) : ''); ?></textarea>
<?php echo display_ckeditor($ckeditor_en); ?>
</div>
<input type="submit" value="submit" />
</form>
The form has another part of html for the other editor which is the same, with changed id and other attributes, and a checkbox, nothing relevant.
And got this in my controller
public function edit(){
$this->load->helper('ckeditor');
$id = (int)$this->uri->segment(4);
if (empty($id)){
$this->session->set_flashdata('error', 'Empty ID!');
redirect('admin/articles');
}
$data = $this->articles_model->fetch_article($id);
$data['page_title'] = "Edit `" . $data['title'] . "`";
$data['form_url'] = "admin/articles/edit/" . $id;
$data['ckeditor'] = array(
'id' => 'ckeditor',
'path' => 'js/ckeditor');
$data['ckeditor_en'] = array(
'id' => 'ckeditor_en',
'path' => 'js/ckeditor');
$data['edit'] = true;
if($this->input->post('submit')){
$this->save_article("update",$id);
}
$this->load->view("admin/articles",$data);
}
private function save_article($type='insert', $id=0){
$this->load->library('form_validation');
$this->form_validation->set_rules('title','Title','trim|xss_clean|max_length[150]|min_length[1]');
$this->form_validation->set_rules('text','Text','trim');
$this->form_validation->set_rules('title_en','Title EN','trim|xss_clean|max_length[150]|min_length[1]');
$this->form_validation->set_rules('text_en','Text EN','trim');
$this->form_validation->set_rules('top_menu','Show in top menu','trim|xss_clean|max_length[1]');
if ($this->form_validation->run() === FALSE)
{
return FALSE;
}
// make sure we only pass in the fields we want
$data = array();
$data['title'] = $this->input->post('title');
$data['text'] = htmlspecialchars($this->input->post('text'));
$data['title_en'] = $this->input->post('title_en');
$data['text_en'] = htmlspecialchars($this->input->post('text_en'));
$data['url'] = $this->toAscii($this->input->post('title'));
$data['url_en'] = $this->toAscii($this->input->post('title_en'));
$data['top_menu'] = $this->input->post('top_menu');
if($type == "insert"){
$data['time'] = date("YmdHis");
}
if ($type == 'insert'){
if($this->articles_model->insert($data)){
$this->session->set_flashdata('success', 'Article added successfully!');
}else{
$this->session->set_flashdata('error', 'An error occured!');
}
}else if ($type == 'update'){
if($this->articles_model->update($id, $data)){
$this->session->set_flashdata('success', 'Article `' . $data['title'] . '` edited successfully!');
}else{
$this->session->set_flashdata('error', 'An error ecc!');
}
}
redirect("admin/articles");
}
Safety, or unsafeness, to be exact, of my code is not relevant
edit
Adding config.js for ckeditor.
CKEDITOR.editorConfig = function( config ) {
config.filebrowserBrowseUrl = '/js/kcfinder/browse.php?type=files';
config.filebrowserImageBrowseUrl = '/js/kcfinder/browse.php?type=images';
config.filebrowserFlashBrowseUrl = '/js/kcfinder/browse.php?type=flash';
config.filebrowserUploadUrl = '/js/kcfinder/upload.php?type=files';
config.filebrowserImageUploadUrl = '/js/kcfinder/upload.php?type=images';
config.filebrowserFlashUploadUrl = '/js/kcfinder/upload.php?type=flash';
config.removeButtons = 'Underline,Subscript,Superscript';
config.allowedContent = true;
// Se the most common block elements.
config.format_tags = 'p;h1;h2;h3;pre';
// Make dialogs simpler.
config.removeDialogTabs = 'image:advanced;link:advanced';
};
I'm stumped and stupified, I've got no ideas on what to do. It seems that the one input has been cursed.
Any help appreciated, thank you.
This would be the result of your mod_security rules. Depending on how strict they are they help better protect scripts from being hacked through vulnerabilities, generally those exploited via POST's.
As I understand you are trying to add something to your second textarea. And CKEditor removing some "unsafe" tags. I won't be very secure, but this can help you:
config.extraAllowedContent = '*{*}';
You will add this to your config.js. This code provides you to add anything you want. And CKEditor won't delete "unsafe" tags.
Documenation for this method
https://www.bilisimkitabi.com/403-error-on-submit-of-ckeditor
You can add to following code in your .htaccess file
#ckeditor Post 403 problem
<IfModule mod_security.c>
SecFilterEngine Off
SecFilterScanPOST Off
</IfModule>
#ckeditor Post 403 problem
Here is the situation: I have 2 pages.
What I want is to have a number of text links(<a href="">) on page 1 all directing to page 2, but I want each link to send a different value.
On page 2 I want to show that value like this:
Hello you clicked {value}
Another point to take into account is that I can't use any php in this situation, just html.
Can you use any scripting? Something like Javascript. If you can, then pass the values along in the query string (just add a "?ValueName=Value") to the end of your links. Then on the target page retrieve the query string value. The following site shows how to parse it out: Parsing the Query String.
Here's the Javascript code you would need:
var qs = new Querystring();
var v1 = qs.get("ValueName")
From there you should be able to work with the passed value.
Javascript can get it. Say, you're trying to get the querystring value from this url: http://foo.com/default.html?foo=bar
var tabvalue = getQueryVariable("foo");
function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++)
{
var pair = vars[i].split("=");
if (pair[0] == variable)
{
return pair[1];
}
}
}
** Not 100% certain if my JS code here is correct, as I didn't test it.
You might be able to accomplish this using HTML Anchors.
http://www.w3schools.com/HTML/html_links.asp
Append your data to the HREF tag of your links ad use javascript on second page to parse the URL and display wathever you want
http://java-programming.suite101.com/article.cfm/how_to_get_url_parts_in_javascript
It's not clean, but it should work.
Use document.location.search and split()
http://www.example.com/example.html?argument=value
var queryString = document.location.search();
var parts = queryString.split('=');
document.write(parts[0]); // The argument name
document.write(parts[1]); // The value
Hope it helps
Well this is pretty basic with javascript, but if you want more of this and more advanced stuff you should really look into php for instance. Using php it's easy to get variables from one page to another, here's an example:
the url:
localhost/index.php?myvar=Hello World
You can then access myvar in index.php using this bit of code:
$myvar =$_GET['myvar'];
Ok thanks for all your replies, i'll take a look if i can find a way to use the scripts.
It's really annoying since i have to work around a CMS, because in the CMS, all pages are created with a Wysiwyg editor which tend to filter out unrecognized tags/scripts.
Edit: Ok it seems that the damn wysiwyg editor only recognizes html tags... (as expected)
Using php
<?
$passthis = "See you on the other side";
echo '<form action="whereyouwantittogo.php" target="_blank" method="post">'.
'<input type="text" name="passthis1" value="'.
$passthis .' " /> '.
'<button type="Submit" value="Submit" >Submit</button>'.
'</form>';
?>
The script for the page you would like to pass the info to:
<?
$thispassed = $_POST['passthis1'];
echo '<textarea>'. $thispassed .'</textarea>';
echo $thispassed;
?>
Use this two codes on seperate pages with the latter at whereyouwantittogo.php and you should be in business.