/** * This function takes a string with an html tag and strips out any unallowed * protocols e.g. javascript: * * It calls ancillary functions in kses which are prefixed by kses * * @global object * @global string * @param array $htmlArray An array from {@link cleanAttributes()}, containing in its 1st * element the html to be cleared * @return string */ function cleanAttributes2($htmlArray) { global $CFG, $ALLOWED_PROTOCOLS; require_once $CFG->libdir . '/kses.php'; $htmlTag = $htmlArray[1]; if (substr($htmlTag, 0, 1) != '<') { return '>'; //a single character ">" detected } if (!preg_match('%^<\\s*(/\\s*)?([a-zA-Z0-9]+)([^>]*)>?$%', $htmlTag, $matches)) { return ''; // It's seriously malformed } $slash = trim($matches[1]); //trailing xhtml slash $elem = $matches[2]; //the element name $attrlist = $matches[3]; // the list of attributes as a string $attrArray = kses_hair($attrlist, $ALLOWED_PROTOCOLS); $attStr = ''; foreach ($attrArray as $arreach) { $arreach['name'] = strtolower($arreach['name']); if ($arreach['name'] == 'style') { $value = $arreach['value']; while (true) { $prevvalue = $value; $value = kses_no_null($value); $value = preg_replace("/\\/\\*.*\\*\\//Us", '', $value); $value = kses_decode_entities($value); $value = preg_replace('/(&#[0-9]+)(;?)/', "\\1;", $value); $value = preg_replace('/(&#x[0-9a-fA-F]+)(;?)/', "\\1;", $value); if ($value === $prevvalue) { $arreach['value'] = $value; break; } } $arreach['value'] = preg_replace("/j\\s*a\\s*v\\s*a\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t/i", "Xjavascript", $arreach['value']); $arreach['value'] = preg_replace("/v\\s*b\\s*s\\s*c\\s*r\\s*i\\s*p\\s*t/i", "Xvbscript", $arreach['value']); $arreach['value'] = preg_replace("/e\\s*x\\s*p\\s*r\\s*e\\s*s\\s*s\\s*i\\s*o\\s*n/i", "Xexpression", $arreach['value']); $arreach['value'] = preg_replace("/b\\s*i\\s*n\\s*d\\s*i\\s*n\\s*g/i", "Xbinding", $arreach['value']); } else { if ($arreach['name'] == 'href') { //Adobe Acrobat Reader XSS protection $arreach['value'] = preg_replace('/(\\.(pdf|fdf|xfdf|xdp|xfd)[^#]*)#.*$/i', '$1', $arreach['value']); } } $attStr .= ' ' . $arreach['name'] . '="' . $arreach['value'] . '"'; } $xhtml_slash = ''; if (preg_match('%/\\s*$%', $attrlist)) { $xhtml_slash = ' /'; } return '<' . $slash . $elem . $attStr . $xhtml_slash . '>'; }
function kses_bad_protocol_once2($string, $allowed_protocols) { $string2 = kses_decode_entities($string); $string2 = preg_replace('/\\s/', '', $string2); $string2 = kses_no_null($string2); $string2 = preg_replace('/\\xad+/', '', $string2); # deals with Opera "feature" $string2 = strtolower($string2); $allowed = false; foreach ($allowed_protocols as $one_protocol) { if (strtolower($one_protocol) == $string2) { $allowed = true; break; } } if ($allowed) { return "{$string2}:"; } else { return ''; } }
function kses($string, $allowed_html, $allowed_protocols = array('http', 'https', 'ftp', 'news', 'nntp', 'telnet', 'gopher', 'mailto')) { $string = kses_no_null($string); $string = kses_js_entities($string); $string = kses_normalize_entities($string); $string = kses_hook($string); $allowed_html_fixed = kses_array_lc($allowed_html); return kses_split($string, $allowed_html_fixed, $allowed_protocols); }
function kses_bad_protocol_once2($matches) { //Zenphoto:preg_replace with the "e" modifier is deprecated, this is the callback global $_allowed_protocols; $allowed_protocols = $_allowed_protocols; $string2 = kses_decode_entities($matches[1]); $string2 = preg_replace('/\\s/', '', $string2); $string2 = kses_no_null($string2); $string2 = preg_replace('/\\xad+/', '', $string2); # deals with Opera "feature" $string2 = strtolower($string2); $allowed = false; foreach ($allowed_protocols as $one_protocol) { if (strtolower($one_protocol) == $string2) { $allowed = true; break; } } if ($allowed) { return "{$string2}:"; } else { return ''; } }
/** * Inline CSS filter * */ function kses_safecss_filter_attr($css) { $css = kses_no_null($css); $css = str_replace(array("\n", "\r", "\t"), '', $css); if (preg_match('%[\\(&=}]|/\\*%', $css)) { // remove any inline css containing \ ( & } = or comments return ''; } $css_array = explode(';', trim($css)); $allowed_attr = array('text-align', 'margin', 'color', 'float', 'border', 'background', 'background-color', 'border-bottom', 'border-bottom-color', 'border-bottom-style', 'border-bottom-width', 'border-collapse', 'border-color', 'border-left', 'border-left-color', 'border-left-style', 'border-left-width', 'border-right', 'border-right-color', 'border-right-style', 'border-right-width', 'border-spacing', 'border-style', 'border-top', 'border-top-color', 'border-top-style', 'border-top-width', 'border-width', 'caption-side', 'clear', 'cursor', 'direction', 'display', 'font', 'font-family', 'font-size', 'font-style', 'font-variant', 'font-weight', 'height', 'letter-spacing', 'line-height', 'margin-bottom', 'margin-left', 'margin-right', 'margin-top', 'overflow', 'padding', 'padding-bottom', 'padding-left', 'padding-right', 'padding-top', 'text-decoration', 'text-indent', 'vertical-align', 'width'); if (empty($allowed_attr)) { return $css; } $css = ''; foreach ($css_array as $css_item) { if ($css_item == '') { continue; } $css_item = trim($css_item); $found = false; if (strpos($css_item, ':') === false) { $found = true; } else { $parts = split(':', $css_item); if (in_array(strtolower(trim($parts[0])), $allowed_attr)) { $found = true; } } if ($found) { if ($css != '') { $css .= ';'; } $css .= $css_item; } } return $css; }
function kses_bad_protocol_once2($matches) { ############################################################################### # This function processes URL protocols, checks to see if they're in the white- # list or not, and returns different data depending on the answer. ############################################################################### //update// preg_replace with the "e" modifier is deprecated, this is the callback global $_allowed_protocols; $allowed_protocols = $_allowed_protocols; $string2 = kses_decode_entities($matches[1]); $string2 = preg_replace('/\\s/', '', $string2); $string2 = kses_no_null($string2); $string2 = preg_replace('/\\xad+/', '', $string2); # deals with Opera "feature" $string2 = strtolower($string2); $allowed = false; foreach ($allowed_protocols as $one_protocol) { if (strtolower($one_protocol) == $string2) { $allowed = true; break; } } if ($allowed) { return "{$string2}:"; } else { return ''; } }