mirror of
https://github.com/Lastorder-DC/rhymix.git
synced 2026-01-04 17:21:39 +09:00
Merge pull request #860 from kijin/pr/autohtml
모바일에서 댓글 작성 또는 수정시 HTML 태그가 escape되는 문제 수정
This commit is contained in:
commit
49cc39e507
6 changed files with 158 additions and 66 deletions
|
|
@ -594,6 +594,36 @@ function utf8_trim($str)
|
|||
return preg_replace('/^[\s\pZ\pC]+|[\s\pZ\pC]+$/u', '', $str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a string contains HTML content.
|
||||
* This function checks whether a string seems to contain HTML.
|
||||
* It checks for tags like <p>, <div>, <br> at the beginning and end of lines.
|
||||
*
|
||||
* @param string $str The input string
|
||||
* @return bool
|
||||
*/
|
||||
function is_html_content($str)
|
||||
{
|
||||
$str = preg_replace('![\r\n]+!', "\n", utf8_trim(utf8_clean($str)));
|
||||
$line_count = substr_count($str, "\n") + 1;
|
||||
$p_tag_count = preg_match_all('!(?:^<(?:p|div|h[1-6])(?:>|\s*[a-z])|</(?:p|div|h[1-6])>$)!im', $str);
|
||||
if ($p_tag_count > 4 || ($p_tag_count > 0 && $p_tag_count >= $line_count * 2))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
$br_tag_count = preg_match_all('!<br\s?/?>$!im', $str);
|
||||
if ($br_tag_count > 4 || ($br_tag_count > 0 && $br_tag_count >= $line_count - 1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
$span_tag_count = preg_match_all('!<span\s+style="[^"<>]*?">.+?</span>!i', $str);
|
||||
if ($span_tag_count >= 1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if HTML content is empty.
|
||||
* This function checks whether any printable characters remain
|
||||
|
|
|
|||
|
|
@ -426,6 +426,7 @@ class commentController extends comment
|
|||
|
||||
// remove Rhymix's own tags from the contents
|
||||
$obj->content = preg_replace('!<\!--(Before|After)(Document|Comment)\(([0-9]+),([0-9]+)\)-->!is', '', $obj->content);
|
||||
|
||||
// Return error if content is empty.
|
||||
if (!$manual_inserted && is_empty_html_content($obj->content))
|
||||
{
|
||||
|
|
@ -435,25 +436,27 @@ class commentController extends comment
|
|||
// if use editor of nohtml, Remove HTML tags from the contents.
|
||||
if(!$manual_inserted)
|
||||
{
|
||||
if(Mobile::isFromMobilePhone() && $obj->use_editor != 'Y')
|
||||
$editor_config = getModel('editor')->getEditorConfig($obj->module_srl);
|
||||
if (strpos($editor_config->sel_comment_editor_colorset, 'nohtml') !== false)
|
||||
{
|
||||
if($obj->use_html != 'Y')
|
||||
{
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
}
|
||||
$obj->content = nl2br($obj->content);
|
||||
$is_html_content = false;
|
||||
}
|
||||
elseif ($obj->use_editor === 'Y' || $obj->use_html === 'Y')
|
||||
{
|
||||
$is_html_content = true;
|
||||
}
|
||||
elseif ($obj->use_editor === 'N' || $obj->use_html === 'N')
|
||||
{
|
||||
$is_html_content = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oEditorModel = getModel('editor');
|
||||
$editor_config = $oEditorModel->getEditorConfig($obj->module_srl);
|
||||
|
||||
if(strpos($editor_config->sel_comment_editor_colorset, 'nohtml') !== FALSE)
|
||||
{
|
||||
$obj->content = preg_replace('/\<br(\s*)?\/?\>/i', PHP_EOL, $obj->content);
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
$obj->content = str_replace(array("\r\n", "\r", "\n"), '<br />', $obj->content);
|
||||
}
|
||||
$is_html_content = is_html_content($obj->content);
|
||||
}
|
||||
|
||||
if (!$is_html_content)
|
||||
{
|
||||
$obj->content = nl2br($obj->use_html === 'Y' ? $obj->content : escape($obj->content, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -807,25 +810,27 @@ class commentController extends comment
|
|||
// if use editor of nohtml, Remove HTML tags from the contents.
|
||||
if(!$manual_updated)
|
||||
{
|
||||
if(Mobile::isFromMobilePhone() && $obj->use_editor != 'Y')
|
||||
$editor_config = getModel('editor')->getEditorConfig($obj->module_srl);
|
||||
if (strpos($editor_config->sel_comment_editor_colorset, 'nohtml') !== false)
|
||||
{
|
||||
if($obj->use_html != 'Y')
|
||||
{
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
}
|
||||
$obj->content = nl2br($obj->content);
|
||||
$is_html_content = false;
|
||||
}
|
||||
elseif ($obj->use_editor === 'Y' || $obj->use_html === 'Y')
|
||||
{
|
||||
$is_html_content = true;
|
||||
}
|
||||
elseif ($obj->use_editor === 'N' || $obj->use_html === 'N')
|
||||
{
|
||||
$is_html_content = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oEditorModel = getModel('editor');
|
||||
$editor_config = $oEditorModel->getEditorConfig($obj->module_srl);
|
||||
|
||||
if(strpos($editor_config->sel_comment_editor_colorset, 'nohtml') !== FALSE)
|
||||
{
|
||||
$obj->content = preg_replace('/\<br(\s*)?\/?\>/i', PHP_EOL, $obj->content);
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
$obj->content = str_replace(array("\r\n", "\r", "\n"), '<br />', $obj->content);
|
||||
}
|
||||
$is_html_content = is_html_content($obj->content);
|
||||
}
|
||||
|
||||
if (!$is_html_content)
|
||||
{
|
||||
$obj->content = nl2br($obj->use_html === 'Y' ? $obj->content : escape($obj->content, false));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -457,27 +457,30 @@ class documentController extends document
|
|||
// if use editor of nohtml, Remove HTML tags from the contents.
|
||||
if(!$manual_inserted)
|
||||
{
|
||||
if(Mobile::isFromMobilePhone() && $obj->use_editor != 'Y')
|
||||
$editor_config = getModel('editor')->getEditorConfig($obj->module_srl);
|
||||
if (strpos($editor_config->sel_editor_colorset, 'nohtml') !== false)
|
||||
{
|
||||
if($obj->use_html != 'Y')
|
||||
{
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
}
|
||||
$obj->content = nl2br($obj->content);
|
||||
$is_html_content = false;
|
||||
}
|
||||
elseif ($obj->use_editor === 'Y' || $obj->use_html === 'Y')
|
||||
{
|
||||
$is_html_content = true;
|
||||
}
|
||||
elseif ($obj->use_editor === 'N' || $obj->use_html === 'N')
|
||||
{
|
||||
$is_html_content = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oEditorModel = getModel('editor');
|
||||
$editor_config = $oEditorModel->getEditorConfig($obj->module_srl);
|
||||
|
||||
if(strpos($editor_config->sel_editor_colorset, 'nohtml') !== FALSE)
|
||||
{
|
||||
$obj->content = preg_replace('/\<br(\s*)?\/?\>/i', PHP_EOL, $obj->content);
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
$obj->content = str_replace(array("\r\n", "\r", "\n"), '<br />', $obj->content);
|
||||
}
|
||||
$is_html_content = is_html_content($obj->content);
|
||||
}
|
||||
|
||||
if (!$is_html_content)
|
||||
{
|
||||
$obj->content = nl2br($obj->use_html === 'Y' ? $obj->content : escape($obj->content, false));
|
||||
}
|
||||
}
|
||||
|
||||
// Remove iframe and script if not a top adminisrator in the session.
|
||||
if($logged_info->is_admin != 'Y') $obj->content = removeHackTag($obj->content);
|
||||
// An error appears if both log-in info and user name don't exist.
|
||||
|
|
@ -713,27 +716,30 @@ class documentController extends document
|
|||
// if use editor of nohtml, Remove HTML tags from the contents.
|
||||
if(!$manual_updated)
|
||||
{
|
||||
if(Mobile::isFromMobilePhone() && $obj->use_editor != 'Y')
|
||||
$editor_config = getModel('editor')->getEditorConfig($obj->module_srl);
|
||||
if (strpos($editor_config->sel_editor_colorset, 'nohtml') !== false)
|
||||
{
|
||||
if($obj->use_html != 'Y')
|
||||
{
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
}
|
||||
$obj->content = nl2br($obj->content);
|
||||
$is_html_content = false;
|
||||
}
|
||||
elseif ($obj->use_editor === 'Y' || $obj->use_html === 'Y')
|
||||
{
|
||||
$is_html_content = true;
|
||||
}
|
||||
elseif ($obj->use_editor === 'N' || $obj->use_html === 'N')
|
||||
{
|
||||
$is_html_content = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
$oEditorModel = getModel('editor');
|
||||
$editor_config = $oEditorModel->getEditorConfig($obj->module_srl);
|
||||
|
||||
if(strpos($editor_config->sel_editor_colorset, 'nohtml') !== FALSE)
|
||||
{
|
||||
$obj->content = preg_replace('/\<br(\s*)?\/?\>/i', PHP_EOL, $obj->content);
|
||||
$obj->content = htmlspecialchars($obj->content, ENT_COMPAT | ENT_HTML401, 'UTF-8', false);
|
||||
$obj->content = str_replace(array("\r\n", "\r", "\n"), '<br />', $obj->content);
|
||||
}
|
||||
$is_html_content = is_html_content($obj->content);
|
||||
}
|
||||
|
||||
if (!$is_html_content)
|
||||
{
|
||||
$obj->content = nl2br($obj->use_html === 'Y' ? $obj->content : escape($obj->content, false));
|
||||
}
|
||||
}
|
||||
|
||||
// Change not extra vars but language code of the original document if document's lang_code is different from author's setting.
|
||||
if($source_obj->get('lang_code') != Context::getLangType())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -45,10 +45,8 @@ var auto_saved_msg = "{$lang->msg_auto_saved}";
|
|||
</block>
|
||||
|
||||
<script>
|
||||
(function($){
|
||||
"use strict";
|
||||
// editor
|
||||
$(function(){
|
||||
"use strict";
|
||||
<!--@if(!FileHandler::exists('common/js/plugins/ckeditor/ckeditor/config.js'))-->CKEDITOR.config.customConfig = '';<!--@endif-->
|
||||
|
||||
// Import CSS content from PHP.
|
||||
|
|
@ -69,7 +67,9 @@ var auto_saved_msg = "{$lang->msg_auto_saved}";
|
|||
}
|
||||
}
|
||||
var font_list = [];
|
||||
<block loop="$lang->edit->fontlist => $fontname">font_list.push({json_encode($fontname)});</block>
|
||||
<!--@foreach($lang->edit->fontlist as $fontname)-->
|
||||
font_list.push({json_encode($fontname)});
|
||||
<!--@endforeach-->
|
||||
if (default_font_fullname !== null && !$.inArray(default_font_fullname, font_list)) {
|
||||
font_list.push(default_font_fullname);
|
||||
}
|
||||
|
|
@ -89,6 +89,7 @@ var auto_saved_msg = "{$lang->msg_auto_saved}";
|
|||
return val + "/" + val + "px";
|
||||
}).join(";");
|
||||
|
||||
// Initialize CKEditor settings.
|
||||
var settings = {
|
||||
ckeconfig: {
|
||||
height: '{$editor_height}',
|
||||
|
|
@ -108,11 +109,13 @@ var auto_saved_msg = "{$lang->msg_auto_saved}";
|
|||
content_field: jQuery('[name={$editor_content_key_name}]')
|
||||
};
|
||||
|
||||
// Temporary workaround for line break bug in recent versions of iOS.
|
||||
if (navigator.userAgent.match(/i(OS|Phone|Pad)/)) {
|
||||
settings.ckeconfig.enterMode = CKEDITOR.ENTER_BR;
|
||||
settings.ckeconfig.shiftEnterMode = CKEDITOR.ENTER_P;
|
||||
}
|
||||
|
||||
// Prevent removal of icon fonts and Google code.
|
||||
CKEDITOR.dtd.$removeEmpty.i = 0;
|
||||
CKEDITOR.dtd.$removeEmpty.ins = 0;
|
||||
|
||||
|
|
@ -157,7 +160,22 @@ var auto_saved_msg = "{$lang->msg_auto_saved}";
|
|||
|
||||
CKEDITOR.addCss(css_content);
|
||||
|
||||
// Initialize CKEditor.
|
||||
var ckeApp = $('#ckeditor_instance_{$editor_sequence}').XeCkEditor(settings);
|
||||
|
||||
// Add use_editor and use_html fields to parent form.
|
||||
var parentform = $('#ckeditor_instance_{$editor_sequence}').parents('form');
|
||||
var use_editor = parentform.find("input[name='use_editor']");
|
||||
var use_html = parentform.find("input[name='use_html']");
|
||||
if (use_editor.size()) {
|
||||
use_editor.val("Y");
|
||||
} else {
|
||||
parentform.append('<input type="hidden" name="use_editor" value="Y" />');
|
||||
}
|
||||
if (use_html.size()) {
|
||||
use_html.val("Y");
|
||||
} else {
|
||||
parentform.append('<input type="hidden" name="use_html" value="Y" />');
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -28,9 +28,24 @@
|
|||
|
||||
// Save edited content
|
||||
textarea.on("change", function() {
|
||||
content_input.val("<p>" + String($(this).val()).escape().replace(/\r?\n/, "</p>\n<p>") + "</p>");
|
||||
content_input.val("<p>" + String($(this).val()).escape().replace(/\r?\n/g, "</p>\n<p>") + "</p>");
|
||||
});
|
||||
|
||||
// Add use_editor and use_html fields to parent form.
|
||||
var parentform = $('#textarea_instance_{$editor_sequence}').parents('form');
|
||||
var use_editor = parentform.find("input[name='use_editor']");
|
||||
var use_html = parentform.find("input[name='use_html']");
|
||||
if (use_editor.size()) {
|
||||
use_editor.val("Y");
|
||||
} else {
|
||||
parentform.append('<input type="hidden" name="use_editor" value="Y" />');
|
||||
}
|
||||
if (use_html.size()) {
|
||||
use_html.val("Y");
|
||||
} else {
|
||||
parentform.append('<input type="hidden" name="use_html" value="Y" />');
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -168,6 +168,24 @@ class FunctionsTest extends \Codeception\TestCase\Test
|
|||
$this->assertEquals("Trimmed", utf8_trim("\x20\xe2\x80\x80Trimmed\x0a\x0c\x07\x09"));
|
||||
}
|
||||
|
||||
public function testIsHTMLContent()
|
||||
{
|
||||
$this->assertTrue(is_html_content("<p>Hello World</p>"));
|
||||
$this->assertTrue(is_html_content("Hello World<br>"));
|
||||
$this->assertTrue(is_html_content("Hello World<br/>"));
|
||||
$this->assertTrue(is_html_content("Hello<br />\nWorld"));
|
||||
$this->assertTrue(is_html_content("<p class='foo'>Hello</p>\n<p class='bar'>World</p>"));
|
||||
$this->assertTrue(is_html_content("<div>Hello<br>\r\n\n\n\n\nWorld</div>"));
|
||||
$this->assertTrue(is_html_content('<p style="margin-top:16px">이럴 때는 <p> 태그나 <span> 태그를 사용해야 합니다.</p>'));
|
||||
$this->assertTrue(is_html_content('This is <span style="font-style:italic">italic</span> text.'));
|
||||
$this->assertFalse(is_html_content('This is an empty <span></span> tag. Most editors don\'t produce these.'));
|
||||
$this->assertFalse(is_html_content('The <p class="foobar"> tag is the most appropriate here.'));
|
||||
$this->assertFalse(is_html_content("이럴 때는 <p> 태그나 <span> 태그를 사용해야 합니다."));
|
||||
$this->assertFalse(is_html_content("This is multiline content.\n<p> tag is here.\nOther lines are here, too.<br>\nMost lines don't have any tags."));
|
||||
$this->assertFalse(is_html_content("<p> tag is unbalanced here.\nAnother line!<br />\nAnd a dangling line..."));
|
||||
$this->assertFalse(is_html_content("Looks like a broken editor<br />\nthat produced\nthis kind of\nstring!</div>"));
|
||||
}
|
||||
|
||||
public function testIsEmptyHTMLContent()
|
||||
{
|
||||
$this->assertTrue(is_empty_html_content('<p> <br><br></p>'));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue