Skip to content

Commit

Permalink
Merge pull request #2 from alromh87/master
Browse files Browse the repository at this point in the history
Enhance filterHTML Regexp to handle self closing tags
  • Loading branch information
Raj authored Sep 22, 2020
2 parents 2da440a + 3945449 commit 2a6ef97
Show file tree
Hide file tree
Showing 2 changed files with 197 additions and 117 deletions.
218 changes: 135 additions & 83 deletions editormd.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* @license MIT License
* @author Pandao
* {@link https://github.com/pandao/editor.md}
* @updateTime 2015-06-09
* @updateTime 2020-09-17
*/

;(function(factory) {
Expand Down Expand Up @@ -363,9 +363,8 @@
options = id;
}

var _this = this;
var classPrefix = this.classPrefix = editormd.classPrefix;
var settings = this.settings = $.extend(true, {}, editormd.defaults, options);
var settings = this.settings = $.extend(true, editormd.defaults, options);

id = (typeof id === "object") ? settings.id : id;

Expand Down Expand Up @@ -813,7 +812,6 @@
}

var cm = this.cm;
var editor = this.editor;
var count = cm.lineCount();
var preview = this.preview;

Expand Down Expand Up @@ -1112,7 +1110,6 @@
}

var editor = this.editor;
var preview = this.preview;
var classPrefix = this.classPrefix;

var toolbar = this.toolbar = editor.children("." + classPrefix + "toolbar");
Expand Down Expand Up @@ -1247,7 +1244,7 @@
var toolbarIcons = this.toolbarIcons = toolbar.find("." + classPrefix + "menu > li > a");
var toolbarIconHandlers = this.getToolbarHandles();

toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function(event) {
toolbarIcons.bind(editormd.mouseOrTouch("click", "touchend"), function() {

var icon = $(this).children(".fa");
var name = icon.attr("name");
Expand Down Expand Up @@ -1371,8 +1368,7 @@

$("html,body").css("overflow-x", "hidden");

var _this = this;
var editor = this.editor;
var editor = this.editor;
var settings = this.settings;
var infoDialog = this.infoDialog = editor.children("." + this.classPrefix + "dialog-info");

Expand Down Expand Up @@ -1434,7 +1430,6 @@
*/

recreate : function() {
var _this = this;
var editor = this.editor;
var settings = this.settings;

Expand Down Expand Up @@ -1629,18 +1624,15 @@
{
case 120:
$.proxy(toolbarHandlers["watch"], _this)();
return false;
break;
return false;

case 121:
$.proxy(toolbarHandlers["preview"], _this)();
return false;
break;
return false;

case 122:
$.proxy(toolbarHandlers["fullscreen"], _this)();
return false;
break;
return false;

default:
break;
Expand Down Expand Up @@ -1965,15 +1957,14 @@

save : function() {

var _this = this;
var state = this.state;
var settings = this.settings;

if (timer === null && !(!settings.watch && state.preview))
if (timer === null)
{
return this;
}

var _this = this;
var state = this.state;
var settings = this.settings;
var cm = this.cm;
var cmValue = cm.getValue();
var previewContainer = this.previewContainer;
Expand Down Expand Up @@ -3183,17 +3174,20 @@
}
};

var isMac = navigator.platform.toUpperCase().indexOf('MAC')>=0;
var key = isMac ? "Cmd" : "Ctrl";

editormd.keyMaps = {
"Ctrl-1" : "h1",
"Ctrl-2" : "h2",
"Ctrl-3" : "h3",
"Ctrl-4" : "h4",
"Ctrl-5" : "h5",
"Ctrl-6" : "h6",
"Ctrl-B" : "bold", // if this is string == editormd.toolbarHandlers.xxxx
"Ctrl-D" : "datetime",

"Ctrl-E" : function() { // emoji
[key + "-1"] : "h1",
[key + "-2"] : "h2",
[key + "-3"] : "h3",
[key + "-4"] : "h4",
[key + "-5"] : "h5",
[key + "-6"] : "h6",
[key + "-B"] : "bold", // if this is string == editormd.toolbarHandlers.xxxx
[key + "-D"] : "datetime",

[key + "Ctrl-E"] : function() { // emoji
var cm = this.cm;
var cursor = cm.getCursor();
var selection = cm.getSelection();
Expand All @@ -3210,10 +3204,10 @@
cm.setCursor(cursor.line, cursor.ch + 1);
}
},
"Ctrl-Alt-G" : "goto-line",
"Ctrl-H" : "hr",
"Ctrl-I" : "italic",
"Ctrl-K" : "code",
[key + "-Alt-G"] : "goto-line",
[key + "-H"] : "hr",
[key + "-I"] : "italic",
[key + "-K"] : "code",

"Ctrl-L" : function() {
var cm = this.cm;
Expand All @@ -3228,7 +3222,7 @@
cm.setCursor(cursor.line, cursor.ch + 1);
}
},
"Ctrl-U" : "list-ul",
[key + "-U"] : "list-ul",

"Shift-Ctrl-A" : function() {
var cm = this.cm;
Expand All @@ -3248,10 +3242,10 @@
}
},

"Shift-Ctrl-C" : "code",
"Shift-Ctrl-Q" : "quote",
"Shift-Ctrl-S" : "del",
"Shift-Ctrl-K" : "tex", // KaTeX
["Shift" + key + "-C"] : "code",
["Shift" + key + "Q"] : "quote",
["Shift" + key + "S"] : "del",
["Shift" + key + "K"] : "tex", // KaTeX

"Shift-Alt-C" : function() {
var cm = this.cm;
Expand All @@ -3265,16 +3259,16 @@
}
},

"Shift-Ctrl-Alt-C" : "code-block",
"Shift-Ctrl-H" : "html-entities",
"Shift-Alt-H" : "help",
"Shift-Ctrl-E" : "emoji",
"Shift-Ctrl-U" : "uppercase",
"Shift-Alt-U" : "ucwords",
"Shift-Ctrl-Alt-U" : "ucfirst",
"Shift-Alt-L" : "lowercase",
["Shift-" + key + "-Alt-C"] : "code-block",
["Shift-" + key + "-H"] : "html-entities",
"Shift-Alt-H" : "help",
["Shift-" + key + "-E"] : "emoji",
["Shift-" + key + "-U"] : "uppercase",
"Shift-Alt-U" : "ucwords",
["Shift-" + key + "-Alt-U"] : "ucfirst",
"Shift-Alt-L" : "lowercase",

"Shift-Ctrl-I" : function() {
["Shift-" + key + "-I"] : function() {
var cm = this.cm;
var cursor = cm.getCursor();
var selection = cm.getSelection();
Expand All @@ -3288,15 +3282,15 @@
}
},

"Shift-Ctrl-Alt-I" : "image",
"Shift-Ctrl-L" : "link",
"Shift-Ctrl-O" : "list-ol",
"Shift-Ctrl-P" : "preformatted-text",
"Shift-Ctrl-T" : "table",
"Shift-Alt-P" : "pagebreak",
"F9" : "watch",
"F10" : "preview",
"F11" : "fullscreen",
["Shift-" + key + "-Alt-I"] : "image",
["Shift-" + key + "-L"] : "link",
["Shift-" + key + "-O"] : "list-ol",
["Shift-" + key + "-P"] : "preformatted-text",
["Shift-" + key + "-T"] : "table",
"Shift-Alt-P" : "pagebreak",
"F9" : "watch",
"F10" : "preview",
"F11" : "fullscreen",
};

/**
Expand Down Expand Up @@ -3356,7 +3350,7 @@
email : /(\w+)@(\w+)\.(\w+)\.?(\w+)?/g,
emailLink : /(mailto:)?([\w\.\_]+)@(\w+)\.(\w+)\.?(\w+)?/g,
emoji : /:([\w\+-]+):/g,
emojiDatetime : /(\d{2}:\d{2}:\d{2})/g,
emojiDatetime : /(\d{1,2}:\d{1,2}:\d{1,2})/g,
twemoji : /:(tw-([\w]+)-?(\w+)?):/g,
fontAwesome : /:(fa-([\w]+)(-(\w+)){0,}):/g,
editormdLogo : /:(editormd-logo-?(\w+)?):/g,
Expand All @@ -3365,7 +3359,7 @@

// Emoji graphics files url path
editormd.emoji = {
path : "https://www.webpagefx.com/tools/emoji-cheat-sheet/graphics/emojis/",
path : "http://www.emoji-cheat-sheet.com/graphics/emojis/",
ext : ".png"
};

Expand Down Expand Up @@ -3808,68 +3802,126 @@
*/

editormd.filterHTMLTags = function(html, filters) {


const basicAttrs ={
'img': 'src',
'a': 'href'
}

if (typeof html !== "string") {
html = new String(html);
}


try{
html = decodeURI(html)
}catch(error){
return "Invalid encoding detected"
}
if (typeof filters !== "string") {
return html;
// If no filters set use "script|on*" by default to avoid XSS
filters = "script|on*";
}

var expression = filters.split("|");
var filterTags = expression[0].split(",");
var attrs = expression[1];

if(!filterTags.includes('allowScript') && !filterTags.includes('script'))
{
// Only allow script if requested specifically
filterTags.push('script');
}

for (var i = 0, len = filterTags.length; i < len; i++)
{
var tag = filterTags[i];

html = html.replace(new RegExp("\<\s*" + tag + "\s*([^\>]*)\>([^\>]*)\<\s*\/" + tag + "\s*\>", "igm"), "");
html = html.replace(new RegExp("\<\s*" + tag + "\s*([^\>]*)\>(?:([^\>]*)\<\s*\/" + tag + "\s*\>)?", "igm"), "");

}

//return html;

if (typeof attrs === "undefined")
{
// If no attrs set, block "on*" to avoid XSS
attrs = "on*"
}

if (typeof attrs !== "undefined")
{
var htmlTagRegex = /\<(\w+)\s*([^\>]*)\>([^\>]*)\<\/(\w+)\>/ig;
var htmlTagRegex = /\<(\w+)\s*([^\>]*)\>(?:([^\>]*)\<\/(\1)\>)?/ig;

var filterAttrs = attrs.split(",");
var filterOn = true;

if(filterAttrs.includes('allowOn'))
{
// Only allow on* if requested specifically
filterOn = false;
}

if (attrs === "*")
{
html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) {
return "<" + $2 + ">" + $4 + "</" + $5 + ">";
});
// Add basic attrs to elements that need them
Object.entries(basicAttrs).forEach( item =>
{
var match;
if(item[0].toUpperCase() === $2.toUpperCase())
{
var regBas = new RegExp(item[1]+`\s*=\s*("|')(?:(?!\\1).)*\\1`,"i");
if(match = regBas.exec($3)){
$2 += ' ' + match[0];
}
}
});
if(typeof($4)!== 'undefined'){
return "<" + $2 + ">" + $4 + "</" + $5 + ">";
}else{
return "<" + $2 + "/>";
}
});
}
else if (attrs === "on*")
else if ((attrs === "on*") || filterOn)
{

html = html.replace(htmlTagRegex, function($1, $2, $3, $4, $5) {
var el = $("<" + $2 + ">" + $4 + "</" + $5 + ">");
var _attrs = $($1)[0].attributes;
var el;
try{
if(typeof($4)!== 'undefined'){
el = $("<" + $2 + ">" + $4 + "</" + $5 + ">");
}else{
el = $("<" + $2 + "/>");
}
} catch (error){
console.log('Trying to create invalid element');
return '';
}
// var _attrs = $($1)[0].attributes; // ARH: Replace with regexp, beacause this triggers execution of onLoad ... (Also should be faster now)
var match;
var $attrs = {};

$.each(_attrs, function(i, e) {
if (e.nodeName !== '"') $attrs[e.nodeName] = e.nodeValue;
});

$.each($attrs, function(i) {
if (i.indexOf("on") === 0) {
delete $attrs[i];
var regOn = /^on*/i

var regAttr = /(\w*)\s*=\s*("|')((?:(?!\2).)*)\2/gi;
while(match = regAttr.exec($3)){
if (!regOn.exec(match[1]) && match[1].length>0){
$attrs[match[1]] = match[3];
}
});

}
el.attr($attrs);

var text = (typeof el[1] !== "undefined") ? $(el[1]).text() : "";

return el[0].outerHTML + text;
});
}
else
if(filterAttrs.length > 1 || (filterAttrs[0]!=="*" && filterAttrs[0]!=="on*"))
{
html = html.replace(htmlTagRegex, function($1, $2, $3, $4) {
var filterAttrs = attrs.split(",");
var el = $($1);
el.html($4);
if(typeof($4)!== 'undefined'){
el.html($4);
}

$.each(filterAttrs, function(i) {
el.attr(filterAttrs[i], null);
Expand Down
Loading

0 comments on commit 2a6ef97

Please sign in to comment.