From 45ea013b111547ef684cc7c64dd91a6217935ab1 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sun, 1 Jan 2017 21:22:29 +0100 Subject: [PATCH 1/4] [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. PHPBB3-14943 --- phpBB/phpbb/template/context.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index 8bf6c10e2d..f0bc4c859a 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -325,11 +325,13 @@ class context } $block = &$block[$blocks[$i]]; // Traverse the last block + $name = $blocks[$i]; } else { // Top-level block. $block = &$this->tpldata[$blockname]; + $name = $blockname; } // Change key to zero (change first position) if false and to last position if true @@ -378,7 +380,7 @@ class context } // Assign S_BLOCK_NAME - $vararray['S_BLOCK_NAME'] = $blockname; + $vararray['S_BLOCK_NAME'] = $name; // Re-position template blocks for ($i = sizeof($block); $i > $key; $i--) From c40642b8274c9afa39af6b34cd831bed8b960b83 Mon Sep 17 00:00:00 2001 From: javiexin Date: Sat, 7 Jan 2017 19:57:22 +0100 Subject: [PATCH 2/4] [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. Added tests. PHPBB3-14943 --- tests/template/template_test.php | 123 ++++++++++++++++++++++++++++++- 1 file changed, 120 insertions(+), 3 deletions(-) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 0bbfe3848d..92de5d3fac 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -528,11 +528,11 @@ EOT ), array( 'outer', - array('VARIABLE' => 'pos #1'), + array('VARIABLE' => 'changed'), 0, 'change', << 'changed'), + array('S_ROW_NUM' => 2), + 'change', + << 'before'), + false, + 'insert', + << 'after'), + true, + 'insert', + << 'pos #1'), + 1, + 'insert', + << 'changed'), + 0, + 'change', + << 'changed'), + array('S_ROW_NUM' => 1), + 'change', + << Date: Sat, 7 Jan 2017 20:12:32 +0100 Subject: [PATCH 3/4] [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. Added more tests. PHPBB3-14943 --- tests/template/template_test.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/template/template_test.php b/tests/template/template_test.php index 92de5d3fac..7231f71511 100644 --- a/tests/template/template_test.php +++ b/tests/template/template_test.php @@ -718,6 +718,16 @@ EOT $expect = 'outer - 0[outer|4]outer - 1[outer|4]middle - 0[middle|1]outer - 2 - test[outer|4]middle - 0[middle|2]middle - 1[middle|2]outer - 3[outer|4]middle - 0[middle|3]middle - 1[middle|3]middle - 2[middle|3]'; $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after modification'); + + $this->template->alter_block_array('outer.middle', array()); + + $expect = 'outer - 0[outer|4]outer - 1[outer|4]middle - 0[middle|1]outer - 2 - test[outer|4]middle - 0[middle|2]middle - 1[middle|2]outer - 3[outer|4]middle - 0[middle|4]middle - 1[middle|4]middle - 2[middle|4]middle - 3[middle|4]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after insertion at middle level'); + + $this->template->alter_block_array('outer.middle', array('VARIABLE' => 'test'), 2, 'change'); + + $expect = 'outer - 0[outer|4]outer - 1[outer|4]middle - 0[middle|1]outer - 2 - test[outer|4]middle - 0[middle|2]middle - 1[middle|2]outer - 3[outer|4]middle - 0[middle|4]middle - 1[middle|4]middle - 2 - test[middle|4]middle - 3[middle|4]'; + $this->assertEquals($expect, str_replace(array("\n", "\r", "\t"), '', $this->display('test')), 'Ensuring S_NUM_ROWS is correct after modification at middle level'); } public function assign_block_vars_array_data() From d2ad751851c955c19d1688cbe511925489212121 Mon Sep 17 00:00:00 2001 From: javiexin Date: Thu, 12 Jan 2017 21:25:39 +0100 Subject: [PATCH 4/4] [ticket/14943] Fix template loop access by index Allows inserting elements in a loop specified as 'outer[3].inner'. This was coded, but malfunctioning. Name incorrectly set on insert. If block was empty, the insertion process should create it. Checking for out of bounds indexes. PHPBB3-14943 --- phpBB/phpbb/template/context.php | 69 ++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/phpBB/phpbb/template/context.php b/phpBB/phpbb/template/context.php index f0bc4c859a..4235a8543e 100644 --- a/phpBB/phpbb/template/context.php +++ b/phpBB/phpbb/template/context.php @@ -293,47 +293,49 @@ class context public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') { $this->num_rows_is_set = false; - if (strpos($blockname, '.') !== false) + + // For nested block, $blockcount > 0, for top-level block, $blockcount == 0 + $blocks = explode('.', $blockname); + $blockcount = sizeof($blocks) - 1; + + $block = &$this->tpldata; + for ($i = 0; $i < $blockcount; $i++) { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - $block = &$this->tpldata; - for ($i = 0; $i < $blockcount; $i++) + if (($pos = strpos($blocks[$i], '[')) !== false) { - if (($pos = strpos($blocks[$i], '[')) !== false) - { - $name = substr($blocks[$i], 0, $pos); + $name = substr($blocks[$i], 0, $pos); - if (strpos($blocks[$i], '[]') === $pos) - { - $index = sizeof($block[$name]) - 1; - } - else - { - $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); - } + if (strpos($blocks[$i], '[]') === $pos) + { + $index = sizeof($block[$name]) - 1; } else { - $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; + $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); } - $block = &$block[$name]; - $block = &$block[$index]; } + else + { + $name = $blocks[$i]; + $index = sizeof($block[$name]) - 1; + } + $block = &$block[$name]; + $block = &$block[$index]; + } + $name = $blocks[$i]; - $block = &$block[$blocks[$i]]; // Traverse the last block - $name = $blocks[$i]; - } - else + // If last block does not exist and we are inserting, and not searching for key, we create it empty; otherwise, nothing to do + if (!isset($block[$name])) { - // Top-level block. - $block = &$this->tpldata[$blockname]; - $name = $blockname; + if ($mode != 'insert' || is_array($key)) + { + return false; + } + $block[$name] = array(); } + $block = &$block[$name]; // Now we can traverse the last block + // Change key to zero (change first position) if false and to last position if true if ($key === false || $key === true) { @@ -373,8 +375,9 @@ class context unset($block[($key - 1)]['S_LAST_ROW']); $vararray['S_LAST_ROW'] = true; } - else if ($key === 0) + if ($key <= 0) { + $key = 0; unset($block[0]['S_FIRST_ROW']); $vararray['S_FIRST_ROW'] = true; } @@ -400,6 +403,12 @@ class context // Which block to change? if ($mode == 'change') { + // If key is out of bounds, do not change anything + if ($key > sizeof($block) || $key < 0) + { + return false; + } + if ($key == sizeof($block)) { $key--;