From: Leo Koppelkamm Date: Tue, 12 Apr 2011 21:27:24 +0000 (+0000) Subject: (no commit message) X-Git-Tag: 1.31.0-rc.0~30885 X-Git-Url: https://git.cyclocoop.org/%7B%24admin_url%7Dmembres/cotisations/rappels.php?a=commitdiff_plain;h=109f7bcb9de9b9f82baa5a9a7454dc7448a05aec;p=lhc%2Fweb%2Fwiklou.git --- diff --git a/includes/Sanitizer.php b/includes/Sanitizer.php index 0fd593f295..fa961cf974 100644 --- a/includes/Sanitizer.php +++ b/includes/Sanitizer.php @@ -369,7 +369,7 @@ class Sanitizer { 'strike', 'strong', 'tt', 'var', 'div', 'center', 'blockquote', 'ol', 'ul', 'dl', 'table', 'caption', 'pre', 'ruby', 'rt' , 'rb' , 'rp', 'p', 'span', 'abbr', 'dfn', - 'kbd', 'samp' + 'kbd', 'samp', 'thead', 'tbody', 'tfoot' ); $htmlsingle = array( 'br', 'hr', 'li', 'dt', 'dd' diff --git a/includes/parser/Parser.php b/includes/parser/Parser.php index b14e366e8c..7045690b15 100644 --- a/includes/parser/Parser.php +++ b/includes/parser/Parser.php @@ -824,189 +824,283 @@ class Parser { $lines = StringUtils::explode( "\n", $text ); $out = ''; - $td_history = array(); # Is currently a td tag open? - $last_tag_history = array(); # Save history of last lag activated (td, th or caption) - $tr_history = array(); # Is currently a tr tag open? - $tr_attributes = array(); # history of tr attributes - $has_opened_tr = array(); # Did this table open a element? - $indent_level = 0; # indent level of the table + $output =& $out; foreach ( $lines as $outLine ) { $line = trim( $outLine ); - if ( $line === '' ) { # empty line, go to next line + if ( $line == '') { //empty line, go to next line $out .= $outLine."\n"; continue; } - - $first_character = $line[0]; + $first_chars = $line[0]; + if ( strlen($line) > 1) { + $first_chars .= in_array($line[1], array('}', '+', '-')) ? $line[1] : ''; + } $matches = array(); if ( preg_match( '/^(:*)\{\|(.*)$/', $line , $matches ) ) { - # First check if we are starting a new table - $indent_level = strlen( $matches[1] ); + $tables[] = array(); + $table =& $this->last($tables); + $table[0] = array(); //first row + $current_row =& $table[0]; + + $table['indent'] = strlen( $matches[1] ); $attributes = $this->mStripState->unstripBoth( $matches[2] ); $attributes = Sanitizer::fixTagAttributes( $attributes , 'table' ); - $outLine = str_repeat( '
' , $indent_level ) . ""; - array_push( $td_history , false ); - array_push( $last_tag_history , '' ); - array_push( $tr_history , false ); - array_push( $tr_attributes , '' ); - array_push( $has_opened_tr , false ); - } elseif ( count( $td_history ) == 0 ) { - # Don't do any of the following - $out .= $outLine."\n"; - continue; - } elseif ( substr( $line , 0 , 2 ) === '|}' ) { - # We are ending a table - $line = '' . substr( $line , 2 ); - $last_tag = array_pop( $last_tag_history ); - - if ( !array_pop( $has_opened_tr ) ) { - $line = "{$line}"; + if ( $attributes !== '' ) { + $table['attributes'] = $attributes; } + } else if ( !isset($tables[0]) ) { + // we're outside the table - if ( array_pop( $tr_history ) ) { - $line = "{$line}"; + $out .= $outLine."\n"; + } else if ( $first_chars === '|}' ) { + // trim the |} code from the line + $line = substr ( $line , 2 ); + + // Shorthand for last row + $last_row =& $this->last($table); + + // a thead at the end becomes a tfoot, unless there is only one row + // Do this before deleting empty last lines to allow headers at the bottom of tables + if ( isset($last_row['type'] ) && $last_row['type'] == 'thead' && isset($table[1])) { + $last_row['type'] = 'tfoot'; + for($i = 0; isset($last_row[$i]); $i++ ) { + $last_row[$i]['type'] = 'td'; + } } - if ( array_pop( $td_history ) ) { - $line = "{$line}"; + // Delete empty last lines + if ( empty($last_row) ) { + $last_row = NULL; } - array_pop( $tr_attributes ); - $outLine = $line . str_repeat( '
' , $indent_level ); - } elseif ( substr( $line , 0 , 2 ) === '|-' ) { - # Now we have a table row - $line = preg_replace( '#^\|-+#', '', $line ); + $o = $this->printTableHtml( array_pop($tables) ) . $line; - # Whats after the tag is now only attributes - $attributes = $this->mStripState->unstripBoth( $line ); - $attributes = Sanitizer::fixTagAttributes( $attributes, 'tr' ); - array_pop( $tr_attributes ); - array_push( $tr_attributes, $attributes ); + if ( count($tables) > 0 ) { + $table =& $this->last($tables); + $current_row =& $this->last($table); + $current_element =& $this->last($current_row); - $line = ''; - $last_tag = array_pop( $last_tag_history ); - array_pop( $has_opened_tr ); - array_push( $has_opened_tr , true ); - - if ( array_pop( $tr_history ) ) { - $line = ''; + $output =& $current_element['content']; + } else { + $output =& $out; } - if ( array_pop( $td_history ) ) { - $line = "{$line}"; - } + $output .= $o; - $outLine = $line; - array_push( $tr_history , false ); - array_push( $td_history , false ); - array_push( $last_tag_history , '' ); - } elseif ( $first_character === '|' || $first_character === '!' || substr( $line , 0 , 2 ) === '|+' ) { - # This might be cell elements, td, th or captions - if ( substr( $line , 0 , 2 ) === '|+' ) { - $first_character = '+'; - $line = substr( $line , 1 ); + } else if ( $first_chars === '|-' ) { + // start a new row element + // but only when we haven't started one already + if( count($current_row) != 0 ) { + $table[] = array(); + $current_row =& $this->last($table); } - - $line = substr( $line , 1 ); - - if ( $first_character === '!' ) { - $line = str_replace( '!!' , '||' , $line ); + // Get the attributes, there's nothing else useful in $line now + $line = substr ( $line , 2 ); + $attributes = $this->mStripState->unstripBoth( $line ); + $attributes = Sanitizer::fixTagAttributes( $attributes, 'tr' ); + if( $attributes !== '') { + $current_row['attributes'] = $attributes; + } + + } else if ( $first_chars === '|+' ) { + // a table caption + $line = substr ( $line , 2 ); + + $c = $this->getCellAttr($line , 'caption'); + $table['caption'] = array(); + $table['caption']['content'] = $c[0]; + if(isset($c[1])) $table['caption']['attributes'] = $c[1]; + unset($c); + + $output =& $table['caption']; + } else if ( $first_chars === '|' || $first_chars === '!' || $first_chars === '!+' ) { + // Which kind of cells are we dealing with + $this_tag = 'td'; + $line = substr ( $line , 1 ); + + if ( $first_chars === '!' || $first_chars === '!+' ) { + $line = str_replace ( '!!' , '||' , $line ); + $this_tag = 'th'; } - # Split up multiple cells on the same line. - # FIXME : This can result in improper nesting of tags processed - # by earlier parser steps, but should avoid splitting up eg - # attribute values containing literal "||". + // Split up multiple cells on the same line. $cells = StringUtils::explodeMarkup( '||' , $line ); + $line = ''; // save memory - $outLine = ''; + // decide whether thead to tbody + if ( !array_key_exists('type', $current_row) ) { + $current_row['type'] = ( $first_chars === '!' ) ? 'thead' : 'tbody' ; + } else if( $first_chars === '|' ) { + $current_row['type'] = 'tbody'; + } - # Loop through each table cell + // Loop through each table cell foreach ( $cells as $cell ) { - $previous = ''; - if ( $first_character !== '+' ) { - $tr_after = array_pop( $tr_attributes ); - if ( !array_pop( $tr_history ) ) { - $previous = "\n"; - } - array_push( $tr_history , true ); - array_push( $tr_attributes , '' ); - array_pop( $has_opened_tr ); - array_push( $has_opened_tr , true ); - } + // a new cell + $current_row[] = array(); + $current_element =& $this->last($current_row); - $last_tag = array_pop( $last_tag_history ); + $current_element['type'] = $this_tag; - if ( array_pop( $td_history ) ) { - $previous = "\n{$previous}"; - } + $c = $this->getCellAttr($cell , $this_tag); + $current_element['content'] = $c[0]; + if(isset($c[1])) $current_element['attributes'] = $c[1]; + unset($c); + } + $output =& $current_element['content']; + + } else { + $output .= $outLine."\n"; + } + } + + # Remove trailing line-ending (b/c) + if ( substr( $out, -1 ) === "\n" ) { + $out = substr( $out, 0, -1 ); + } + + #Close any unclosed tables + if (isset($tables) && count($tables) > 0 ) { + for ($i = 0; $i < count($tables); $i++) { + $out .= $this->printTableHtml( array_pop($tables) ); + } + } + + wfProfileOut( __METHOD__ ); - if ( $first_character === '|' ) { - $last_tag = 'td'; - } elseif ( $first_character === '!' ) { - $last_tag = 'th'; - } elseif ( $first_character === '+' ) { - $last_tag = 'caption'; - } else { - $last_tag = ''; - } + return $out; + } - array_push( $last_tag_history , $last_tag ); - # A cell could contain both parameters and data - $cell_data = explode( '|' , $cell , 2 ); + /** + * Helper function for doTableStuff() separating the contents of cells from + * attributes. Particularly useful as there's a possible bug and this action + * is repeated twice. + * + * @private + */ + function getCellAttr ($cell , $tag_name) { + $content = null; + $attributes = null; - # Bug 553: Note that a '|' inside an invalid link should not - # be mistaken as delimiting cell parameters - if ( strpos( $cell_data[0], '[[' ) !== false ) { - $cell = "{$previous}<{$last_tag}>{$cell}"; - } elseif ( count( $cell_data ) == 1 ) { - $cell = "{$previous}<{$last_tag}>{$cell_data[0]}"; - } else { - $attributes = $this->mStripState->unstripBoth( $cell_data[0] ); - $attributes = Sanitizer::fixTagAttributes( $attributes , $last_tag ); - $cell = "{$previous}<{$last_tag}{$attributes}>{$cell_data[1]}"; - } + $cell = trim ( $cell ); - $outLine .= $cell; - array_push( $td_history , true ); - } - } - $out .= $outLine . "\n"; + // A cell could contain both parameters and data + $cell_data = explode ( '|' , $cell , 2 ); + + // Bug 553: Note that a '|' inside an invalid link should not + // be mistaken as delimiting cell parameters + if ( strpos( $cell_data[0], '[[' ) !== false ) { + $content = trim ( $cell ); } + else if ( count ( $cell_data ) == 1 ) { + $content = trim ( $cell_data[0] ); + } + else { + $attributes = $this->mStripState->unstripBoth( $cell_data[0] ); + $attributes = Sanitizer::fixTagAttributes( $attributes , $tag_name ); - # Closing open td, tr && table - while ( count( $td_history ) > 0 ) { - if ( array_pop( $td_history ) ) { - $out .= "\n"; - } - if ( array_pop( $tr_history ) ) { - $out .= "\n"; + $content = trim ( $cell_data[1] ); + } + return array($content, $attributes); + } + + + /** + * Helper function for doTableStuff(). This converts the structured array into html. + * + * @private + */ + function printTableHtml (&$t) { + $r = "\n"; + $r .= str_repeat( '
' , $t['indent'] ); + $r .= ''; } - $out .= "\n"; - } + $r .= "\n\n\n" ) { - $out = ''; + $r .= ''; + unset($t[$i][$j]); + } + $r .= "\n"; + + if( ( !isset($t[$i+1]) && !$simple )|| ( isset($t[$i+1]) && ($t[$i]['type'] != $t[$i+1]['type'])) ) { + $r .= ''; + } + $last_section = $t[$i]['type']; + unset($t[$i]); + } + if ( $empty ) { + if ( isset($t['caption']) ) { + $r .= "\n"; + } else { + return ''; + } } + $r .= "\n"; + $r .= str_repeat( '
' , $t['indent'] ); - wfProfileOut( __METHOD__ ); + return $r; + } - return $out; + /** + * like end() but only works on the numeric array index and php's internal pointers + * returns a reference to the last element of an array much like "\$arr[-1]" in perl + * ignores associative elements and will create a 0 key will a NULL value if there were + * no numric elements and an array itself if not previously defined. + * + * @private + */ + function &last (&$arr) { + for($i = count($arr); (!isset($arr[$i]) && $i > 0); $i--) { } + return $arr[$i]; } /** @@ -2239,7 +2333,7 @@ class Parser { 'mUniqPrefix.'-pre|<\\/li|<\\/ul|<\\/ol|<\\/?center)/iS', $t ); if ( $openmatch or $closematch ) { $paragraphStack = false; - # TODO bug 5718: paragraph closed + # TODO bug 5718: paragraph closed $output .= $this->closeParagraph(); if ( $preOpenMatch and !$preCloseMatch ) { $this->mInPre = true; diff --git a/skins/common/wikibits.js b/skins/common/wikibits.js index 3f9dc6752a..1db54f27fb 100644 --- a/skins/common/wikibits.js +++ b/skins/common/wikibits.js @@ -551,14 +551,7 @@ window.sortables_init = function() { }; window.ts_makeSortable = function( table ) { - var firstRow; - if ( table.rows && table.rows.length > 0 ) { - if ( table.tHead && table.tHead.rows.length > 0 ) { - firstRow = table.tHead.rows[table.tHead.rows.length-1]; - } else { - firstRow = table.rows[0]; - } - } + var firstRow = table.rows[0]; if ( !firstRow ) { return; } diff --git a/tests/parser/parserTests.txt b/tests/parser/parserTests.txt index bce99f6768..6e45e0aa73 100644 --- a/tests/parser/parserTests.txt +++ b/tests/parser/parserTests.txt @@ -1237,8 +1237,9 @@ A table with nothing but a caption |} !! result -
caption -
+caption + + !! end @@ -1253,13 +1254,14 @@ Simple table !! result - - + + + - -
1 2 -
12
3 4 -
+3 +4 + + !! end @@ -1288,49 +1290,46 @@ Multiplication table |} !! result - + + - - - - + + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - -
Multiplication table -Multiplication table
× 1 2 3 -
×123
1 - 1 2 3 -
1123
2 - 2 4 6 -
2246
3 - 3 6 9 -
3369
4 - 4 8 12 -
44812
5 - 5 10 15 -
+5 +5 +10 +15 + + !! end @@ -1348,17 +1347,15 @@ Table rowspan !! result - - - + + + + - -
Cell 1, row 1 - Cell 2, row 1 (and 2) - Cell 3, row 1 -
Cell 1, row 1Cell 2, row 1 (and 2)Cell 3, row 1
Cell 1, row 2 - Cell 3, row 2 -
+Cell 1, row 2 +Cell 3, row 2 + + !! end @@ -1378,19 +1375,19 @@ Nested table !! result - + -
α -α - + + -
nested -
nested
table -
-
the original table again -
+table + + +the original table again + + !! end @@ -1403,8 +1400,9 @@ Invalid attributes in table cell (bug 1830) !! result -
broken -
+broken + + !! end @@ -1418,8 +1416,7 @@ Table security: embedded pipes (http://lists.wikimedia.org/mailman/htdig/wikitec - +
[ftp://%7Cx]" onmouseover="alert(document.cookie)">test -]" onmouseover="alert(document.cookie)">test
@@ -2685,8 +2682,9 @@ BUG 553: link with two variables in a piped link !! result -
[[{{{1}}}|{{{2}}}]] -
+[[{{{1}}}|{{{2}}}]] + + !! end @@ -2795,13 +2793,14 @@ foo {{table}}

- - + + + - -
1 2 -
12
3 4 -
+3 +4 + + !! end @@ -2815,13 +2814,14 @@ foo

- - + + + - -
1 2 -
12
3 4 -
+3 +4 + + !! end @@ -4370,8 +4370,9 @@ Table multiple attributes correction !! result -
status -
+status + + !!end @@ -4815,8 +4816,9 @@ Table attribute legitimate extension !! result -
status -
+status + + !!end @@ -4829,8 +4831,9 @@ Table attribute safety !! result -
status -
+status + + !! end @@ -5452,8 +5455,7 @@ Fuzz testing: Parser13 !! result - +
-
@@ -5501,8 +5503,7 @@ noxml https:// - - + @@ -5517,10 +5518,8 @@ Fuzz testing: Parser21 !! result - - + +
irc://{{ftp://a" onmouseover="alert('hello world');" - -irc://{{ftp://a" onmouseover="alert('hello world');"
@@ -5542,6 +5541,22 @@ http://===r:::https://b !! end # Known to produce bad XML for now + +# Note: the current result listed for this is not what the original one was, +# but the original bug was JavaScript injection, which is fixed in any case. +# It's not clear that the original result listed was any more correct than the +# current one. Original result: +# +# {{{| +# }}}} > +#
+# +# MOVE YOUR MOUSE CURSOR OVER THIS TEXT +#
+# +# +#
+#
!! test Fuzz testing: Parser24 !! options @@ -5556,15 +5571,14 @@ noxml MOVE YOUR MOUSE CURSOR OVER THIS TEXT | !! result - -{{{| +

{{{| }}}} >
- -MOVE YOUR MOUSE CURSOR OVER THIS TEXT +

MOVE YOUR MOUSE CURSOR OVER THIS TEXT +

+
- +
-
@@ -7735,13 +7749,13 @@ y

- - + + + - -
1 2 -
12
3 4 -
+3 +4 +

y

!! end