3 // major TODO: hook into some sort of templating system that utilizes
4 // XHTML Compiler to process the template (cacheable, of course), before
5 // passing it along to this script
7 // using _REQUEST because we accept GET and POST requests
9 // can break XML handling (ideally we should place these errors
10 // somewhere the user can see, so this is a stopgap)
13 function getFormMethod() {
14 return (isset($_REQUEST['post'])) ?
'post' : 'get';
16 function escapeHTML($html) {
17 return htmlspecialchars(
18 HTMLPurifier_Encoder
::cleanUTF8($html), ENT_COMPAT
, 'UTF-8');
23 if (file_exists($dir = 'xhtml-compiler/conf/name.txt')) {
24 $name = trim(file_get_contents($dir));
25 } elseif (file_exists('xhtml-compiler/local.txt')) {
27 } elseif (file_exists('local.txt')) {
31 return $name == 'EZYANG' ||
$name == 'EZYANG2';
34 if (empty($_REQUEST['experimental'])) {
35 require_once 'live/library/HTMLPurifier.auto.php';
36 } elseif (!isLocal()) {
37 require_once 'dev/library/HTMLPurifier.auto.php';
39 require_once '../htmlpurifier/library/HTMLPurifier.auto.php';
41 require_once 'HTMLPurifier/Printer/ConfigForm.php';
43 // Permissible configuration options have to be chosen carefully; HTML
44 // Purifier wasn't designed for unfriendly user configuration, so
45 // certain configuration directives can be used to cause XSS attacks
46 // because they're not validated at all.
48 $allowed_lite = array(
50 'URI.DisableExternalResources',
57 'CSS.AllowedProperties',
60 '-AutoFormat.PurifierLinkify',
61 '-AutoFormat.PurifierLinkify.DocURL',
62 '-AutoFormat.RemoveEmpty.RemoveNbsp',
63 '-AutoFormat.RemoveEmpty.RemoveNbsp.Exceptions'
66 $config = HTMLPurifier_Config
::loadArrayFromForm($_REQUEST, 'filter', $allowed_lite);
67 $purifier = new HTMLPurifier($config);
69 if (!empty($_REQUEST['strict'])) {
70 // backwards-compatibility
71 // (muting deprecated error)
72 @$config->set('HTML', 'Strict', true);
74 if (!empty($_REQUEST['experimental'])) {
75 //require_once 'HTMLPurifier/Lexer/PH5P.php';
76 //$config->set('Core', 'LexerImpl', 'PH5P');
77 //$config->set('HTML.SafeObject', true);
78 //$config->set('HTML.FlashCompat', true);
81 if (file_exists('demo.custom.php') && isLocal()) include 'demo.custom.php';
83 $definition = $config->getHTMLDefinition();
84 $doctype = $definition->doctype
;
86 if ($doctype->xml
&& stripos($_SERVER["HTTP_ACCEPT"], 'application/xhtml+xml') !== false && !isset($_REQUEST['debug'])) {
87 $type = 'application/xhtml+xml';
91 header("Content-type:$type;charset=UTF-8");
93 // prevent PHP versions with shorttags from barfing
95 echo '<?xml version="1.0" encoding="UTF-8" ?>' . PHP_EOL
;
98 if (!empty($doctype->dtdPublic
) && !empty($doctype->dtdSystem
)) {
99 echo '<!DOCTYPE html PUBLIC "'.$doctype->dtdPublic
.'" "'.$doctype->dtdSystem
.'">' . PHP_EOL
;
103 echo '<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">' . PHP_EOL
;
106 echo '<html lang="en">' . PHP_EOL
;
111 <title
>HTML Purifier Live Demo
</title
>
112 <!-- make sure all
empty elements that are not generated are
113 appropriately ended
-->
114 <meta name
="author" content
="Edward Z. Yang"<?php
echo $END; ?
>>
115 <meta http
-equiv
="Content-Type" content
="text/html; charset=UTF-8"<?php
echo $END; ?
>>
116 <link rel
="icon" href
="favicon.ico" type
="image/x-icon"<?php
echo $END; ?
>>
117 <link rel
="shortcut icon" href
="favicon.ico" type
="image/x-icon"<?php
echo $END; ?
>>
118 <link rel
="stylesheet" href
="common.css" type
="text/css"<?php
echo $END; ?
>>
119 <link rel
="stylesheet" href
="demo.css" type
="text/css"<?php
echo $END; ?
>>
120 <link rel
="stylesheet" href
="live/library/HTMLPurifier/Printer/ConfigForm.css" type
="text/css"<?php
echo $END; ?
>>
121 <script defer
="defer" type
="text/javascript" src
="live/library/HTMLPurifier/Printer/ConfigForm.js"></script
>
124 <div id
="logo"></div
>
125 <div id
="header"><a href
=".">HTML Purifier
</a
></div
>
127 if (file_exists('navigation.frag')) {
128 readfile('navigation.frag');
130 <div
><strong
>Please navigate to
<a href
="navigation.html">navigation
.html
</a
> to regenerate menu
</strong
></div
>
134 <h1 id
="title">Live Demo
</h1
>
138 if (!empty($_REQUEST['html'])) { // start result
140 if (strlen($_REQUEST['html']) > 50000) {
142 <p
>Request exceeds maximum allowed text size of
50kb
.</p
>
144 } else { // start main processing
146 $html = get_magic_quotes_gpc() ?
stripslashes($_REQUEST['html']) : $_REQUEST['html'];
147 $pure_html = $purifier->purify($html);
150 <p
>Here is your purified HTML
:</p
>
152 <?php
if(getFormMethod() == 'get') {
155 if ($doctype->name
== 'HTML 4.01 Transitional' ||
$doctype->name
== 'HTML 4.01 Strict') {
156 $img = 'http://www.w3.org/Icons/valid-html401';
157 } elseif ($doctype->name
== 'XHTML 1.0 Transitional' ||
$doctype->name
== 'XHTML 1.0 Strict') {
158 $img = 'http://www.w3.org/Icons/valid-xhtml10';
159 } elseif ($doctype->name
== 'XHTML 1.1') {
160 $img = 'http://www.w3.org/Icons/valid-xhtml11';
163 <div id
="w3c-validator">
164 <a href
="http://validator.w3.org/check?uri=referer" title
="Valid <?php echo escapeHTML($doctype->name); ?>">
167 src
="<?php echo escapeHTML($img); ?>" height
="31" width
="88"
168 alt
="Valid <?php echo escapeHTML($doctype->name); ?>"<?php
echo $END; ?
>>
170 Valid
<?php
echo escapeHTML($doctype->name
); ?
>
180 <div
class="clear"></div
>
182 <?php
if (@$config->get('Core', 'CollectErrors')) {
183 $e = $purifier->context
->get('ErrorCollector');
184 $class = $e->getRaw() ?
'fail' : 'pass';
186 <p
>Here are errors that occurred during purification
:</p
>
187 <div id
="errors" class="<?php echo $class ?>">
189 echo $e->getHTMLFormatted($config);
193 <p
>Here is the source code of the purified HTML
:</p
>
194 <pre id
="source"><?php
echo escapeHTML($pure_html); ?
></pre
>
196 if (getFormMethod() == 'post') { // start POST validation notice
198 <p
>If you would like to validate the code with
199 <a href
="http://validator.w3.org/#validate-by-input">W3C
's
200 validator</a>, copy and paste the <em>entire</em> demo page's source
.</p
>
202 } // end POST validation notice
205 <p
>Share this purification using the
<a href
="javascript:var%20e=document.createElement('script');e.setAttribute('language','javascript');e.setAttribute('src','http://bit.ly/bookmarklet/load.js');document.body.appendChild(e);void(0);">bit
.ly URL shortener
</a
>.</p
>
208 } // end main processing
214 <p
>Welcome to the live demo
. Enter some HTML
and see how HTML Purifier
221 <form id
="filter" action
="demo.php<?php
222 echo '?' . getFormMethod();
223 if (isset($_REQUEST['profile']) || isset($_REQUEST['XDEBUG_PROFILE'])) {
224 echo '&XDEBUG_PROFILE=1';
225 } ?>" method
="<?php echo getFormMethod(); ?>">
227 <legend
>HTML Purifier
Input (<?php
echo getFormMethod(); ?
>)</legend
>
230 $form_printer = new HTMLPurifier_Printer_ConfigForm('filter', 'http://htmlpurifier.org/live/configdoc/plain.html#%s', 14);
231 echo $form_printer->render($config, $allowed_lite, false);
235 <textarea name
="html" cols
="60" rows
="15"><?php
236 if (isset($html)) echo escapeHTML($html);
241 By
default, HTML Purifier may remove some of your spacing
or
242 indentation
. Turn on CollectErrors
or experimental features in
243 order to fully preserve whitespace
.
245 <?php
if (getFormMethod() == 'get') { ?
>
246 <p
><strong
>Warning
:</strong
> GET request method can only hold
247 8129 characters (probably less depending on your browser
).
248 If you need to test anything
249 larger than that
, try the
<a href
="?post">POST form
</a
>.</p
>
252 <input type
="submit" value
="Submit" name
="submit" class="button"<?php
echo $END; ?
>>
253 Use <abbr
class="elaborates" title
="This runs code from the master Git repository branch.">experimental features
</abbr
>: <input type
="checkbox" value
="1" <?php
if(!empty($_REQUEST['experimental'])) {echo 'checked="checked" ';} ?
>name
="experimental"<?php
echo $END; ?
>>
257 <p
class="lead">Try the form in
<a href
="?get">GET
</a
> and <a href
="?post">POST
</a
> request
258 flavors (GET is easy to validate with W3C
, but POST allows larger inputs
).
259 Don
't know what to test? Try out these sample filterings:</p>
261 <li><a href="demo.php?html=%3Cimg+src%3D%22javascript%3Aevil%28%29%3B%22+onload%3D%22evil%28%29%3B%22+%2F%3E">Malicious code removed</a></li>
262 <li><a href="demo.php?html=%3Cb%3EBold&submit=Submit">Missing end tags fixed</a></li>
263 <li><a href="demo.php?html=%3Cb%3EInline+%3Cdel%3Econtext+%3Cdiv%3ENo+block+allowed%3C%2Fdiv%3E%3C%2Fdel%3E%3C%2Fb%3E&submit=Submit">Illegal nesting fixed</a></li>
264 <li><a href="demo.php?html=%3Ccenter%3ECentered%3C%2Fcenter%3E&filter%5BHTML.Doctype%5D=XHTML+1.0+Strict&submit=Submit">Deprecated tags converted</a></li>
265 <li><a href="demo.php?html=%3Cspan+style%3D%22color%3A%23COW%3Bfloat%3Aaround%3Btext-decoration%3Ablink%3B%22%3EText%3C%2Fspan%3E&submit=Submit"><abbr>CSS</abbr> validated</a></li>
266 <li><a href="demo.php?html=%3Ctable%3E%0D%0A++%3Ccaption%3E%0D%0A++++Cool+table%0D%0A++%3C%2Fcaption%3E%0D%0A++%3Ctfoot%3E%0D%0A++++%3Ctr%3E%0D%0A++++++%3Cth%3EI+can+do+so+much%21%3C%2Fth%3E%0D%0A++++%3C%2Ftr%3E%0D%0A++%3C%2Ftfoot%3E%0D%0A++%3Ctr%3E%0D%0A++++%3Ctd+style%3D%22font-size%3A16pt%3B%0D%0A++++++color%3A%23F00%3Bfont-family%3Asans-serif%3B%0D%0A++++++text-align%3Acenter%3B%22%3EWow%3C%2Ftd%3E%0D%0A++%3C%2Ftr%3E%0D%0A%3C%2Ftable%3E&experimental=1&submit=Submit">Rich formatting preserved</a></li>