| 1 |
<?php
|
| 2 |
// $Id: safehtml.module,v 1.9 2009/08/11 17:32:33 claudiucristea Exp $
|
| 3 |
|
| 4 |
|
| 5 |
/**
|
| 6 |
* Implementation of hook_help().
|
| 7 |
*/
|
| 8 |
function safehtml_help($path, $arg) {
|
| 9 |
switch ($path) {
|
| 10 |
case 'admin/help#safehtml':
|
| 11 |
return
|
| 12 |
t('<p>Safe HTML is a module that filters the input and performs code cleaning before the content is stored.</p>') .
|
| 13 |
t('<p>Safe HTML must be enabled on the <em>Input formats</em> section to take effect. Safe HTML cannot be used in conjunction with the PHP Parser Filter because Safe HTML will strip any PHP code. Safe HTML can be used together with HTML Filter in order to limit HTML tags to an allowed array.</p>') .
|
| 14 |
t('<p>Administrators and allowed users can define custom PHP code to perform additional tasks on the form input. The site administrator can define what kind of custom transformation may occur on the form content and apply these transformations to a variable named <strong>$html</strong>.</p>') .
|
| 15 |
t('<p>The module is based on <a href="http://pixel-apes.com/safehtml/">HTML Safe</a> a project lead by Roman Ivanov and strips content of potentially dangerous HTML:</p>') .
|
| 16 |
t('<ul><li>opening tag without its closing tag</li><li>closing tag without its opening tag;</li><li>resolving cases like <p><em>abc</p></em>;</li><li>strip any of these tags: "base", "basefont", "head", "html", "body", "applet", "object", "iframe", "frame", "frameset", "script", "layer", "ilayer", "embed", "bgsound", "link", "meta", "style", "title", "blink", "xml" etc.</li><li>any of these attributes: on*, data*, dynsrc</li><li>javascript:/vbscript:/about: etc. protocols</li><li>expression/behavior etc. in styles</li><li>any other active content</li></ul>') .
|
| 17 |
t('<p>It also tries to convert code to XHTML valid, but htmltidy is a better solution for this task.</p>');
|
| 18 |
}
|
| 19 |
}
|
| 20 |
|
| 21 |
/**
|
| 22 |
* Implementation of hook_perm().
|
| 23 |
*/
|
| 24 |
function safehtml_perm() {
|
| 25 |
return array('administer safehtml');
|
| 26 |
}
|
| 27 |
|
| 28 |
/**
|
| 29 |
* Menu callback; return module settings form.
|
| 30 |
*/
|
| 31 |
function _safehtml_settings($format) {
|
| 32 |
$form['safehtml'] = array(
|
| 33 |
'#type' => 'fieldset',
|
| 34 |
'#title' => 'Safe HTML',
|
| 35 |
'#collapsible' => TRUE,
|
| 36 |
);
|
| 37 |
$form['safehtml']['safehtml_custom_code_' . $format] = array(
|
| 38 |
'#type' => 'textarea',
|
| 39 |
'#title' => t('Custom code'),
|
| 40 |
'#default_value' => variable_get('safehtml_custom_code_' . $format, variable_get('safehtml_custom_code', '// strip consecutive spaces' . "\n" . '$html = preg_replace("/[ ]{2,}/i", " ", $html);')),
|
| 41 |
'#description' => t('Add here code to perform additional tasks on the HTML string. You must process the <strong>$html</strong> variable in order to add additional tasks. This variable acts as input and output as well. If you are not familiar with PHP do not edit this field!'),
|
| 42 |
);
|
| 43 |
|
| 44 |
return $form;
|
| 45 |
}
|
| 46 |
|
| 47 |
/**
|
| 48 |
* hook_filter() implementation
|
| 49 |
*/
|
| 50 |
function safehtml_filter($op, $delta = 0, $format = -1, $text = '') {
|
| 51 |
switch ($op) {
|
| 52 |
case 'list':
|
| 53 |
return array(0 => t('Safe HTML'));
|
| 54 |
|
| 55 |
case 'description':
|
| 56 |
return t('An input filter that check and correct HTML before is stored in database.');
|
| 57 |
|
| 58 |
case 'settings':
|
| 59 |
return _safehtml_settings($format);
|
| 60 |
|
| 61 |
default:
|
| 62 |
return $text;
|
| 63 |
}
|
| 64 |
}
|
| 65 |
|
| 66 |
/**
|
| 67 |
* hook_filter_tips() implementation
|
| 68 |
*/
|
| 69 |
function safehtml_filter_tips($delta, $format, $long = FALSE) {
|
| 70 |
if (!$long) {
|
| 71 |
return t('Potentially problem-causing HTML tags are filtered.');
|
| 72 |
}
|
| 73 |
return t('Check and correct HTML before is stored in database. This parser strips down all potentially dangerous content within HTML: opening tag without its closing tag; closing tag without its opening tag; any of these tags: "base", "basefont", "head", "html", "body", "applet", "object", "iframe", "frame", "frameset", "script", "layer", "ilayer", "embed", "bgsound", "link", "meta", "style", "title", "blink", "xml" etc.; any of these attributes: on*, data*, dynsrc; javascript:/vbscript:/about: etc. protocols; expression/behavior etc. in styles; any other active content. It also tries to convert code to XHTML valid, but htmltidy is far better solution for this task.');
|
| 74 |
}
|
| 75 |
|
| 76 |
/**
|
| 77 |
* hook_nodeapi() implementation
|
| 78 |
*/
|
| 79 |
function safehtml_nodeapi(&$node, $op, $teaser = NULL, $page = NULL) {
|
| 80 |
if ($op == 'presave') {
|
| 81 |
$filters = array_keys(filter_list_format($node->format));
|
| 82 |
if (in_array('safehtml/0', $filters)) {
|
| 83 |
if ($node->body) {
|
| 84 |
$node->body = _safehtml_parse($node->body, $node->format);
|
| 85 |
}
|
| 86 |
if ($node->teaser) {
|
| 87 |
$node->teaser = _safehtml_parse($node->teaser, $node->format);
|
| 88 |
}
|
| 89 |
|
| 90 |
/**
|
| 91 |
* Check also if we have
|
| 92 |
* CCK Text formatted fields
|
| 93 |
* and parse them
|
| 94 |
*/
|
| 95 |
if (module_exists('text')) {
|
| 96 |
_safehtml_cck_text($node);
|
| 97 |
}
|
| 98 |
}
|
| 99 |
}
|
| 100 |
}
|
| 101 |
|
| 102 |
/**
|
| 103 |
* Implementation of hook_comment()
|
| 104 |
*/
|
| 105 |
function safehtml_comment($comment, $op) {
|
| 106 |
if (in_array($op, array('insert', 'update'))) {
|
| 107 |
$filters = array_keys(filter_list_format($comment['format']));
|
| 108 |
if (in_array('safehtml/0', $filters)) {
|
| 109 |
$parsed = _safehtml_parse($comment['comment'], $comment['format']);
|
| 110 |
db_query("UPDATE {comments} SET comment = '%s' WHERE cid = %d", $parsed, $comment['cid']);
|
| 111 |
}
|
| 112 |
}
|
| 113 |
}
|
| 114 |
|
| 115 |
/**
|
| 116 |
* Also parse CCK text fields
|
| 117 |
*/
|
| 118 |
function _safehtml_cck_text(&$node) {
|
| 119 |
static $filters = array();
|
| 120 |
$type = content_types($node->type);
|
| 121 |
foreach ($type['fields'] as $field_id => $field) {
|
| 122 |
if ($field['type'] == 'text' && $field['text_processing']) {
|
| 123 |
foreach ($node->$field_id as $delta => $item) {
|
| 124 |
if (!isset($filters[$item['format']])) {
|
| 125 |
$filters[$item['format']] = array_keys(filter_list_format($item['format']));
|
| 126 |
}
|
| 127 |
if (in_array('safehtml/0', $filters[$item['format']])) {
|
| 128 |
$node->{$field_id}[$delta]['value'] = _safehtml_parse($item['value'], $item['format']);
|
| 129 |
}
|
| 130 |
}
|
| 131 |
}
|
| 132 |
}
|
| 133 |
}
|
| 134 |
|
| 135 |
/**
|
| 136 |
* HTML parser
|
| 137 |
*/
|
| 138 |
function _safehtml_parse($html, $format) {
|
| 139 |
static $parser;
|
| 140 |
$path = './'. drupal_get_path('module', 'safehtml') .'/classes';
|
| 141 |
if (!defined('XML_HTMLSAX3')) {
|
| 142 |
define('XML_HTMLSAX3', $path .'/');
|
| 143 |
}
|
| 144 |
include_once($path .'/safehtml.php');
|
| 145 |
if (!isset($parser)) {
|
| 146 |
$parser = new SafeHTML();
|
| 147 |
}
|
| 148 |
else {
|
| 149 |
$parser->clear();
|
| 150 |
}
|
| 151 |
$html = $parser->parse($html);
|
| 152 |
eval(variable_get('safehtml_custom_code_'. $format, '// strip consecutive spaces' . "\n" . '$html = preg_replace("/[ ]{2,}/i", " ", $html);'));
|
| 153 |
return $html;
|
| 154 |
}
|