1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Python Bleach 4.0.0</title>
<style>
textarea, iframe {
width: 95%;
}
#clean, #dirty, #ifr {
height: 100px;
}
.test-case > .ifr {
height: 50px;
}
.test-case, .demo {
padding-bottom: 15px;
border-bottom: 2px solid gray;
}
</style>
</head>
<body>
<h2>Python Bleach 4.0.0</h2>
<div class="demo">
<h3>Demo</h3>
<p>
This is the demo for <a href="https://bleach.readthedocs.io/en/latest/index.html">Bleach</a>, an allowed-list-based HTML sanitizing library that escapes or strips markup and attributes.
Enter a sample payload in the textarea below and watch it sanitize in the textarea and iframe below.
</p>
<hr>
<p><button class="unsafe-write">write <strong>unsanitized</strong> textarea value to DOM</button></p>
<p><button class="clean-and-write">bleach.clean textarea value then write result to DOM</button></p>
<p><input id="autoclean" type="checkbox" checked /> clean when dirty HTML changes</p>
<p><label for="dirty">Dirty HTML</label></p>
<textarea placeholder="Payload goes here." id="dirty" class="dirty"><!-- Loading Test-Vectors ... --></textarea>
<p><label for="clean">Clean HTML</label></p>
<textarea placeholder="Here be the sanitized markup to inspect!" id="clean" class="clean"></textarea>
<p><label for="ifr" class="dom-label">Clean DOM</label></p>
<iframe src="about:blank" id="ifr" class="ifr"></iframe>
</div>
<div id="test-template" class="test-case" style="display:none">
<a class="test-name-link" href="#"><h3 class="test-name"></h3></a>
<p>
<button class="unsafe-write" data-test="null">
write <strong>unsanitized</strong> textarea value to DOM
</button>
<p><button class="clean-and-write">bleach.clean textarea value then write result to DOM</button></p>
</p>
<p><label for="dirty">Dirty HTML</label></p>
<textarea placeholder="Payload goes here." class="dirty" readonly rows="2"></textarea>
<p><label for="clean">Clean HTML</label></p>
<textarea placeholder="Here be the sanitized markup to inspect!" class="clean" readonly rows="2"></textarea>
<p><label for="ifr" class="dom-label">Clean DOM</label></p>
<iframe src="about:blank" class="ifr"></iframe>
</div>
<script>
var writeToIframe = function(ifr, value) {
ifr.contentDocument.open();
ifr.contentDocument.write(value);
ifr.contentDocument.close();
};
var sanitize = function(event) {
if (event && event.target && event.target.className.indexOf("clean-and-write") !== -1) {
var grandParent = event.target.parentElement.parentElement;
var xhr = new XMLHttpRequest();
xhr.open('POST', '/sanitize');
xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");
xhr.onload = function() {
var sanitized = xhr.responseText;
grandParent.querySelector("label.dom-label[for=ifr]").textContent = "Clean DOM";
writeToIframe(grandParent.querySelector('.ifr'), sanitized);
grandParent.querySelector("textarea.clean").value = sanitized;
}
xhr.send(grandParent.querySelector("textarea.dirty").value);
}
};
var unsafeWrite = function(event) {
if (event.target.className.indexOf("unsafe-write") !== -1) {
var grandParent = event.target.parentElement.parentElement;
grandParent.querySelector("textarea.clean").value = "N/A";
grandParent.querySelector("label.dom-label[for=ifr]").textContent = "Dirty DOM";
writeToIframe(grandParent.querySelector('.ifr'), grandParent.querySelector("textarea.dirty").value);
}
};
var addTest = function (test, index) {
var testTemplate = document.getElementById('test-template');
var template = testTemplate.cloneNode(true);
var testId = 'test-' + index;
template.setAttribute('id', testId);
template.getElementsByClassName('test-name-link')[0].setAttribute('href', '#' + testId);
template.getElementsByClassName('test-name')[0].textContent = test.title;
template.getElementsByClassName('dirty')[0].value = test.payload;
template.getElementsByClassName('clean')[0].value = test.actual;
template.style.display = "block";
// iframe must be in DOM before we can write to it.
document.getElementsByTagName('body')[0].appendChild(template);
writeToIframe(template.getElementsByClassName('ifr')[0], test.actual);
};
var loadTests = function(url, onSuccess) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function () {
return onSuccess(xhr.responseText);
};
xhr.onerror = function() {
console.error(arguments)
}
xhr.send(null);
};
// TODO: debounce input events?
document.getElementById('dirty')
.addEventListener('input', function () {
var autocleanEl = document.getElementById('autoclean');
if (autocleanEl.checked) {
sanitize({target: document.getElementsByClassName('clean-and-write')[0]});
}
});
document.addEventListener('click', unsafeWrite, false);
document.addEventListener('click', sanitize, false);
document.addEventListener('DOMContentLoaded', function() {
loadTests('/testcases.json', function (responseText) {
dirty.value = '<!-- I am ready now, click one of the buttons! -->\r\n';
JSON.parse(responseText).forEach(addTest)
});
}, false);
</script>
</body>
</html>
|