?????????????? ?????????????? ?????????????? ?????????????? HTMLSax3.php000066600000023203151454721230006570 0ustar00 Original port from Python | // | Authors: Harry Fuecks Port to PEAR + more | // | Authors: Many @ Sitepointforums Advanced PHP Forums | // +----------------------------------------------------------------------+ // if (!defined('XML_HTMLSAX3')) { define('XML_HTMLSAX3', 'XML/'); } require_once(XML_HTMLSAX3 . 'HTMLSax3/States.php'); require_once(XML_HTMLSAX3 . 'HTMLSax3/Decorators.php'); class XML_HTMLSax3_StateParser { var $htmlsax; var $handler_object_element; var $handler_method_opening; var $handler_method_closing; var $handler_object_data; var $handler_method_data; var $handler_object_pi; var $handler_method_pi; var $handler_object_jasp; var $handler_method_jasp; var $handler_object_escape; var $handler_method_escape; var $handler_default; var $parser_options = array(); var $rawtext; var $position; var $length; var $State = array(); function XML_HTMLSax3_StateParser (& $htmlsax) { $this->htmlsax = & $htmlsax; $this->State[XML_HTMLSAX3_STATE_START] = new XML_HTMLSax3_StartingState(); $this->State[XML_HTMLSAX3_STATE_CLOSING_TAG] = new XML_HTMLSax3_ClosingTagState(); $this->State[XML_HTMLSAX3_STATE_TAG] = new XML_HTMLSax3_TagState(); $this->State[XML_HTMLSAX3_STATE_OPENING_TAG] = new XML_HTMLSax3_OpeningTagState(); $this->State[XML_HTMLSAX3_STATE_PI] = new XML_HTMLSax3_PiState(); $this->State[XML_HTMLSAX3_STATE_JASP] = new XML_HTMLSax3_JaspState(); $this->State[XML_HTMLSAX3_STATE_ESCAPE] = new XML_HTMLSax3_EscapeState(); } function unscanCharacter() { $this->position -= 1; } function ignoreCharacter() { $this->position += 1; } function scanCharacter() { if ($this->position < $this->length) { return $this->rawtext{$this->position++}; } } function scanUntilString($string) { $start = $this->position; $this->position = strpos($this->rawtext, $string, $start); if ($this->position === FALSE) { $this->position = $this->length; } return substr($this->rawtext, $start, $this->position - $start); } function scanUntilCharacters($string) {} function ignoreWhitespace() {} function parse($data) { if ($this->parser_options['XML_OPTION_TRIM_DATA_NODES']==1) { $decorator = new XML_HTMLSax3_Trim( $this->handler_object_data, $this->handler_method_data); $this->handler_object_data =& $decorator; $this->handler_method_data = 'trimData'; } if ($this->parser_options['XML_OPTION_CASE_FOLDING']==1) { $open_decor = new XML_HTMLSax3_CaseFolding( $this->handler_object_element, $this->handler_method_opening, $this->handler_method_closing); $this->handler_object_element =& $open_decor; $this->handler_method_opening ='foldOpen'; $this->handler_method_closing ='foldClose'; } if ($this->parser_options['XML_OPTION_LINEFEED_BREAK']==1) { $decorator = new XML_HTMLSax3_Linefeed( $this->handler_object_data, $this->handler_method_data); $this->handler_object_data =& $decorator; $this->handler_method_data = 'breakData'; } if ($this->parser_options['XML_OPTION_TAB_BREAK']==1) { $decorator = new XML_HTMLSax3_Tab( $this->handler_object_data, $this->handler_method_data); $this->handler_object_data =& $decorator; $this->handler_method_data = 'breakData'; } if ($this->parser_options['XML_OPTION_ENTITIES_UNPARSED']==1) { $decorator = new XML_HTMLSax3_Entities_Unparsed( $this->handler_object_data, $this->handler_method_data); $this->handler_object_data =& $decorator; $this->handler_method_data = 'breakData'; } if ($this->parser_options['XML_OPTION_ENTITIES_PARSED']==1) { $decorator = new XML_HTMLSax3_Entities_Parsed( $this->handler_object_data, $this->handler_method_data); $this->handler_object_data =& $decorator; $this->handler_method_data = 'breakData'; } // Note switched on by default if ($this->parser_options['XML_OPTION_STRIP_ESCAPES']==1) { $decorator = new XML_HTMLSax3_Escape_Stripper( $this->handler_object_escape, $this->handler_method_escape); $this->handler_object_escape =& $decorator; $this->handler_method_escape = 'strip'; } $this->rawtext = $data; $this->length = strlen($data); $this->position = 0; $this->_parse(); } function _parse($state = XML_HTMLSAX3_STATE_START) { do { $state = $this->State[$state]->parse($this); } while ($state != XML_HTMLSAX3_STATE_STOP && $this->position < $this->length); } } class XML_HTMLSax3_StateParser_Lt430 extends XML_HTMLSax3_StateParser { function XML_HTMLSax3_StateParser_Lt430(& $htmlsax) { parent::XML_HTMLSax3_StateParser($htmlsax); $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; } function scanUntilCharacters($string) { $startpos = $this->position; while ($this->position < $this->length && strpos($string, $this->rawtext{$this->position}) === FALSE) { $this->position++; } return substr($this->rawtext, $startpos, $this->position - $startpos); } function ignoreWhitespace() { while ($this->position < $this->length && strpos(" \n\r\t", $this->rawtext{$this->position}) !== FALSE) { $this->position++; } } function parse($data) { parent::parse($data); } } class XML_HTMLSax3_StateParser_Gtet430 extends XML_HTMLSax3_StateParser { function XML_HTMLSax3_StateParser_Gtet430(& $htmlsax) { parent::XML_HTMLSax3_StateParser($htmlsax); $this->parser_options['XML_OPTION_TRIM_DATA_NODES'] = 0; $this->parser_options['XML_OPTION_CASE_FOLDING'] = 0; $this->parser_options['XML_OPTION_LINEFEED_BREAK'] = 0; $this->parser_options['XML_OPTION_TAB_BREAK'] = 0; $this->parser_options['XML_OPTION_ENTITIES_PARSED'] = 0; $this->parser_options['XML_OPTION_ENTITIES_UNPARSED'] = 0; $this->parser_options['XML_OPTION_STRIP_ESCAPES'] = 0; } function scanUntilCharacters($string) { $startpos = $this->position; $length = strcspn($this->rawtext, $string, $startpos); $this->position += $length; return substr($this->rawtext, $startpos, $length); } function ignoreWhitespace() { $this->position += strspn($this->rawtext, " \n\r\t", $this->position); } function parse($data) { parent::parse($data); } } class XML_HTMLSax3_NullHandler { function DoNothing() { } } class XML_HTMLSax3 { var $state_parser; function XML_HTMLSax3() { if (version_compare(phpversion(), '4.3', 'ge')) { $this->state_parser = new XML_HTMLSax3_StateParser_Gtet430($this); } else { $this->state_parser = new XML_HTMLSax3_StateParser_Lt430($this); } $nullhandler = new XML_HTMLSax3_NullHandler(); $this->set_object($nullhandler); $this->set_element_handler('DoNothing', 'DoNothing'); $this->set_data_handler('DoNothing'); $this->set_pi_handler('DoNothing'); $this->set_jasp_handler('DoNothing'); $this->set_escape_handler('DoNothing'); } function set_object(&$object) { if ( is_object($object) ) { $this->state_parser->handler_default =& $object; return true; } else { require_once('PEAR.php'); PEAR::raiseError('XML_HTMLSax3::set_object requires '. 'an object instance'); } } function set_option($name, $value=1) { if ( array_key_exists($name,$this->state_parser->parser_options) ) { $this->state_parser->parser_options[$name] = $value; return true; } else { require_once('PEAR.php'); PEAR::raiseError('XML_HTMLSax3::set_option('.$name.') illegal'); } } function set_data_handler($data_method) { $this->state_parser->handler_object_data =& $this->state_parser->handler_default; $this->state_parser->handler_method_data = $data_method; } function set_element_handler($opening_method, $closing_method) { $this->state_parser->handler_object_element =& $this->state_parser->handler_default; $this->state_parser->handler_method_opening = $opening_method; $this->state_parser->handler_method_closing = $closing_method; } function set_pi_handler($pi_method) { $this->state_parser->handler_object_pi =& $this->state_parser->handler_default; $this->state_parser->handler_method_pi = $pi_method; } function set_escape_handler($escape_method) { $this->state_parser->handler_object_escape =& $this->state_parser->handler_default; $this->state_parser->handler_method_escape = $escape_method; } function set_jasp_handler ($jasp_method) { $this->state_parser->handler_object_jasp =& $this->state_parser->handler_default; $this->state_parser->handler_method_jasp = $jasp_method; } function get_current_position() { return $this->state_parser->position; } function get_length() { return $this->state_parser->length; } function parse($data) { $this->state_parser->parse($data); } } ?>index.php000066600000000002151454721230006364 0ustar00X HTMLSax3/States.php000066600000011545151454721230010041 0ustar00scanUntilString('<'); if ($data != '') { $context->handler_object_data-> {$context->handler_method_data}($context->htmlsax, $data); } $context->IgnoreCharacter(); return XML_HTMLSAX3_STATE_TAG; } } class XML_HTMLSax3_TagState { function parse(&$context) { switch($context->ScanCharacter()) { case '/': return XML_HTMLSAX3_STATE_CLOSING_TAG; break; case '?': return XML_HTMLSAX3_STATE_PI; break; case '%': return XML_HTMLSAX3_STATE_JASP; break; case '!': return XML_HTMLSAX3_STATE_ESCAPE; break; default: $context->unscanCharacter(); return XML_HTMLSAX3_STATE_OPENING_TAG; } } } class XML_HTMLSax3_ClosingTagState { function parse(&$context) { $tag = $context->scanUntilCharacters('/>'); if ($tag != '') { $char = $context->scanCharacter(); if ($char == '/') { $char = $context->scanCharacter(); if ($char != '>') { $context->unscanCharacter(); } } $context->handler_object_element-> {$context->handler_method_closing}($context->htmlsax, $tag, FALSE); } return XML_HTMLSAX3_STATE_START; } } class XML_HTMLSax3_OpeningTagState { function parseAttributes(&$context) { $Attributes = array(); $context->ignoreWhitespace(); $attributename = $context->scanUntilCharacters("=/> \n\r\t"); while ($attributename != '') { $attributevalue = NULL; $context->ignoreWhitespace(); $char = $context->scanCharacter(); if ($char == '=') { $context->ignoreWhitespace(); $char = $context->ScanCharacter(); if ($char == '"') { $attributevalue= $context->scanUntilString('"'); $context->IgnoreCharacter(); } else if ($char == "'") { $attributevalue = $context->scanUntilString("'"); $context->IgnoreCharacter(); } else { $context->unscanCharacter(); $attributevalue = $context->scanUntilCharacters("> \n\r\t"); } } else if ($char !== NULL) { $attributevalue = NULL; $context->unscanCharacter(); } $Attributes[$attributename] = $attributevalue; $context->ignoreWhitespace(); $attributename = $context->scanUntilCharacters("=/> \n\r\t"); } return $Attributes; } function parse(&$context) { $tag = $context->scanUntilCharacters("/> \n\r\t"); if ($tag != '') { $this->attrs = array(); $Attributes = $this->parseAttributes($context); $char = $context->scanCharacter(); if ($char == '/') { $char = $context->scanCharacter(); if ($char != '>') { $context->unscanCharacter(); } $context->handler_object_element-> {$context->handler_method_opening}($context->htmlsax, $tag, $Attributes, TRUE); $context->handler_object_element-> {$context->handler_method_closing}($context->htmlsax, $tag, TRUE); } else { $context->handler_object_element-> {$context->handler_method_opening}($context->htmlsax, $tag, $Attributes, FALSE); } } return XML_HTMLSAX3_STATE_START; } } class XML_HTMLSax3_EscapeState { function parse(&$context) { $char = $context->ScanCharacter(); if ($char == '-') { $char = $context->ScanCharacter(); if ($char == '-') { $context->unscanCharacter(); $context->unscanCharacter(); $text = $context->scanUntilString('-->'); $text .= $context->scanCharacter(); $text .= $context->scanCharacter(); } else { $context->unscanCharacter(); $text = $context->scanUntilString('>'); } } else if ( $char == '[') { $context->unscanCharacter(); $text = $context->scanUntilString(']>'); $text.= $context->scanCharacter(); } else { $context->unscanCharacter(); $text = $context->scanUntilString('>'); } $context->IgnoreCharacter(); if ($text != '') { $context->handler_object_escape-> {$context->handler_method_escape}($context->htmlsax, $text); } return XML_HTMLSAX3_STATE_START; } } class XML_HTMLSax3_JaspState { function parse(&$context) { $text = $context->scanUntilString('%>'); if ($text != '') { $context->handler_object_jasp-> {$context->handler_method_jasp}($context->htmlsax, $text); } $context->IgnoreCharacter(); $context->IgnoreCharacter(); return XML_HTMLSAX3_STATE_START; } } class XML_HTMLSax3_PiState { function parse(&$context) { $target = $context->scanUntilCharacters(" \n\r\t"); $data = $context->scanUntilString('?>'); if ($data != '') { $context->handler_object_pi-> {$context->handler_method_pi}($context->htmlsax, $target, $data); } $context->IgnoreCharacter(); $context->IgnoreCharacter(); return XML_HTMLSAX3_STATE_START; } } ?>HTMLSax3/index.php000066600000000002151454721230007667 0ustar00X HTMLSax3/Decorators.php000066600000006756151454721230010713 0ustar00orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function trimData(&$parser, $data) { $data = trim($data); if ($data != '') { $this->orig_obj->{$this->orig_method}($parser, $data); } } } class XML_HTMLSax3_CaseFolding { var $orig_obj; var $orig_open_method; var $orig_close_method; function XML_HTMLSax3_CaseFolding(&$orig_obj, $orig_open_method, $orig_close_method) { $this->orig_obj =& $orig_obj; $this->orig_open_method = $orig_open_method; $this->orig_close_method = $orig_close_method; } function foldOpen(&$parser, $tag, $attrs=array(), $empty = FALSE) { $this->orig_obj->{$this->orig_open_method}($parser, strtoupper($tag), $attrs, $empty); } function foldClose(&$parser, $tag, $empty = FALSE) { $this->orig_obj->{$this->orig_close_method}($parser, strtoupper($tag), $empty); } } class XML_HTMLSax3_Linefeed { var $orig_obj; var $orig_method; function XML_HTMLSax3_LineFeed(&$orig_obj, $orig_method) { $this->orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function breakData(&$parser, $data) { $data = explode("\n",$data); foreach ( $data as $chunk ) { $this->orig_obj->{$this->orig_method}($parser, $chunk); } } } class XML_HTMLSax3_Tab { var $orig_obj; var $orig_method; function XML_HTMLSax3_Tab(&$orig_obj, $orig_method) { $this->orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function breakData(&$parser, $data) { $data = explode("\t",$data); foreach ( $data as $chunk ) { $this->orig_obj->{$this->orig_method}($this, $chunk); } } } class XML_HTMLSax3_Entities_Parsed { var $orig_obj; var $orig_method; function XML_HTMLSax3_Entities_Parsed(&$orig_obj, $orig_method) { $this->orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function breakData(&$parser, $data) { $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); foreach ( $data as $chunk ) { $chunk = html_entity_decode($chunk,ENT_NOQUOTES); $this->orig_obj->{$this->orig_method}($this, $chunk); } } } if (version_compare(phpversion(), '4.3', '<') && !function_exists('html_entity_decode') ) { function html_entity_decode($str, $style=ENT_NOQUOTES) { return strtr($str, array_flip(get_html_translation_table(HTML_ENTITIES,$style))); } } class XML_HTMLSax3_Entities_Unparsed { var $orig_obj; var $orig_method; function XML_HTMLSax3_Entities_Unparsed(&$orig_obj, $orig_method) { $this->orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function breakData(&$parser, $data) { $data = preg_split('/(&.+?;)/',$data,-1,PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); foreach ( $data as $chunk ) { $this->orig_obj->{$this->orig_method}($this, $chunk); } } } class XML_HTMLSax3_Escape_Stripper { var $orig_obj; var $orig_method; function XML_HTMLSax3_Escape_Stripper(&$orig_obj, $orig_method) { $this->orig_obj =& $orig_obj; $this->orig_method = $orig_method; } function strip(&$parser, $data) { if ( substr($data,0,2) == '--' ) { $patterns = array( '/^\-\-/', // Opening comment: -- '/\-\-$/', // Closing comment: -- ); $data = preg_replace($patterns,'',$data); } else if ( substr($data,0,1) == '[' ) { $patterns = array( '/^\[.*CDATA.*\[/s', // Opening CDATA '/\].*\]$/s', // Closing CDATA ); $data = preg_replace($patterns,'',$data); } $this->orig_obj->{$this->orig_method}($this, $data); } } ?>safehtml.php000066600000022017151454721230007072 0ustar00 * @copyright 2004-2005 Roman Ivanov * @license http://www.debian.org/misc/bsd.license BSD License (3 Clause) * @version 1.3.7 * @link http://pixel-apes.com/safehtml/ */ require_once(XML_HTMLSAX3 . 'HTMLSax3.php'); class SafeHTML { var $_xhtml = ''; var $_counter = array(); var $_stack = array(); var $_dcCounter = array(); var $_dcStack = array(); var $_listScope = 0; var $_liStack = array(); var $_protoRegexps = array(); var $_cssRegexps = array(); var $singleTags = array('area', 'br', 'img', 'input', 'hr', 'wbr', ); var $deleteTags = array( 'applet', 'base', 'basefont', 'bgsound', 'blink', 'body', 'embed', 'frame', 'frameset', 'head', 'html', 'ilayer', 'iframe', 'layer', 'link', 'meta', 'object', 'style', 'title', 'script', ); var $deleteTagsContent = array('script', 'style', 'title', 'xml', ); var $protocolFiltering = 'white'; var $blackProtocols = array( 'about', 'chrome', 'data', 'disk', 'hcp', 'help', 'javascript', 'livescript', 'lynxcgi', 'lynxexec', 'ms-help', 'ms-its', 'mhtml', 'mocha', 'opera', 'res', 'resource', 'shell', 'vbscript', 'view-source', 'vnd.ms.radio', 'wysiwyg', ); var $whiteProtocols = array( 'ed2k', 'file', 'ftp', 'gopher', 'http', 'https', 'irc', 'mailto', 'news', 'nntp', 'telnet', 'webcal', 'xmpp', 'callto', ); var $protocolAttributes = array( 'action', 'background', 'codebase', 'dynsrc', 'href', 'lowsrc', 'src', ); var $cssKeywords = array( 'absolute', 'behavior', 'behaviour', 'content', 'expression', 'fixed', 'include-source', 'moz-binding', ); var $noClose = array(); var $closeParagraph = array( 'address', 'blockquote', 'center', 'dd', 'dir', 'div', 'dl', 'dt', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hr', 'isindex', 'listing', 'marquee', 'menu', 'multicol', 'ol', 'p', 'plaintext', 'pre', 'table', 'ul', 'xmp', ); var $tableTags = array( 'caption', 'col', 'colgroup', 'tbody', 'td', 'tfoot', 'th', 'thead', 'tr', ); var $listTags = array('dir', 'menu', 'ol', 'ul', 'dl', ); var $attributes = array('dynsrc', 'id', 'name', ); var $attributesNS = array('xml:lang', ); function SafeHTML() { //making regular expressions based on Proto & CSS arrays foreach ($this->blackProtocols as $proto) { $preg = "/[\s\x01-\x1F]*"; for ($i=0; $i_protoRegexps[] = $preg; } foreach ($this->cssKeywords as $css) { $this->_cssRegexps[] = '/' . $css . '/i'; } return true; } function _writeAttrs ($attrs) { if (is_array($attrs)) { foreach ($attrs as $name => $value) { $name = strtolower($name); if (strpos($name, 'on') === 0) { continue; } if (strpos($name, 'data') === 0) { continue; } if (in_array($name, $this->attributes)) { continue; } if (!preg_match("/^[a-z0-9-]+$/i", $name)) { if (!in_array($name, $this->attributesNS)) { continue; } } if (($value === TRUE) || (is_null($value))) { $value = $name; } if ($name == 'style') { // removes insignificant backslahes $value = str_replace("\\", '', $value); // removes CSS comments while (1) { $_value = preg_replace("!/\*.*?\*/!s", '', $value); if ($_value == $value) break; $value = $_value; } // replace all & to & $value = str_replace('&', '&', $value); $value = str_replace('&', '&', $value); foreach ($this->_cssRegexps as $css) { if (preg_match($css, $value)) { continue 2; } } foreach ($this->_protoRegexps as $proto) { if (preg_match($proto, $value)) { continue 2; } } } $tempval = preg_replace('/&#(\d+);?/me', "chr('\\1')", $value); //"' $tempval = preg_replace('/&#x([0-9a-f]+);?/mei', "chr(hexdec('\\1'))", $tempval); if ((in_array($name, $this->protocolAttributes)) && (strpos($tempval, ':') !== false)) { if ($this->protocolFiltering == 'black') { foreach ($this->_protoRegexps as $proto) { if (preg_match($proto, $tempval)) continue 2; } } else { $_tempval = explode(':', $tempval); $proto = $_tempval[0]; if (!in_array($proto, $this->whiteProtocols)) { continue; } } } $value = str_replace("\"", """, $value); $this->_xhtml .= ' ' . $name . '="' . $value . '"'; } } return true; } function _openHandler(&$parser, $name, $attrs) { $name = strtolower($name); if (in_array($name, $this->deleteTagsContent)) { array_push($this->_dcStack, $name); $this->_dcCounter[$name] = isset($this->_dcCounter[$name]) ? $this->_dcCounter[$name]+1 : 1; } if (count($this->_dcStack) != 0) { return true; } if (in_array($name, $this->deleteTags)) { return true; } if (!preg_match("/^[a-z0-9]+$/i", $name)) { if (preg_match("!(?:\@|://)!i", $name)) { $this->_xhtml .= '<' . $name . '>'; } return true; } if (in_array($name, $this->singleTags)) { $this->_xhtml .= '<' . $name; $this->_writeAttrs($attrs); $this->_xhtml .= ' />'; return true; } // TABLES: cannot open table elements when we are not inside table if ((isset($this->_counter['table'])) && ($this->_counter['table'] <= 0) && (in_array($name, $this->tableTags))) { return true; } // PARAGRAPHS: close paragraph when closeParagraph tags opening if ((in_array($name, $this->closeParagraph)) && (in_array('p', $this->_stack))) { $this->_closeHandler($parser, 'p'); } // LISTS: we should close
  • if
  • of the same level opening if ($name == 'li' && count($this->_liStack) && $this->_listScope == $this->_liStack[count($this->_liStack)-1]) { $this->_closeHandler($parser, 'li'); } // LISTS: we want to know on what nesting level of lists we are if (in_array($name, $this->listTags)) { $this->_listScope++; } if ($name == 'li') { array_push($this->_liStack, $this->_listScope); } $this->_xhtml .= '<' . $name; $this->_writeAttrs($attrs); $this->_xhtml .= '>'; array_push($this->_stack,$name); $this->_counter[$name] = isset($this->_counter[$name]) ? $this->_counter[$name]+1 : 1; return true; } function _closeHandler(&$parser, $name) { $name = strtolower($name); if (isset($this->_dcCounter[$name]) && ($this->_dcCounter[$name] > 0) && (in_array($name, $this->deleteTagsContent))) { while ($name != ($tag = array_pop($this->_dcStack))) { $this->_dcCounter[$tag]--; } $this->_dcCounter[$name]--; } if (count($this->_dcStack) != 0) { return true; } if ((isset($this->_counter[$name])) && ($this->_counter[$name] > 0)) { while ($name != ($tag = array_pop($this->_stack))) { $this->_closeTag($tag); } $this->_closeTag($name); } return true; } function _closeTag($tag) { if (!in_array($tag, $this->noClose)) { $this->_xhtml .= ''; } $this->_counter[$tag]--; if (in_array($tag, $this->listTags)) { $this->_listScope--; } if ($tag == 'li') { array_pop($this->_liStack); } return true; } function _dataHandler(&$parser, $data) { if (count($this->_dcStack) == 0) { $this->_xhtml .= $data; } return true; } function _escapeHandler(&$parser, $data) { return true; } function getXHTML () { while ($tag = array_pop($this->_stack)) { $this->_closeTag($tag); } return $this->_xhtml; } function clear() { $this->_xhtml = ''; return true; } function parse($doc) { // Save all '<' symbols $doc = preg_replace("/<(?=[^a-zA-Z\/\!\?\%])/", '<', $doc); // Web documents shouldn't contains \x00 symbol $doc = str_replace("\x00", '', $doc); // Opera6 bug workaround $doc = str_replace("\xC0\xBC", '<', $doc); // UTF-7 encoding ASCII decode $doc = $this->repackUTF7($doc); // Instantiate the parser $parser= new XML_HTMLSax3(); // Set up the parser $parser->set_object($this); $parser->set_element_handler('_openHandler','_closeHandler'); $parser->set_data_handler('_dataHandler'); $parser->set_escape_handler('_escapeHandler'); $parser->parse($doc); return $this->getXHTML(); } function repackUTF7($str) { return preg_replace_callback('!\+([0-9a-zA-Z/]+)\-!', array($this, 'repackUTF7Callback'), $str); } function repackUTF7Callback($str) { $str = base64_decode($str[1]); $str = preg_replace_callback('/^((?:\x00.)*)((?:[^\x00].)+)/', array($this, 'repackUTF7Back'), $str); return preg_replace('/\x00(.)/', '$1', $str); } function repackUTF7Back($str) { return $str[1].'+'.rtrim(base64_encode($str[2]), '=').'-'; } } ?> type_pwd.php000066600000001204151506635500007117 0ustar00val[$champ]) < 5){ $cfg->ajouter_erreur($champ, _T('cfg:erreur_type_pwd', array('champ'=>$champ))); } return true; } ?> cfg_couleur.php000066600000001575151506635500007574 0ustar00param['selecteur_couleur'] = 1; $cfg->ajouter_extension_parametre('selecteur_couleur'); return $cfg; } ?> cfg_id.php000066600000004253151506635500006506 0ustar00champs[$nom]['id'] = count($cfg->champs_id); $cfg->champs_id[] = $nom; // Cas des champs multi, si des champs (Y) // sont declares id par la classe cfg_id, // // on les ajoute dans le chemin pour retrouver les donnees // #CONFIG{.../y1/y2/y3/...} // if (_request('_cfg_affiche')) { $cfg->param['cfg_id'] = implode('/', array_map('_request', $cfg->champs_id)); } return true; } /** * * @param string $nom * @param Object $cfg * @return string */ function cfg_pre_traiter_cfg_id($nom, &$cfg){ // lorsque c'est un champ de type multi que l'on modifie // et si l'identifiant a change, il faut soit le copier, soit de deplacer // // pour ca, on compare le hidden name='cfg_id' aux champs editables // qui ont la classe css 'cfg_id' if ($cfg->champs_id) { $new_id = implode('/', array_map('_request', $cfg->champs_id)); if ($new_id != $cfg->param['cfg_id']){ // si c'est un deplacement, on efface if (!_request('_cfg_copier')) { // et ne pas perdre les valeurs suite a l'effacement dans ce cas precis $vals = $cfg->val; $cfg->effacer(); $cfg->val = $vals; } $cfg->param['cfg_id'] = $new_id; // recreer un depot avec le nouvel identifiant // (sinon les requetes ne creent pas les bons 'where') include_spip('inc/cfg_config'); $cfg->depot = new cfg_depot($cfg->param['depot'], $cfg->params); // recharger le formulaire avec le nouvel identifiant (sinon les parametres // de formulaires qui contienent // #ENV{cfg_id} ou #ENV{id} ne sont pas a jour) $cfg->formulaire(); } } return true; } ?> type_idnum.php000066600000001500151506635500007440 0ustar00val[$champ])){ $cfg->ajouter_erreur(_T('cfg:erreur_type_idnum', array('champ'=>$champ))); } return true; } /** * * @param string $champ * @param Object $cfg * @return string */ function cfg_pre_traiter_type_idnum($champ, &$cfg){ $cfg->val[$champ] = intval($cfg->val[$champ]); return true; } ?> cfg_fichier.php000066600000024363151506635500007527 0ustar00champs[$nom], $cfg->extensions['cfg_fichier'][$nom]); // sinon indiquer un changement // pour eviter le message d'erreur "pas de changement" } else { set_request($nom, ''. $cfg->val[$nom]); } return $cfg; } /** * Pré-traitement du fichier $nom * * @param string $nom * @param Object $cfg * @return Object */ function cfg_pre_traiter_cfg_fichier($nom, &$cfg){ include_spip('inc/flock'); // enlever $cfg->val[$nom] = str_replace('','', $cfg->val[$nom]); // effacement if (_request('_cfg_delete')){ $supprimer_fichier = _COMPAT_CFG_192 ? 'cfg_supprimer_fichier' : 'supprimer_fichier'; if (!$supprimer_fichier(get_spip_doc($cfg->val[$nom]))) { $cfg->messages['erreurs'][$nom] = _T('cfg:erreur_suppression_fichier', array('fichier'=>get_spip_doc($cfg->val[$nom]))); } // ajout ou modification } else { $f = cfg_get_info_fichier_upload($nom); if ($f['tmp_name']) { // suppression de l'ancien fichier $supprimer_fichier = _COMPAT_CFG_192 ? 'cfg_supprimer_fichier' : 'supprimer_fichier'; if ($cfg->val[$nom] && !$supprimer_fichier(get_spip_doc($cfg->val[$nom]))) { $cfg->messages['erreurs'][$nom] = _T('cfg:erreur_suppression_fichier', array('fichier'=>get_spip_doc($cfg->val[$nom]))); } else { if (!$fichier = cfg_ajoute_un_document($f['tmp_name'],$f['name'],$nom, 'config/'.$cfg->vue)){ $cfg->messages['erreurs'][$nom] = _T('cfg:erreur_copie_fichier', array('fichier'=>'config/'.$cfg->vue . '/' . $f['name'])); } else { $cfg->val[$nom] = set_spip_doc($fichier); } } } } return $cfg; } /** * * @param string $nom * @return string */ function cfg_get_info_fichier_upload($nom){ return $_FILES ? $_FILES[$nom] : $GLOBALS['HTTP_POST_FILES'][$nom]; } /** * Ajouter un document (au format $_FILES)
    * (n'ajoute pas le contenu en base dans spip_documents...) * * @param string $source Le fichier sur le serveur (/var/tmp/xyz34) * @param string $nom_envoye Son nom chez le client (portequoi.pdf) * @param string $nom_dest Le nom sous lequel le sauvegarder * @param string $dans Où l'enregistrer * @return string */ function cfg_ajoute_un_document($source, $nom_envoye, $nom_dest, $dans='config') { include_spip('inc/modifier'); include_spip('inc/ajouter_documents'); $type_image = ''; // au pire // tester le type de document : // - interdit a l'upload ? // - quelle extension dans spip_types_documents ? // - est-ce "inclus" comme une image ? preg_match(",^(.*)\.([^.]+)$,", $nom_envoye, $match); @list(,$titre,$ext) = $match; $ext = corriger_extension(strtolower($ext)); // ajouter l'extension au nom propose... $row = sql_fetsel("inclus", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"); if ($row) { $type_inclus_image = ($row['inclus'] == 'image'); // hum stocke dans IMG/$ext ? $fichier = cfg_copier_document($ext, $nom_dest.'.'.$ext, $source, $dans); } else { /* STOCKER LES DOCUMENTS INCONNUS AU FORMAT .ZIP */ $type_inclus_image = false; if (!sql_countsel("spip_types_documents", "extension='zip' AND upload='oui'")) { spip_log("Extension $ext interdite a l'upload"); return; } $ext = 'zip'; if (!$tmp_dir = tempnam(_DIR_TMP, 'tmp_upload')) return; spip_unlink($tmp_dir); @mkdir($tmp_dir); $tmp = $tmp_dir.'/'.translitteration($nom_envoye); $nom_envoye .= '.zip'; # conserver l'extension dans le nom de fichier, par exemple toto.js => toto.js.zip _COMPAT_CFG_192 ? cfg_deplacer_fichier_upload($source, $tmp) : deplacer_fichier_upload($source, $tmp); include_spip('inc/pclzip'); $source = _DIR_TMP . 'archive.zip'; $archive = new PclZip($source); $v_list = $archive->create($tmp, PCLZIP_OPT_REMOVE_PATH, $tmp_dir, PCLZIP_OPT_ADD_PATH, ''); effacer_repertoire_temporaire($tmp_dir); if (!$v_list) { spip_log("Echec creation du zip "); return; } // hum too ? $fichier = cfg_copier_document($ext, $nom_dest.'.zip', $source, $dans); spip_unlink($source); } if ($ext == "svg") { // supprimer les scripts traite_svg($fichier); } elseif ($ext != "mov") {// image ? // Si c'est une image, recuperer sa taille et son type (detecte aussi swf) $size_image = @getimagesize($fichier); $type_image = decoder_type_image($size_image[2]); } // Quelques infos sur le fichier if (!$fichier OR !@file_exists($fichier) OR !$taille = @intval(filesize($fichier))) { spip_log ("Echec copie du fichier $fichier"); return; } if (!$type_image) { if (_DOC_MAX_SIZE > 0 AND $taille > _DOC_MAX_SIZE*1024) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_poids', array('maxi' => taille_en_octets(_DOC_MAX_SIZE*1024), 'actuel' => taille_en_octets($taille)))); } } else { // image if (_IMG_MAX_SIZE > 0 AND $taille > _IMG_MAX_SIZE*1024) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_poids', array('maxi' => taille_en_octets(_IMG_MAX_SIZE*1024), 'actuel' => taille_en_octets($taille)))); } if (_IMG_MAX_WIDTH * _IMG_MAX_HEIGHT AND ($size_image[0] > _IMG_MAX_WIDTH OR $size_image[1] > _IMG_MAX_HEIGHT)) { spip_unlink ($fichier); check_upload_error(6, _T('info_logo_max_taille', array( 'maxi' => _T('info_largeur_vignette', array('largeur_vignette' => _IMG_MAX_WIDTH, 'hauteur_vignette' => _IMG_MAX_HEIGHT)), 'actuel' => _T('info_largeur_vignette', array('largeur_vignette' => $size_image[0], 'hauteur_vignette' => $size_image[1])) ))); } } return $fichier; } /** * Copier un document * * @param string $ext L'extension du fichier * @param string $dest le nom sous lequel le sauvegarder * @param string $source le fichier sur le serveur (/var/tmp/xyz34) * @param string $dans Où le copier * @return string */ function cfg_copier_document($ext, $dest, $source, $dans='_cfg') { $dest = preg_replace(',\.\.+,', '.', $dest); // pas de .. dans le nom du doc $dir = cfg_creer_repertoire_cfg($dans); $dest = preg_replace("/[^._=-\w\d]+/", "_", translitteration(preg_replace("/\.([^.]+)$/", "", preg_replace("/<[^>]*>/", '', basename($dest))))); // ne pas accepter de noms de la forme -r90.jpg qui sont reserves // pour les images transformees par rotation (action/documenter) $dest = preg_replace(',-r(90|180|270)$,', '', $dest); $newFile = $dir . $dest .'.'.$ext; return _COMPAT_CFG_192 ? cfg_deplacer_fichier_upload($source, $newFile) : deplacer_fichier_upload($source, $newFile); } /** * Creer IMG/config/vue * comme "creer_repertoire_documents" mais avec 2 profondeurs * * @param string $ext * @return string */ function cfg_creer_repertoire_cfg($ext) { list($racine, $vue) = explode('/',$ext,2); if ($rep = sous_repertoire(_DIR_IMG, $racine)){ $rep = sous_repertoire(_DIR_IMG.$racine, $vue); } if (!$ext OR !$rep) { spip_log("creer_repertoire_cfg interdit"); exit; } // Cette variable de configuration peut etre posee par un plugin // par exemple acces_restreint if ($GLOBALS['meta']["creer_htaccess"] == 'oui') { include_spip('inc/acces'); verifier_htaccess($rep); } return $rep; } /* * compat 1.9.2 : * il y a plein de fonctions qui ont change !! */ if (_COMPAT_CFG_192) { /** * pas de securite tuante sur .. comme en 1.9.3
    * * @deprecated depuis SPIP 2.0 * @param string $source Le nom du fichier source * @param string $dest Le nom du fichier de destination * @param boolean $move TRUE si on le déplace * @return boolean|string La destination comme 1.9.3 */ function cfg_deplacer_fichier_upload($source, $dest, $move=false) { // Securite if (substr($dest,0,strlen(_DIR_RACINE))==_DIR_RACINE) $dest = _DIR_RACINE.preg_replace(',\.\.+,', '.', substr($dest,strlen(_DIR_RACINE))); else $dest = preg_replace(',\.\.+,', '.', $dest); if ($move) $ok = @rename($source, $dest); else $ok = @copy($source, $dest); if (!$ok) $ok = @move_uploaded_file($source, $dest); if ($ok) @chmod($dest, _SPIP_CHMOD & ~0111); else { $f = @fopen($dest,'w'); if ($f) { fclose ($f); } else { include_spip('inc/headers'); redirige_par_entete(generer_url_action("test_dirs", "test_dir=". dirname($dest), true)); } @unlink($dest); } return $ok ? $dest : false; } /** * Supprimer le fichier de maniere sympa (flock) * * @deprecated depuis SPIP 2.0 * @param string $fichier Le nom du fichier à supprimer * @return boolean */ function cfg_supprimer_fichier($fichier) { if (!@file_exists($fichier)) return true; // verrouiller le fichier destination if ($fp = @fopen($fichier, 'a')) @flock($fp, LOCK_EX); else return false; // liberer le verrou @flock($fp, LOCK_UN); @fclose($fp); // supprimer return @unlink($fichier); } if (!function_exists('set_spip_doc')){ /** * donne le chemin du fichier relatif a _DIR_IMG
    * pour stockage 'tel quel' dans la base de donnees * * @deprecated depuis SPIP 2.0 * @param string $fichier * @return string */ function set_spip_doc($fichier) { if (strpos($fichier, _DIR_IMG) === 0) return substr($fichier, strlen(_DIR_IMG)); else return $fichier; // ex: fichier distant } } if (!function_exists('get_spip_doc')){ /** * donne le chemin complet du fichier * * @deprecated depuis SPIP 2.0 * @param string $fichier * @return string */ function get_spip_doc($fichier) { // fichier distant if (preg_match(',^\w+://,', $fichier)) return $fichier; // gestion d'erreurs, fichier='' if (!strlen($fichier)) return false; // fichier normal return (strpos($fichier, _DIR_IMG) === false) ? _DIR_IMG . $fichier : $fichier; } } } ?> type_id.php000066600000001210151506635500006716 0ustar00val[$champ])){ $cfg->ajouter_erreur(_T('cfg:erreur_type_id', array('champ'=>$champ))); } return true; } ?>