Last active
April 17, 2018 19:45
-
-
Save tomjn/d10a52b7a339d9d076c7 to your computer and use it in GitHub Desktop.
Adds a shortcode to WordPress that lets you test escaping and sanitising functions on content
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=== Escaping Checker === | |
Contributors: tjnowell | |
Donate link: https://tomjn.com/ | |
Tags: security | |
Requires at least: 4.3 | |
Tested up to: 4.95 | |
Stable tag: 1.1 | |
License: GPLv2 or later | |
License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
A handy tool for checking the output of escaping, sanitization and validation functions | |
== Description == | |
This plugin adds a shortcode that when used inserts an escaping checker. The checker gives you a form you can enter potentially unsafe content into, and when submitted, passes that content through every sanitisation, validation and escaping function in WordPress Core, and some PHP Core functions | |
== Installation == | |
1. Upload the plugin folder into the `/wp-content/plugins/` directory | |
1. Activate the plugin through the 'Plugins' menu in WordPress | |
1. Place the `[tomjn_escaping_tests]` in a page or post and save | |
If you prefer to create a dedicate page template, use `echo tomjn_escaping_tests();` | |
== Frequently Asked Questions == | |
= There's a Lot of Escaping Functions! = | |
Yes! But not every function listed here is an escaping function, there are validation and sanitising functions too, some of them are PHP Core functions rather than WordPress functions | |
== Screenshots == | |
1. The escaping form | |
== Changelog == | |
= 1.1 = | |
* Put a green or yellow border around output depending on wether it matches the original input | |
* Bumped tested WP version to 4.9.5 | |
= 1.0 = | |
* Added `behave.js` to make typing content easier | |
== Upgrade Notice == | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Behave.js | |
* | |
* Copyright 2013, Jacob Kelley - http://jakiestfu.com/ | |
* Released under the MIT Licence | |
* http://opensource.org/licenses/MIT | |
* | |
* Github: http://github.com/jakiestfu/Behave.js/ | |
* Version: 1.5 | |
*/ | |
(function(undefined){ | |
'use strict'; | |
var BehaveHooks = BehaveHooks || (function(){ | |
var hooks = {}; | |
return { | |
add: function(hookName, fn){ | |
if(typeof hookName == "object"){ | |
var i; | |
for(i=0; i<hookName.length; i++){ | |
var theHook = hookName[i]; | |
if(!hooks[theHook]){ | |
hooks[theHook] = []; | |
} | |
hooks[theHook].push(fn); | |
} | |
} else { | |
if(!hooks[hookName]){ | |
hooks[hookName] = []; | |
} | |
hooks[hookName].push(fn); | |
} | |
}, | |
get: function(hookName){ | |
if(hooks[hookName]){ | |
return hooks[hookName]; | |
} | |
} | |
}; | |
})(), | |
Behave = Behave || function (userOpts) { | |
if (typeof String.prototype.repeat !== 'function') { | |
String.prototype.repeat = function(times) { | |
if(times < 1){ | |
return ''; | |
} | |
if(times % 2){ | |
return this.repeat(times - 1) + this; | |
} | |
var half = this.repeat(times / 2); | |
return half + half; | |
}; | |
} | |
if (typeof Array.prototype.filter !== 'function') { | |
Array.prototype.filter = function(func /*, thisp */) { | |
if (this === null) { | |
throw new TypeError(); | |
} | |
var t = Object(this), | |
len = t.length >>> 0; | |
if (typeof func != "function"){ | |
throw new TypeError(); | |
} | |
var res = [], | |
thisp = arguments[1]; | |
for (var i = 0; i < len; i++) { | |
if (i in t) { | |
var val = t[i]; | |
if (func.call(thisp, val, i, t)) { | |
res.push(val); | |
} | |
} | |
} | |
return res; | |
}; | |
} | |
var defaults = { | |
textarea: null, | |
replaceTab: true, | |
softTabs: true, | |
tabSize: 4, | |
autoOpen: true, | |
overwrite: true, | |
autoStrip: true, | |
autoIndent: true, | |
fence: false | |
}, | |
tab, | |
newLine, | |
charSettings = { | |
keyMap: [ | |
{ open: "\"", close: "\"", canBreak: false }, | |
{ open: "'", close: "'", canBreak: false }, | |
{ open: "(", close: ")", canBreak: false }, | |
{ open: "[", close: "]", canBreak: true }, | |
{ open: "{", close: "}", canBreak: true } | |
] | |
}, | |
utils = { | |
_callHook: function(hookName, passData){ | |
var hooks = BehaveHooks.get(hookName); | |
passData = typeof passData=="boolean" && passData === false ? false : true; | |
if(hooks){ | |
if(passData){ | |
var theEditor = defaults.textarea, | |
textVal = theEditor.value, | |
caretPos = utils.cursor.get(), | |
i; | |
for(i=0; i<hooks.length; i++){ | |
hooks[i].call(undefined, { | |
editor: { | |
element: theEditor, | |
text: textVal, | |
levelsDeep: utils.levelsDeep() | |
}, | |
caret: { | |
pos: caretPos | |
}, | |
lines: { | |
current: utils.cursor.getLine(textVal, caretPos), | |
total: utils.editor.getLines(textVal) | |
} | |
}); | |
} | |
} else { | |
for(i=0; i<hooks.length; i++){ | |
hooks[i].call(undefined); | |
} | |
} | |
} | |
}, | |
defineNewLine: function(){ | |
var ta = document.createElement('textarea'); | |
ta.value = "\n"; | |
if(ta.value.length==2){ | |
newLine = "\r\n"; | |
} else { | |
newLine = "\n"; | |
} | |
}, | |
defineTabSize: function(tabSize){ | |
if(typeof defaults.textarea.style.OTabSize != "undefined"){ | |
defaults.textarea.style.OTabSize = tabSize; return; | |
} | |
if(typeof defaults.textarea.style.MozTabSize != "undefined"){ | |
defaults.textarea.style.MozTabSize = tabSize; return; | |
} | |
if(typeof defaults.textarea.style.tabSize != "undefined"){ | |
defaults.textarea.style.tabSize = tabSize; return; | |
} | |
}, | |
cursor: { | |
getLine: function(textVal, pos){ | |
return ((textVal.substring(0,pos)).split("\n")).length; | |
}, | |
get: function() { | |
if (typeof document.createElement('textarea').selectionStart==="number") { | |
return defaults.textarea.selectionStart; | |
} else if (document.selection) { | |
var caretPos = 0, | |
range = defaults.textarea.createTextRange(), | |
rangeDupe = document.selection.createRange().duplicate(), | |
rangeDupeBookmark = rangeDupe.getBookmark(); | |
range.moveToBookmark(rangeDupeBookmark); | |
while (range.moveStart('character' , -1) !== 0) { | |
caretPos++; | |
} | |
return caretPos; | |
} | |
}, | |
set: function (start, end) { | |
if(!end){ | |
end = start; | |
} | |
if (defaults.textarea.setSelectionRange) { | |
defaults.textarea.focus(); | |
defaults.textarea.setSelectionRange(start, end); | |
} else if (defaults.textarea.createTextRange) { | |
var range = defaults.textarea.createTextRange(); | |
range.collapse(true); | |
range.moveEnd('character', end); | |
range.moveStart('character', start); | |
range.select(); | |
} | |
}, | |
selection: function(){ | |
var textAreaElement = defaults.textarea, | |
start = 0, | |
end = 0, | |
normalizedValue, | |
range, | |
textInputRange, | |
len, | |
endRange; | |
if (typeof textAreaElement.selectionStart == "number" && typeof textAreaElement.selectionEnd == "number") { | |
start = textAreaElement.selectionStart; | |
end = textAreaElement.selectionEnd; | |
} else { | |
range = document.selection.createRange(); | |
if (range && range.parentElement() == textAreaElement) { | |
normalizedValue = utils.editor.get(); | |
len = normalizedValue.length; | |
textInputRange = textAreaElement.createTextRange(); | |
textInputRange.moveToBookmark(range.getBookmark()); | |
endRange = textAreaElement.createTextRange(); | |
endRange.collapse(false); | |
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) { | |
start = end = len; | |
} else { | |
start = -textInputRange.moveStart("character", -len); | |
start += normalizedValue.slice(0, start).split(newLine).length - 1; | |
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) { | |
end = len; | |
} else { | |
end = -textInputRange.moveEnd("character", -len); | |
end += normalizedValue.slice(0, end).split(newLine).length - 1; | |
} | |
} | |
} | |
} | |
return start==end ? false : { | |
start: start, | |
end: end | |
}; | |
} | |
}, | |
editor: { | |
getLines: function(textVal){ | |
return (textVal).split("\n").length; | |
}, | |
get: function(){ | |
return defaults.textarea.value.replace(/\r/g,''); | |
}, | |
set: function(data){ | |
defaults.textarea.value = data; | |
} | |
}, | |
fenceRange: function(){ | |
if(typeof defaults.fence == "string"){ | |
var data = utils.editor.get(), | |
pos = utils.cursor.get(), | |
hacked = 0, | |
matchedFence = data.indexOf(defaults.fence), | |
matchCase = 0; | |
while(matchedFence>=0){ | |
matchCase++; | |
if( pos < (matchedFence+hacked) ){ | |
break; | |
} | |
hacked += matchedFence+defaults.fence.length; | |
data = data.substring(matchedFence+defaults.fence.length); | |
matchedFence = data.indexOf(defaults.fence); | |
} | |
if( (hacked) < pos && ( (matchedFence+hacked) > pos ) && matchCase%2===0){ | |
return true; | |
} | |
return false; | |
} else { | |
return true; | |
} | |
}, | |
isEven: function(_this,i){ | |
return i%2; | |
}, | |
levelsDeep: function(){ | |
var pos = utils.cursor.get(), | |
val = utils.editor.get(); | |
var left = val.substring(0, pos), | |
levels = 0, | |
i, j; | |
for(i=0; i<left.length; i++){ | |
for (j=0; j<charSettings.keyMap.length; j++) { | |
if(charSettings.keyMap[j].canBreak){ | |
if(charSettings.keyMap[j].open == left.charAt(i)){ | |
levels++; | |
} | |
if(charSettings.keyMap[j].close == left.charAt(i)){ | |
levels--; | |
} | |
} | |
} | |
} | |
var toDecrement = 0, | |
quoteMap = ["'", "\""]; | |
for(i=0; i<charSettings.keyMap.length; i++) { | |
if(charSettings.keyMap[i].canBreak){ | |
for(j in quoteMap){ | |
toDecrement += left.split(quoteMap[j]).filter(utils.isEven).join('').split(charSettings.keyMap[i].open).length - 1; | |
} | |
} | |
} | |
var finalLevels = levels - toDecrement; | |
return finalLevels >=0 ? finalLevels : 0; | |
}, | |
deepExtend: function(destination, source) { | |
for (var property in source) { | |
if (source[property] && source[property].constructor && | |
source[property].constructor === Object) { | |
destination[property] = destination[property] || {}; | |
utils.deepExtend(destination[property], source[property]); | |
} else { | |
destination[property] = source[property]; | |
} | |
} | |
return destination; | |
}, | |
addEvent: function addEvent(element, eventName, func) { | |
if (element.addEventListener){ | |
element.addEventListener(eventName,func,false); | |
} else if (element.attachEvent) { | |
element.attachEvent("on"+eventName, func); | |
} | |
}, | |
removeEvent: function addEvent(element, eventName, func){ | |
if (element.addEventListener){ | |
element.removeEventListener(eventName,func,false); | |
} else if (element.attachEvent) { | |
element.detachEvent("on"+eventName, func); | |
} | |
}, | |
preventDefaultEvent: function(e){ | |
if(e.preventDefault){ | |
e.preventDefault(); | |
} else { | |
e.returnValue = false; | |
} | |
} | |
}, | |
intercept = { | |
tabKey: function (e) { | |
if(!utils.fenceRange()){ return; } | |
if (e.keyCode == 9) { | |
utils.preventDefaultEvent(e); | |
var toReturn = true; | |
utils._callHook('tab:before'); | |
var selection = utils.cursor.selection(), | |
pos = utils.cursor.get(), | |
val = utils.editor.get(); | |
if(selection){ | |
var tempStart = selection.start; | |
while(tempStart--){ | |
if(val.charAt(tempStart)=="\n"){ | |
selection.start = tempStart + 1; | |
break; | |
} | |
} | |
var toIndent = val.substring(selection.start, selection.end), | |
lines = toIndent.split("\n"), | |
i; | |
if(e.shiftKey){ | |
for(i = 0; i<lines.length; i++){ | |
if(lines[i].substring(0,tab.length) == tab){ | |
lines[i] = lines[i].substring(tab.length); | |
} | |
} | |
toIndent = lines.join("\n"); | |
utils.editor.set( val.substring(0,selection.start) + toIndent + val.substring(selection.end) ); | |
utils.cursor.set(selection.start, selection.start+toIndent.length); | |
} else { | |
for(i in lines){ | |
lines[i] = tab + lines[i]; | |
} | |
toIndent = lines.join("\n"); | |
utils.editor.set( val.substring(0,selection.start) + toIndent + val.substring(selection.end) ); | |
utils.cursor.set(selection.start, selection.start+toIndent.length); | |
} | |
} else { | |
var left = val.substring(0, pos), | |
right = val.substring(pos), | |
edited = left + tab + right; | |
if(e.shiftKey){ | |
if(val.substring(pos-tab.length, pos) == tab){ | |
edited = val.substring(0, pos-tab.length) + right; | |
utils.editor.set(edited); | |
utils.cursor.set(pos-tab.length); | |
} | |
} else { | |
utils.editor.set(edited); | |
utils.cursor.set(pos + tab.length); | |
toReturn = false; | |
} | |
} | |
utils._callHook('tab:after'); | |
} | |
return toReturn; | |
}, | |
enterKey: function (e) { | |
if(!utils.fenceRange()){ return; } | |
if (e.keyCode == 13) { | |
utils.preventDefaultEvent(e); | |
utils._callHook('enter:before'); | |
var pos = utils.cursor.get(), | |
val = utils.editor.get(), | |
left = val.substring(0, pos), | |
right = val.substring(pos), | |
leftChar = left.charAt(left.length - 1), | |
rightChar = right.charAt(0), | |
numTabs = utils.levelsDeep(), | |
ourIndent = "", | |
closingBreak = "", | |
finalCursorPos, | |
i; | |
if(!numTabs){ | |
finalCursorPos = 1; | |
} else { | |
while(numTabs--){ | |
ourIndent+=tab; | |
} | |
ourIndent = ourIndent; | |
finalCursorPos = ourIndent.length + 1; | |
for(i=0; i<charSettings.keyMap.length; i++) { | |
if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar){ | |
closingBreak = newLine; | |
} | |
} | |
} | |
var edited = left + newLine + ourIndent + closingBreak + (ourIndent.substring(0, ourIndent.length-tab.length) ) + right; | |
utils.editor.set(edited); | |
utils.cursor.set(pos + finalCursorPos); | |
utils._callHook('enter:after'); | |
} | |
}, | |
deleteKey: function (e) { | |
if(!utils.fenceRange()){ return; } | |
if(e.keyCode == 8){ | |
utils.preventDefaultEvent(e); | |
utils._callHook('delete:before'); | |
var pos = utils.cursor.get(), | |
val = utils.editor.get(), | |
left = val.substring(0, pos), | |
right = val.substring(pos), | |
leftChar = left.charAt(left.length - 1), | |
rightChar = right.charAt(0), | |
i; | |
if( utils.cursor.selection() === false ){ | |
for(i=0; i<charSettings.keyMap.length; i++) { | |
if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar) { | |
var edited = val.substring(0,pos-1) + val.substring(pos+1); | |
utils.editor.set(edited); | |
utils.cursor.set(pos - 1); | |
return; | |
} | |
} | |
var edited = val.substring(0,pos-1) + val.substring(pos); | |
utils.editor.set(edited); | |
utils.cursor.set(pos - 1); | |
} else { | |
var sel = utils.cursor.selection(), | |
edited = val.substring(0,sel.start) + val.substring(sel.end); | |
utils.editor.set(edited); | |
utils.cursor.set(pos); | |
} | |
utils._callHook('delete:after'); | |
} | |
} | |
}, | |
charFuncs = { | |
openedChar: function (_char, e) { | |
utils.preventDefaultEvent(e); | |
utils._callHook('openChar:before'); | |
var pos = utils.cursor.get(), | |
val = utils.editor.get(), | |
left = val.substring(0, pos), | |
right = val.substring(pos), | |
edited = left + _char.open + _char.close + right; | |
defaults.textarea.value = edited; | |
utils.cursor.set(pos + 1); | |
utils._callHook('openChar:after'); | |
}, | |
closedChar: function (_char, e) { | |
var pos = utils.cursor.get(), | |
val = utils.editor.get(), | |
toOverwrite = val.substring(pos, pos + 1); | |
if (toOverwrite == _char.close) { | |
utils.preventDefaultEvent(e); | |
utils._callHook('closeChar:before'); | |
utils.cursor.set(utils.cursor.get() + 1); | |
utils._callHook('closeChar:after'); | |
return true; | |
} | |
return false; | |
} | |
}, | |
action = { | |
filter: function (e) { | |
if(!utils.fenceRange()){ return; } | |
var theCode = e.which || e.keyCode; | |
if(theCode == 39 || theCode == 40 && e.which===0){ return; } | |
var _char = String.fromCharCode(theCode), | |
i; | |
for(i=0; i<charSettings.keyMap.length; i++) { | |
if (charSettings.keyMap[i].close == _char) { | |
var didClose = defaults.overwrite && charFuncs.closedChar(charSettings.keyMap[i], e); | |
if (!didClose && charSettings.keyMap[i].open == _char && defaults.autoOpen) { | |
charFuncs.openedChar(charSettings.keyMap[i], e); | |
} | |
} else if (charSettings.keyMap[i].open == _char && defaults.autoOpen) { | |
charFuncs.openedChar(charSettings.keyMap[i], e); | |
} | |
} | |
}, | |
listen: function () { | |
if(defaults.replaceTab){ utils.addEvent(defaults.textarea, 'keydown', intercept.tabKey); } | |
if(defaults.autoIndent){ utils.addEvent(defaults.textarea, 'keydown', intercept.enterKey); } | |
if(defaults.autoStrip){ utils.addEvent(defaults.textarea, 'keydown', intercept.deleteKey); } | |
utils.addEvent(defaults.textarea, 'keypress', action.filter); | |
utils.addEvent(defaults.textarea, 'keydown', function(){ utils._callHook('keydown'); }); | |
utils.addEvent(defaults.textarea, 'keyup', function(){ utils._callHook('keyup'); }); | |
} | |
}, | |
init = function (opts) { | |
if(opts.textarea){ | |
utils._callHook('init:before', false); | |
utils.deepExtend(defaults, opts); | |
utils.defineNewLine(); | |
if (defaults.softTabs) { | |
tab = " ".repeat(defaults.tabSize); | |
} else { | |
tab = "\t"; | |
utils.defineTabSize(defaults.tabSize); | |
} | |
action.listen(); | |
utils._callHook('init:after', false); | |
} | |
}; | |
this.destroy = function(){ | |
utils.removeEvent(defaults.textarea, 'keydown', intercept.tabKey); | |
utils.removeEvent(defaults.textarea, 'keydown', intercept.enterKey); | |
utils.removeEvent(defaults.textarea, 'keydown', intercept.deleteKey); | |
utils.removeEvent(defaults.textarea, 'keypress', action.filter); | |
}; | |
init(userOpts); | |
}; | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = Behave; | |
} | |
if (typeof ender === 'undefined') { | |
this.Behave = Behave; | |
this.BehaveHooks = BehaveHooks; | |
} | |
if (typeof define === "function" && define.amd) { | |
define("behave", [], function () { | |
return Behave; | |
}); | |
} | |
}).call(this); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Plugin Name: Toms Escaping tester | |
Plugin URI: https://tomjn.com | |
Description: Provides a tomjn_esc_test shortcode that lets you test values with escaping | |
Author: Tom J Nowell | |
Version: 1.1 | |
Author URI: https://www.tomjn.com/escaping | |
License: GPLv2 or later | |
License URI: http://www.gnu.org/licenses/gpl-2.0.html | |
This program is free software: you can redistribute it and/or modify | |
it under the terms of the GNU General Public License as published by | |
the Free Software Foundation, either version 2 of the License, or | |
(at your option) any later version. | |
This program is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
GNU General Public License for more details. | |
You should have received a copy of the GNU General Public License | |
along with this program. If not, see <http://www.gnu.org/licenses/>. | |
*/ | |
function tomjn_escaping_tests(){ | |
$value = (!empty( $_POST['tomjn_esc_value'] ) ) ? $_POST['tomjn_esc_value'] : false; | |
$esc_array = array(); | |
if ( $value ) { | |
global $wpdb; | |
$esc_array = array( | |
'esc_html' => esc_html( $value ), | |
'esc_attr' => esc_attr($value), | |
'esc_js' => esc_js($value), | |
'esc_textarea' => esc_textarea( $value ), | |
'esc_url' => esc_url($value), | |
'esc_url_raw' => esc_url_raw($value), | |
'esc_sql' => esc_sql( $value ), | |
'wp_json_encode' => wp_json_encode($value), | |
'wp_kses( , array(), array())' => wp_kses( $value, array(), array()), | |
'wp_kses_data' => wp_kses_data( $value ), | |
'wp_kses_post' => wp_kses_post( $value ), | |
'wp_strip_all_tags' => wp_strip_all_tags($value), | |
'strip_tags' => strip_tags($value), | |
'htmlentities' => htmlentities($value), | |
'urlencode' => urlencode($value), | |
'rawurlencode' => rawurlencode($value), | |
'sanitize_email' => sanitize_email($value), | |
'sanitize_file_name' => sanitize_file_name($value), | |
'sanitize_html_class' => sanitize_html_class($value), | |
'sanitize_key' => sanitize_key($value), | |
/*'sanitize_meta' => sanitize_meta($value), doesn't make sense to run */ | |
'sanitize_mime_type' => sanitize_mime_type($value), | |
/*'sanitize_option' => sanitize_option($value), this needs 2 values, and sanitising depends on param 1 */ | |
/*'sanitize_post' => sanitize_post($value), this isn't a WP_Post object */ | |
'sanitize_sql_orderby' => sanitize_sql_orderby($value), | |
/*'sanitize_term' => sanitize_term($value), expects a WP_Term and a taxonomy*/ | |
/*'sanitize_term_field' => sanitize_term_field($value), same as above*/ | |
'sanitize_text_field' => sanitize_text_field($value), | |
'sanitize_title' => sanitize_title($value), | |
'sanitize_title_for_query' => sanitize_title_for_query($value), | |
'sanitize_title_with_dashes' => sanitize_title_with_dashes( $value ), | |
'sanitize_user' => sanitize_user( $value ), | |
'balanceTags' => balanceTags( $value ), | |
'tag_escape' => tag_escape( $value ), | |
'addslashes' => addslashes( $value ), | |
'$wpdb->esc_like' => $wpdb->esc_like( $value ), | |
'$wpdb->prepare' => $wpdb->prepare( $value, array() ), | |
); | |
} | |
wp_enqueue_script( 'behavejs', plugins_url( 'behave.js', __FILE__ ), array(), '1.5', true ); | |
ob_start(); | |
?> | |
<form action="" method="post"> | |
<p> | |
<textarea id="tomjn_escape_textarea" name="tomjn_esc_value"><?php | |
if ( $value ) { | |
echo wp_unslash( esc_html( $esc_array['esc_textarea'] ) ); | |
} | |
?></textarea> | |
</p> | |
<style> | |
#tomjn_escape_textarea { | |
font-family: monospace; | |
min-height: 200px; | |
} | |
.tomjn_escape_same { | |
outline: 2px solid rgb(163, 190, 140); | |
} | |
.tomjn_escape_different { | |
outline: 2px solid rgb(235, 203, 139); | |
} | |
</style> | |
<script> | |
jQuery(document).ready( function() { | |
BehaveHooks.add(['keydown'], function(data){ | |
var numLines = data.lines.total, | |
fontSize = parseInt( getComputedStyle(data.editor.element)['font-size'] ), | |
padding = parseInt( getComputedStyle(data.editor.element)['padding'] ); | |
data.editor.element.style.height = (((numLines*fontSize)+padding))+'px'; | |
}); | |
var editor = new Behave({ | |
textarea: document.getElementById('tomjn_escape_textarea'), | |
replaceTab: true, | |
softTabs: false, | |
tabSize: 4, | |
autoOpen: true, | |
overwrite: true, | |
autoStrip: true, | |
autoIndent: true | |
}); | |
}); | |
</script> | |
<p><input type="submit" value="Escape"></p> | |
</form> | |
<p>Refresh rather than re-submit if you're having problems with expanding quote escaping</p> | |
<?php | |
if ( $value ) { | |
?> | |
<dl> | |
<?php | |
foreach($esc_array as $key => $val) { | |
$class = 'tomjn_escape_different'; | |
if ( $val === $value ) { | |
$class = 'tomjn_escape_same'; | |
} | |
?> | |
<dt><?php echo esc_html( $key ); ?></dt> | |
<dd><pre class="<?php echo esc_attr( $class ); ?>"><?php echo htmlspecialchars( $val ); ?></pre></dd> | |
<?php | |
} | |
?> | |
</dl> | |
<?php | |
} | |
return ob_get_clean(); | |
} | |
add_shortcode( 'tomjn_esc_test', 'tomjn_escaping_tests' ); |
Nice! I suggest running the output through htmlspecialchars()
so the escaped value differences are visible to the eye.
+1 for @zackkatz's suggestion. I just wanted to write the same. Also, the wrapping esc_html()
tempers too much with the actual results.
And the last one is $wpdb->prepare
(and not addslashes
).
But still, very handy. :)
Here's a leaner version, friend: https://gist.github.com/JeppeSigaard/1a439d2af6d4615c41c8
Just reorganizing, not really concerned with the validity of the output. Hope you like.
It's now on the .org repo https://wordpress.org/plugins/escaping-checker/
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You mad, mad genius. Love this, thanks for building it.
I wonder if we can figure out a way to show the differences in the output from each of them, too, so people can know what to expect.