Merge remote-tracking branch 'p/ticket/11095-develop' into develop

* p/ticket/11095-develop:
  [ticket/11095] Restore brace on previous line.
  [ticket/11095] Docs and tests for phpbb_build_hidden_fields_for_query_params.
  [ticket/11095] Forward GET parameters into hidden fields for jumpbox.
  [ticket/11095] Python quoteattr port.
  [ticket/11095] Use get method in jumpboxes.
This commit is contained in:
Andreas Fischer 2012-12-08 16:14:42 +01:00
commit bd987b6e14
6 changed files with 220 additions and 5 deletions

View file

@ -4893,13 +4893,108 @@ function phpbb_http_login($param)
trigger_error('NOT_AUTHORISED'); trigger_error('NOT_AUTHORISED');
} }
/**
* Escapes and quotes a string for use as an HTML/XML attribute value.
*
* This is a port of Python xml.sax.saxutils quoteattr.
*
* The function will attempt to choose a quote character in such a way as to
* avoid escaping quotes in the string. If this is not possible the string will
* be wrapped in double quotes and double quotes will be escaped.
*
* @param string $data The string to be escaped
* @param array $entities Associative array of additional entities to be escaped
* @return string Escaped and quoted string
*/
function phpbb_quoteattr($data, $entities = null)
{
$data = str_replace('&', '&', $data);
$data = str_replace('>', '>', $data);
$data = str_replace('<', '&lt;', $data);
$data = str_replace("\n", '&#10;', $data);
$data = str_replace("\r", '&#13;', $data);
$data = str_replace("\t", '&#9;', $data);
if (!empty($entities))
{
$data = str_replace(array_keys($entities), array_values($entities), $data);
}
if (strpos($data, '"') !== false)
{
if (strpos($data, "'") !== false)
{
$data = '"' . str_replace('"', '&quot;', $data) . '"';
}
else
{
$data = "'" . $data . "'";
}
}
else
{
$data = '"' . $data . '"';
}
return $data;
}
/**
* Converts query string (GET) parameters in request into hidden fields.
*
* Useful for forwarding GET parameters when submitting forms with GET method.
*
* It is possible to omit some of the GET parameters, which is useful if
* they are specified in the form being submitted.
*
* sid is always omitted.
*
* @param phpbb_request $request Request object
* @param array $exclude A list of variable names that should not be forwarded
* @return string HTML with hidden fields
*/
function phpbb_build_hidden_fields_for_query_params($request, $exclude = null)
{
$names = $request->variable_names(phpbb_request_interface::GET);
$hidden = '';
foreach ($names as $name)
{
// Sessions are dealt with elsewhere, omit sid always
if ($name == 'sid')
{
continue;
}
// Omit any additional parameters requested
if (!empty($exclude) && in_array($name, $exclude))
{
continue;
}
$escaped_name = phpbb_quoteattr($name);
// Note: we might retrieve the variable from POST or cookies
// here. To avoid exposing cookies, skip variables that are
// overwritten somewhere other than GET entirely.
$value = $request->variable($name, '', true);
$get_value = $request->variable($name, '', true, phpbb_request_interface::GET);
if ($value === $get_value)
{
$escaped_value = phpbb_quoteattr($value);
$hidden .= "<input type='hidden' name=$escaped_name value=$escaped_value />";
}
}
return $hidden;
}
/** /**
* Generate page header * Generate page header
*/ */
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum') function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{ {
global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path; global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
global $phpbb_dispatcher; global $phpbb_dispatcher, $request;
if (defined('HEADER_INC')) if (defined('HEADER_INC'))
{ {
@ -5088,6 +5183,8 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
$timezone_name = $user->lang['timezones'][$timezone_name]; $timezone_name = $user->lang['timezones'][$timezone_name];
} }
$hidden_fields_for_jumpbox = phpbb_build_hidden_fields_for_query_params($request, array('f'));
// The following assigns all _common_ variables that may be used at any point in a template. // The following assigns all _common_ variables that may be used at any point in a template.
$template->assign_vars(array( $template->assign_vars(array(
'SITENAME' => $config['sitename'], 'SITENAME' => $config['sitename'],
@ -5102,6 +5199,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'RECORD_USERS' => $l_online_record, 'RECORD_USERS' => $l_online_record,
'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text, 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text,
'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread, 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread,
'HIDDEN_FIELDS_FOR_JUMPBOX' => $hidden_fields_for_jumpbox,
'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'], 'S_USER_NEW_PRIVMSG' => $user->data['user_new_privmsg'],
'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'], 'S_USER_UNREAD_PRIVMSG' => $user->data['user_unread_privmsg'],

View file

@ -10,13 +10,14 @@
<!-- ENDIF --> <!-- ENDIF -->
<!-- IF S_DISPLAY_JUMPBOX --> <!-- IF S_DISPLAY_JUMPBOX -->
<form method="post" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(this.f.value == -1){return false;}"> <form method="get" id="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(this.f.value == -1){return false;}">
<!-- IF $CUSTOM_FIELDSET_CLASS --> <!-- IF $CUSTOM_FIELDSET_CLASS -->
<fieldset class="{$CUSTOM_FIELDSET_CLASS}"> <fieldset class="{$CUSTOM_FIELDSET_CLASS}">
<!-- ELSE --> <!-- ELSE -->
<fieldset class="jumpbox"> <fieldset class="jumpbox">
<!-- ENDIF --> <!-- ENDIF -->
{HIDDEN_FIELDS_FOR_JUMPBOX}
<label for="f" accesskey="j"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</label> <label for="f" accesskey="j"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</label>
<select name="f" id="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }"> <select name="f" id="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }">
<!-- BEGIN jumpbox_forums --> <!-- BEGIN jumpbox_forums -->

View file

@ -1,10 +1,10 @@
<!-- IF S_DISPLAY_JUMPBOX --> <!-- IF S_DISPLAY_JUMPBOX -->
<form method="post" name="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}"> <form method="get" name="jumpbox" action="{S_JUMPBOX_ACTION}" onsubmit="if(document.jumpbox.f.value == -1){return false;}">
<table cellspacing="0" cellpadding="0" border="0"> <table cellspacing="0" cellpadding="0" border="0">
<tr> <tr>
<td nowrap="nowrap"><span class="gensmall"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</span>&nbsp;<select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }"> <td nowrap="nowrap">{HIDDEN_FIELDS_FOR_JUMPBOX}<span class="gensmall"><!-- IF S_IN_MCP and S_MERGE_SELECT -->{L_SELECT_TOPICS_FROM}<!-- ELSEIF S_IN_MCP -->{L_MODERATE_FORUM}<!-- ELSE -->{L_JUMP_TO}<!-- ENDIF -->{L_COLON}</span>&nbsp;<select name="f" onchange="if(this.options[this.selectedIndex].value != -1){ document.forms['jumpbox'].submit() }">
<!-- BEGIN jumpbox_forums --> <!-- BEGIN jumpbox_forums -->
<!-- IF jumpbox_forums.S_FORUM_COUNT eq 1 --><option value="-1">------------------</option><!-- ENDIF --> <!-- IF jumpbox_forums.S_FORUM_COUNT eq 1 --><option value="-1">------------------</option><!-- ENDIF -->

View file

@ -1,7 +1,8 @@
<!-- Note: no longer in use... --> <!-- Note: no longer in use... -->
<form name="jumpbox" method="post" action="{S_JUMPBOX_ACTION}"> <form name="jumpbox" method="get" action="{S_JUMPBOX_ACTION}">
{HIDDEN_FIELDS_FOR_JUMPBOX}
<span class="gensmall">{L_JUMP_TO}{L_COLON}</span>&nbsp;<select name="f" onChange="if(this.options[this.selectedIndex].value != -1 && this.options[this.selectedIndex].value != document.jumpbox.current_f.value){ document.forms['jumpbox'].submit() }"> <span class="gensmall">{L_JUMP_TO}{L_COLON}</span>&nbsp;<select name="f" onChange="if(this.options[this.selectedIndex].value != -1 && this.options[this.selectedIndex].value != document.jumpbox.current_f.value){ document.forms['jumpbox'].submit() }">
<!-- IF S_ENABLE_SELECT_ALL --> <!-- IF S_ENABLE_SELECT_ALL -->

View file

@ -0,0 +1,71 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_build_hidden_fields_for_query_params_test extends phpbb_test_case
{
public function build_hidden_fields_for_query_params_test_data()
{
return array(
// get
// post
// exclude
// expected
array(
array('foo' => 'bar'),
array(),
array(),
"<input type='hidden' name=\"foo\" value=\"bar\" />",
),
array(
array('foo' => 'bar', 'a' => 'b'),
array(),
array(),
"<input type='hidden' name=\"foo\" value=\"bar\" /><input type='hidden' name=\"a\" value=\"b\" />",
),
array(
array('a' => 'quote"', 'b' => '<less>'),
array(),
array(),
"<input type='hidden' name=\"a\" value='quote\"' /><input type='hidden' name=\"b\" value=\"&lt;less&gt;\" />",
),
array(
array('a' => "quotes'\""),
array(),
array(),
"<input type='hidden' name=\"a\" value=\"quotes'&quot;\" />",
),
array(
array('foo' => 'bar', 'a' => 'b'),
array('a' => 'c'),
array(),
"<input type='hidden' name=\"foo\" value=\"bar\" />",
),
// strict equality check
array(
array('foo' => 'bar', 'a' => '0'),
array('a' => ''),
array(),
"<input type='hidden' name=\"foo\" value=\"bar\" />",
),
);
}
/**
* @dataProvider build_hidden_fields_for_query_params_test_data
*/
public function test_build_hidden_fields_for_query_params($get, $post, $exclude, $expected)
{
$request = new phpbb_mock_request($get, $post);
$result = phpbb_build_hidden_fields_for_query_params($request, $exclude);
$this->assertEquals($expected, $result);
}
}

View file

@ -0,0 +1,44 @@
<?php
/**
*
* @package testing
* @copyright (c) 2012 phpBB Group
* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
*
*/
require_once dirname(__FILE__) . '/../../phpBB/includes/functions.php';
class phpbb_quoteattr_test extends phpbb_test_case
{
public function quoteattr_test_data()
{
return array(
array('foo', null, '"foo"'),
array('', null, '""'),
array(' ', null, '" "'),
array('<a>', null, '"&lt;a&gt;"'),
array('&amp;', null, '"&amp;amp;"'),
array('"hello"', null, "'\"hello\"'"),
array("'hello'", null, "\"'hello'\""),
array("\"'", null, "\"&quot;'\""),
array("a\nb", null, '"a&#10;b"'),
array("a\r\nb", null, '"a&#13;&#10;b"'),
array("a\tb", null, '"a&#9;b"'),
array('a b', null, '"a b"'),
array('"a<b"', null, "'\"a&lt;b\"'"),
array('foo', array('f' => 'z'), '"zoo"'),
array('<a>', array('a' => '&amp;'), '"&lt;&amp;&gt;"'),
);
}
/**
* @dataProvider quoteattr_test_data
*/
public function test_quoteattr($input, $entities, $expected)
{
$output = phpbb_quoteattr($input, $entities);
$this->assertEquals($expected, $output);
}
}