diff options
Diffstat (limited to 'phpBB/includes')
40 files changed, 1553 insertions, 250 deletions
diff --git a/phpBB/includes/acp/acp_attachments.php b/phpBB/includes/acp/acp_attachments.php index fc5f44e14f..68870dce54 100644 --- a/phpBB/includes/acp/acp_attachments.php +++ b/phpBB/includes/acp/acp_attachments.php @@ -1235,6 +1235,7 @@ class acp_attachments function perform_site_list() { global $db, $user; + global $request; if (isset($_REQUEST['securesubmit'])) { @@ -1243,7 +1244,7 @@ class acp_attachments $ip_list = array_unique(explode("\n", $ips)); $ip_list_log = implode(', ', $ip_list); - $ip_exclude = (!empty($_POST['ipexclude'])) ? 1 : 0; + $ip_exclude = (int) $request->variable('ipexclude', false, false, phpbb_request_interface::POST); $iplist = array(); $hostlist = array(); diff --git a/phpBB/includes/acp/acp_board.php b/phpBB/includes/acp/acp_board.php index a5e80e1f6d..ab9492b7ba 100644 --- a/phpBB/includes/acp/acp_board.php +++ b/phpBB/includes/acp/acp_board.php @@ -435,7 +435,7 @@ class acp_board $cfg_array = (isset($_REQUEST['config'])) ? utf8_normalize_nfc(request_var('config', array('' => ''), true)) : $this->new_config; $error = array(); - // We validate the complete config if whished + // We validate the complete config if wished validate_config_vars($display_vars['vars'], $cfg_array, $error); if ($submit && !check_form_key($form_key)) diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php index 3d64a2acda..43412f3c47 100644 --- a/phpBB/includes/acp/acp_icons.php +++ b/phpBB/includes/acp/acp_icons.php @@ -28,6 +28,7 @@ class acp_icons { global $db, $user, $auth, $template, $cache; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $request; $user->add_lang('acp/posting'); @@ -338,7 +339,7 @@ class acp_icons $image_display_on_posting = (isset($_POST['display_on_posting'])) ? request_var('display_on_posting', array('' => 0)) : array(); // Ok, add the relevant bits if we are adding new codes to existing emoticons... - if (!empty($_POST['add_additional_code'])) + if ($request->variable('add_additional_code', false, false, phpbb_request_interface::POST)) { $add_image = request_var('add_image', ''); $add_code = utf8_normalize_nfc(request_var('add_code', '', true)); @@ -354,7 +355,7 @@ class acp_icons $image_width[$add_image] = request_var('add_width', 0); $image_height[$add_image] = request_var('add_height', 0); - if (!empty($_POST['add_display_on_posting'])) + if ($request->variable('add_display_on_posting', false, false, phpbb_request_interface::POST)) { $image_display_on_posting[$add_image] = 1; } diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index c2cb2f9c11..0f924dc95f 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -34,6 +34,7 @@ class acp_language global $config, $db, $user, $auth, $template, $cache; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; global $safe_mode, $file_uploads; + global $request; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -58,7 +59,7 @@ class acp_language if (isset($_POST['missing_file'])) { $missing_file = request_var('missing_file', array('' => 0)); - list($_REQUEST['language_file'], ) = array_keys($missing_file); + $request->overwrite('language_file', array_shift(array_keys($missing_file))); } $selected_lang_file = request_var('language_file', '|common.' . $phpEx); @@ -68,6 +69,23 @@ class acp_language $this->language_directory = basename($this->language_directory); $this->language_file = basename($this->language_file); + // detect language file type + if ($this->language_directory == 'email') + { + $language_file_type = 'email'; + $request_default = ''; + } + else if (strpos($this->language_file, 'help_') === 0) + { + $language_file_type = 'help'; + $request_default = array(0 => array(0 => '')); + } + else + { + $language_file_type = 'normal'; + $request_default = array('' => ''); + } + $user->add_lang('acp/language'); $this->tpl_name = 'acp_language'; $this->page_title = 'ACP_LANGUAGE_PACKS'; @@ -119,7 +137,7 @@ class acp_language 'DATA' => $data, 'NAME' => $user->lang[strtoupper($method . '_' . $data)], 'EXPLAIN' => $user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], - 'DEFAULT' => (!empty($_REQUEST[$data])) ? request_var($data, '') : $default + 'DEFAULT' => $request->variable($data, (string) $default), )); } @@ -130,7 +148,7 @@ class acp_language 'method' => $method) ); - $hidden_data .= build_hidden_fields(array('entry' => $_POST['entry']), true, STRIP); + $hidden_data .= build_hidden_fields(array('entry' => $request->variable('entry', $request_default, true, phpbb_request_interface::POST))); $template->assign_vars(array( 'S_UPLOAD' => true, @@ -187,12 +205,9 @@ class acp_language trigger_error($user->lang['FORM_INVALID']. adm_back_link($this->u_action), E_USER_WARNING); } - if (!$lang_id || empty($_POST['entry'])) - { - trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); - } + $entry_value = $request->variable('entry', $request_default, true, phpbb_request_interface::POST); - if ($this->language_directory != 'email' && !is_array($_POST['entry'])) + if (!$lang_id || !$entry_value) { trigger_error($user->lang['NO_LANG_ID'] . adm_back_link($this->u_action), E_USER_WARNING); } @@ -291,10 +306,10 @@ class acp_language trigger_error(sprintf($user->lang['UNABLE_TO_WRITE_FILE'], $filename) . adm_back_link($this->u_action . '&id=' . $lang_id . '&action=details&language_file=' . urlencode($selected_lang_file)), E_USER_WARNING); } - if ($this->language_directory == 'email') + if ($language_file_type == 'email') { // Email Template - $entry = $this->prepare_lang_entry($_POST['entry'], false); + $entry = $this->prepare_lang_entry(htmlspecialchars_decode($entry_value), false); fwrite($fp, $entry); } else @@ -302,13 +317,13 @@ class acp_language $name = (($this->language_directory) ? $this->language_directory . '_' : '') . $this->language_file; $header = str_replace(array('{FILENAME}', '{LANG_NAME}', '{CHANGED}', '{AUTHOR}'), array($name, $row['lang_english_name'], date('Y-m-d', time()), $row['lang_author']), $this->language_file_header); - if (strpos($this->language_file, 'help_') === 0) + if ($language_file_type == 'help') { // Help File $header .= '$help = array(' . "\n"; fwrite($fp, $header); - foreach ($_POST['entry'] as $key => $value) + foreach ($entry_value as $key => $value) { if (!is_array($value)) { @@ -319,7 +334,7 @@ class acp_language foreach ($value as $_key => $_value) { - $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry($_value) . "',\n"; + $entry .= "\t\t" . (int) $_key . "\t=> '" . $this->prepare_lang_entry(htmlspecialchars_decode($_value)) . "',\n"; } $entry .= "\t),\n"; @@ -329,15 +344,15 @@ class acp_language $footer = ");\n\n?>"; fwrite($fp, $footer); } - else + else if ($language_file_type == 'normal') { // Language File $header .= $this->lang_header; fwrite($fp, $header); - foreach ($_POST['entry'] as $key => $value) + foreach ($entry_value as $key => $value) { - $entry = $this->format_lang_array($key, $value); + $entry = $this->format_lang_array(htmlspecialchars_decode($key), htmlspecialchars_decode($value)); fwrite($fp, $entry); } diff --git a/phpBB/includes/acp/acp_logs.php b/phpBB/includes/acp/acp_logs.php index 0f4f78fcdd..e37b696873 100644 --- a/phpBB/includes/acp/acp_logs.php +++ b/phpBB/includes/acp/acp_logs.php @@ -27,6 +27,7 @@ class acp_logs { global $db, $user, $auth, $template, $cache; global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx; + global $request; $user->add_lang('mcp'); @@ -35,8 +36,8 @@ class acp_logs $forum_id = request_var('f', 0); $topic_id = request_var('t', 0); $start = request_var('start', 0); - $deletemark = (!empty($_POST['delmarked'])) ? true : false; - $deleteall = (!empty($_POST['delall'])) ? true : false; + $deletemark = $request->variable('delmarked', false, false, phpbb_request_interface::POST); + $deleteall = $request->variable('delall', false, false, phpbb_request_interface::POST); $marked = request_var('mark', array(0)); // Sort keys diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php index e9f0af5071..50d7357100 100644 --- a/phpBB/includes/acp/acp_permissions.php +++ b/phpBB/includes/acp/acp_permissions.php @@ -658,6 +658,7 @@ class acp_permissions function set_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) { global $user, $auth; + global $request; $psubmit = request_var('psubmit', array(0 => array(0 => 0))); @@ -676,18 +677,17 @@ class acp_permissions list($ug_id, ) = each($psubmit); list($forum_id, ) = each($psubmit[$ug_id]); - if (empty($_POST['setting']) || empty($_POST['setting'][$ug_id]) || empty($_POST['setting'][$ug_id][$forum_id]) || !is_array($_POST['setting'][$ug_id][$forum_id])) + $settings = $request->variable('setting', array(0 => array(0 => array('' => 0))), false, phpbb_request_interface::POST); + if (empty($settings) || empty($settings[$ug_id]) || empty($settings[$ug_id][$forum_id])) { trigger_error('WRONG_PERMISSION_SETTING_FORMAT', E_USER_WARNING); } - // We obtain and check $_POST['setting'][$ug_id][$forum_id] directly and not using request_var() because request_var() - // currently does not support the amount of dimensions required. ;) - // $auth_settings = request_var('setting', array(0 => array(0 => array('' => 0)))); - $auth_settings = array_map('intval', $_POST['setting'][$ug_id][$forum_id]); + $auth_settings = $settings[$ug_id][$forum_id]; // Do we have a role we want to set? - $assigned_role = (isset($_POST['role'][$ug_id][$forum_id])) ? (int) $_POST['role'][$ug_id][$forum_id] : 0; + $roles = $request->variable('role', array(0 => array(0 => 0)), false, phpbb_request_interface::POST); + $assigned_role = (isset($roles[$ug_id][$forum_id])) ? (int) $roles[$ug_id][$forum_id] : 0; // Do the admin want to set these permissions to other items too? $inherit = request_var('inherit', array(0 => array(0))); @@ -747,6 +747,7 @@ class acp_permissions function set_all_permissions($mode, $permission_type, &$auth_admin, &$user_id, &$group_id) { global $user, $auth; + global $request; // User or group to be set? $ug_type = (sizeof($user_id)) ? 'user' : 'group'; @@ -757,8 +758,8 @@ class acp_permissions trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING); } - $auth_settings = (isset($_POST['setting'])) ? $_POST['setting'] : array(); - $auth_roles = (isset($_POST['role'])) ? $_POST['role'] : array(); + $auth_settings = $request->variable('setting', array(0 => array(0 => array('' => 0))), false, phpbb_request_interface::POST); + $auth_roles = $request->variable('role', array(0 => array(0 => 0)), false, phpbb_request_interface::POST); $ug_ids = $forum_ids = array(); // We need to go through the auth settings diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php index 2288a0728b..b66737ce03 100644 --- a/phpBB/includes/acp/acp_profile.php +++ b/phpBB/includes/acp/acp_profile.php @@ -30,6 +30,7 @@ class acp_profile { global $config, $db, $user, $auth, $template, $cache; global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix; + global $request; include($phpbb_root_path . 'includes/functions_posting.' . $phpEx); include($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -487,7 +488,8 @@ class acp_profile $cp->vars['field_default_value_day'] = $now['mday']; $cp->vars['field_default_value_month'] = $now['mon']; $cp->vars['field_default_value_year'] = $now['year']; - $var = $_POST['field_default_value'] = 'now'; + $var = 'now'; + $request->overwrite('field_default_value', $var, phpbb_request_interface::POST); } else { @@ -496,7 +498,8 @@ class acp_profile $cp->vars['field_default_value_day'] = request_var('field_default_value_day', 0); $cp->vars['field_default_value_month'] = request_var('field_default_value_month', 0); $cp->vars['field_default_value_year'] = request_var('field_default_value_year', 0); - $var = $_POST['field_default_value'] = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + $var = sprintf('%2d-%2d-%4d', $cp->vars['field_default_value_day'], $cp->vars['field_default_value_month'], $cp->vars['field_default_value_year']); + $request->overwrite('field_default_value', $var, phpbb_request_interface::POST); } else { @@ -688,7 +691,7 @@ class acp_profile } else { - $_new_key_ary[$key] = (is_array($_REQUEST[$key])) ? utf8_normalize_nfc(request_var($key, array(''), true)) : utf8_normalize_nfc(request_var($key, '', true)); + $_new_key_ary[$key] = ($field_type == FIELD_BOOL && $key == 'lang_options') ? utf8_normalize_nfc(request_var($key, array(''), true)) : utf8_normalize_nfc(request_var($key, '', true)); } } } @@ -1623,4 +1626,4 @@ class acp_profile } } -?> +?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_db.php b/phpBB/includes/auth/auth_db.php index e04a6307e9..f1bc47c393 100644 --- a/phpBB/includes/auth/auth_db.php +++ b/phpBB/includes/auth/auth_db.php @@ -69,7 +69,7 @@ function login_db(&$username, &$password) if ($show_captcha) { // Visual Confirmation handling - if (!class_exists('phpbb_captcha_factory')) + if (!class_exists('phpbb_captcha_factory', false)) { global $phpbb_root_path, $phpEx; include ($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); @@ -90,7 +90,7 @@ function login_db(&$username, &$password) { $captcha->reset(); } - + } // If the password convert flag is set we need to convert it diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php index 6e899adc16..a326074c14 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php @@ -19,7 +19,7 @@ if (!defined('IN_PHPBB')) /** * Placeholder for autoload */ -if (!class_exists('phpbb_default_captcha')) +if (!class_exists('phpbb_default_captcha', false)) { include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php index 2f55d15efd..8ac0262302 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php @@ -19,7 +19,7 @@ if (!defined('IN_PHPBB')) /** * Placeholder for autoload */ -if (!class_exists('phpbb_default_captcha')) +if (!class_exists('phpbb_default_captcha', false)) { include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php index ac30ed4297..834d2a7f12 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php @@ -19,7 +19,7 @@ if (!defined('IN_PHPBB')) /** * Placeholder for autoload */ -if (!class_exists('phpbb_default_captcha')) +if (!class_exists('phpbb_default_captcha', false)) { include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); } diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php index 49a64b9339..c0cdc83fa1 100644 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_captcha_qa_plugin.php @@ -87,7 +87,7 @@ class phpbb_captcha_qa } $db->sql_freeresult($result); } - + // okay, if there is a confirm_id, we try to load that confirm's state. If not, we try to find one if (!$this->load_answer() && (!$this->load_confirm_id() || !$this->load_answer())) { @@ -113,7 +113,7 @@ class phpbb_captcha_qa { global $db, $phpbb_root_path, $phpEx; - if (!class_exists('phpbb_db_tools')) + if (!class_exists('phpbb_db_tools', false)) { include("$phpbb_root_path/includes/db/db_tools.$phpEx"); } @@ -365,12 +365,12 @@ class phpbb_captcha_qa global $config, $db, $user; $error = ''; - + if (!sizeof($this->question_ids)) { return false; } - + if (!$this->confirm_id) { $error = $user->lang['CONFIRM_QUESTION_WRONG']; @@ -434,7 +434,7 @@ class phpbb_captcha_qa function reselect_question() { global $db, $user; - + if (!sizeof($this->question_ids)) { return false; @@ -482,8 +482,8 @@ class phpbb_captcha_qa global $db, $user; $sql = 'SELECT confirm_id - FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " - WHERE + FROM ' . CAPTCHA_QA_CONFIRM_TABLE . " + WHERE session_id = '" . $db->sql_escape($user->session_id) . "' AND lang_iso = '" . $db->sql_escape($this->question_lang) . "' AND confirm_type = " . $this->type; @@ -505,7 +505,7 @@ class phpbb_captcha_qa function load_answer() { global $db, $user; - + if (!strlen($this->confirm_id) || !sizeof($this->question_ids)) { return false; @@ -990,9 +990,9 @@ class phpbb_captcha_qa return $langs; } - - - + + + /** * See if there is a question other than the one we have */ diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php index ea171dbe2c..35a33cdfb7 100644 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php @@ -16,7 +16,7 @@ if (!defined('IN_PHPBB')) exit; } -if (!class_exists('phpbb_default_captcha')) +if (!class_exists('phpbb_default_captcha', false)) { // we need the classic captcha code for tracking solutions and attempts include($phpbb_root_path . 'includes/captcha/plugins/captcha_abstract.' . $phpEx); diff --git a/phpBB/includes/class_loader.php b/phpBB/includes/class_loader.php new file mode 100644 index 0000000000..5df654799a --- /dev/null +++ b/phpBB/includes/class_loader.php @@ -0,0 +1,162 @@ +<?php +/** +* +* @package phpBB3 +* @version $Id$ +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* The class loader resolves class names to file system paths and loads them if +* necessary. +* +* Classes have to be of the form phpbb_(dir_)*(classpart_)*, so directory names +* must never contain underscores. Example: phpbb_dir_subdir_class_name is a +* valid class name, while phpbb_dir_sub_dir_class_name is not. +* +* If every part of the class name is a directory, the last directory name is +* also used as the filename, e.g. phpbb_dir would resolve to dir/dir.php. +* +* @package phpBB3 +*/ +class phpbb_class_loader +{ + private $phpbb_root_path; + private $php_ext; + private $cache; + private $cached_paths = array(); + + /** + * Creates a new phpbb_class_loader, which loads files with the given + * file extension from the given phpbb root path. + * + * @param string $phpbb_root_path phpBB's root directory containing includes/ + * @param string $php_ext The file extension for PHP files + */ + public function __construct($phpbb_root_path, $php_ext = '.php', $cache = null) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + $this->set_cache($cache); + } + + /** + * Provide the class loader with a cache to store paths. If set to null, the + * the class loader will resolve paths by checking for the existance of every + * directory in the class name every time. + * + * @param acm $cache An implementation of the phpBB cache interface. + */ + public function set_cache($cache = null) + { + if ($cache) + { + $this->cached_paths = $cache->get('class_loader'); + + if ($this->cached_paths === false) + { + $this->cached_paths = array(); + } + } + + $this->cache = $cache; + } + + /** + * Registers the class loader as an autoloader using SPL. + */ + public function register() + { + spl_autoload_register(array($this, 'load_class')); + } + + /** + * Removes the class loader from the SPL autoloader stack. + */ + public function unregister() + { + spl_autoload_unregister(array($this, 'load_class')); + } + + /** + * Resolves a phpBB class name to a relative path which can be included. + * + * @param string $class The class name to resolve, must have a phpbb_ + * prefix + * @return string|bool A relative path to the file containing the + * class or false if looking it up failed. + */ + public function resolve_path($class) + { + $path_prefix = $this->phpbb_root_path . 'includes/'; + + if (isset($this->cached_paths[$class])) + { + return $path_prefix . $this->cached_paths[$class] . $this->php_ext; + } + + if (!preg_match('/phpbb_[a-zA-Z0-9_]+/', $class)) + { + return false; + } + + $parts = explode('_', substr($class, 6)); + + $dirs = ''; + + for ($i = 0, $n = sizeof($parts); $i < $n && is_dir($path_prefix . $dirs . $parts[$i]); $i++) + { + $dirs .= $parts[$i] . '/'; + } + + // no file name left => use last dir name as file name + if ($i == sizeof($parts)) + { + $parts[] = $parts[$i - 1]; + } + + $relative_path = $dirs . implode(array_slice($parts, $i, sizeof($parts) - $i), '_'); + + if (!file_exists($path_prefix . $relative_path . $this->php_ext)) + { + return false; + } + + if ($this->cache) + { + $this->cached_paths[$class] = $relative_path; + $this->cache->put('class_loader', $this->cached_paths); + } + + return $path_prefix . $relative_path . $this->php_ext; + } + + /** + * Resolves a class name to a path and then includes it. + * + * @param string $class The class name which is being loaded. + */ + public function load_class($class) + { + if (substr($class, 0, 6) === 'phpbb_') + { + $path = $this->resolve_path($class); + + if ($path) + { + require $path; + } + } + } +} diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php index eeddf1f41b..e0d329abfe 100644 --- a/phpBB/includes/db/dbal.php +++ b/phpBB/includes/db/dbal.php @@ -711,8 +711,9 @@ class dbal function sql_report($mode, $query = '') { global $cache, $starttime, $phpbb_root_path, $user; + global $request; - if (empty($_REQUEST['explain'])) + if (is_object($request) && !$request->variable('explain', false)) { return false; } diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 9aec98dce2..912d39e0f0 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -18,122 +18,62 @@ if (!defined('IN_PHPBB')) // Common global functions -/** -* set_var -* -* Set variable, used by {@link request_var the request_var function} -* -* @access private -*/ function set_var(&$result, $var, $type, $multibyte = false) { - settype($var, $type); - $result = $var; - - if ($type == 'string') - { - $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8')); - - if (!empty($result)) - { - // Make sure multibyte characters are wellformed - if ($multibyte) - { - if (!preg_match('/^./u', $result)) - { - $result = ''; - } - } - else - { - // no multibyte, allow only ASCII (0-127) - $result = preg_replace('/[\x80-\xFF]/', '?', $result); - } - } - - $result = (STRIP) ? stripslashes($result) : $result; - } + // no need for dependency injection here, if you have the object, call the method yourself! + $type_cast_helper = new phpbb_request_type_cast_helper(); + $type_cast_helper->set_var($result, $var, $type, $multibyte); } /** -* request_var +* Wrapper function of phpbb_request::variable which exists for backwards compatability. +* See {@link phpbb_request_interface::variable phpbb_request_interface::variable} for +* documentation of this function's use. +* +* @param mixed $var_name The form variable's name from which data shall be retrieved. +* If the value is an array this may be an array of indizes which will give +* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") +* then specifying array("var", 1) as the name will return "a". +* If you pass an instance of {@link phpbb_request_interface phpbb_request_interface} +* as this parameter it will overwrite the current request class instance. If you do +* not do so, it will create its own instance (but leave superglobals enabled). +* @param mixed $default A default value that is returned if the variable was not set. +* This function will always return a value of the same type as the default. +* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters +* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks +* @param bool $cookie This param is mapped to phpbb_request_interface::COOKIE as the last param for +* phpbb_request_interface::variable for backwards compatability reasons. * -* Used to get passed variable +* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the +* the same as that of $default. If the variable is not set $default is returned. */ -function request_var($var_name, $default, $multibyte = false, $cookie = false) +function request_var($var_name, $default, $multibyte = false, $cookie = false, phpbb_request_interface $request = null) { - if (!$cookie && isset($_COOKIE[$var_name])) - { - if (!isset($_GET[$var_name]) && !isset($_POST[$var_name])) - { - return (is_array($default)) ? array() : $default; - } - $_REQUEST[$var_name] = isset($_POST[$var_name]) ? $_POST[$var_name] : $_GET[$var_name]; - } + // This is all just an ugly hack to add "Dependency Injection" to a function + // the only real code is the function call which maps this function to a method. + static $static_request = null; - $super_global = ($cookie) ? '_COOKIE' : '_REQUEST'; - if (!isset($GLOBALS[$super_global][$var_name]) || is_array($GLOBALS[$super_global][$var_name]) != is_array($default)) + if ($request instanceof phpbb_request_interface) { - return (is_array($default)) ? array() : $default; - } + $static_request = $request; - $var = $GLOBALS[$super_global][$var_name]; - if (!is_array($default)) - { - $type = gettype($default); - } - else - { - list($key_type, $type) = each($default); - $type = gettype($type); - $key_type = gettype($key_type); - if ($type == 'array') + if (empty($var_name)) { - reset($default); - $default = current($default); - list($sub_key_type, $sub_type) = each($default); - $sub_type = gettype($sub_type); - $sub_type = ($sub_type == 'array') ? 'NULL' : $sub_type; - $sub_key_type = gettype($sub_key_type); + return; } } - if (is_array($var)) - { - $_var = $var; - $var = array(); + $tmp_request = $static_request; - foreach ($_var as $k => $v) - { - set_var($k, $k, $key_type); - if ($type == 'array' && is_array($v)) - { - foreach ($v as $_k => $_v) - { - if (is_array($_v)) - { - $_v = null; - } - set_var($_k, $_k, $sub_key_type, $multibyte); - set_var($var[$k][$_k], $_v, $sub_type, $multibyte); - } - } - else - { - if ($type == 'array' || is_array($v)) - { - $v = null; - } - set_var($var[$k], $v, $type, $multibyte); - } - } - } - else + // no request class set, create a temporary one ourselves to keep backwards compatability + if ($tmp_request === null) { - set_var($var, $var, $type, $multibyte); + // false param: enable super globals, so the created request class does not + // make super globals inaccessible everywhere outside this function. + $tmp_request = new phpbb_request(new phpbb_request_type_cast_helper(), false); } - return $var; + return $tmp_request->variable($var_name, $default, $multibyte, ($cookie) ? phpbb_request_interface::COOKIE : phpbb_request_interface::REQUEST); } /** @@ -2038,7 +1978,7 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add // Make sure $per_page is a valid value $per_page = ($per_page <= 0) ? 1 : $per_page; - $seperator = '<span class="page-sep">' . $user->lang['COMMA_SEPARATOR'] . '</span>'; + $separator = '<span class="page-sep">' . $user->lang['COMMA_SEPARATOR'] . '</span>'; $total_pages = ceil($num_items / $per_page); if ($total_pages == 1 || !$num_items) @@ -2056,29 +1996,29 @@ function generate_pagination($base_url, $num_items, $per_page, $start_item, $add $start_cnt = min(max(1, $on_page - 4), $total_pages - 5); $end_cnt = max(min($total_pages, $on_page + 4), 6); - $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator; + $page_string .= ($start_cnt > 1) ? ' ... ' : $separator; for ($i = $start_cnt + 1; $i < $end_cnt; $i++) { $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>'; if ($i < $end_cnt - 1) { - $page_string .= $seperator; + $page_string .= $separator; } } - $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator; + $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $separator; } else { - $page_string .= $seperator; + $page_string .= $separator; for ($i = 2; $i < $total_pages; $i++) { $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>'; if ($i < $total_pages) { - $page_string .= $seperator; + $page_string .= $separator; } } } @@ -2758,22 +2698,14 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '') { global $user, $template, $db; - global $phpEx, $phpbb_root_path; + global $phpEx, $phpbb_root_path, $request; if (isset($_POST['cancel'])) { return false; } - $confirm = false; - if (isset($_POST['confirm'])) - { - // language frontier - if ($_POST['confirm'] === $user->lang['YES']) - { - $confirm = true; - } - } + $confirm = ($user->lang['YES'] === $request->variable('confirm', '', true, phpbb_request_interface::POST)); if ($check && $confirm) { @@ -2861,8 +2793,9 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true) { global $db, $user, $template, $auth, $phpEx, $phpbb_root_path, $config; + global $request; - if (!class_exists('phpbb_captcha_factory')) + if (!class_exists('phpbb_captcha_factory', false)) { include($phpbb_root_path . 'includes/captcha/captcha_factory.' . $phpEx); } @@ -2911,8 +2844,8 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa } $username = request_var('username', '', true); - $autologin = (!empty($_POST['autologin'])) ? true : false; - $viewonline = (!empty($_POST['viewonline'])) ? 0 : 1; + $autologin = $request->is_set_post('autologin'); + $viewonline = (int) !$request->is_set_post('viewonline'); $admin = ($admin) ? 1 : 0; $viewonline = ($admin) ? $user->data['session_viewonline'] : $viewonline; @@ -4517,6 +4450,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0 function page_footer($run_cron = true) { global $db, $config, $template, $user, $auth, $cache, $starttime, $phpbb_root_path, $phpEx; + global $request; // Output page creation time if (defined('DEBUG')) @@ -4524,7 +4458,7 @@ function page_footer($run_cron = true) $mtime = explode(' ', microtime()); $totaltime = $mtime[0] + $mtime[1] - $starttime; - if (!empty($_REQUEST['explain']) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report')) + if ($request->variable('explain', false) && $auth->acl_get('a_') && defined('DEBUG_EXTRA') && method_exists($db, 'sql_report')) { $db->sql_report('display'); } diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php index 2de7e1b169..7f9070740f 100644 --- a/phpBB/includes/functions_display.php +++ b/phpBB/includes/functions_display.php @@ -1062,6 +1062,7 @@ function display_user_activity(&$userdata) function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0) { global $template, $db, $user, $phpEx, $start, $phpbb_root_path; + global $request; $table_sql = ($mode == 'forum') ? FORUMS_WATCH_TABLE : TOPICS_WATCH_TABLE; $where_sql = ($mode == 'forum') ? 'forum_id' : 'topic_id'; @@ -1098,7 +1099,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $message = $user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf($user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); trigger_error($message); } - if ($_GET['unwatch'] == $mode) + if ($request->variable('unwatch', '', false, phpbb_request_interface::GET) == $mode) { $is_watching = 0; @@ -1136,7 +1137,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $token = request_var('hash', ''); $redirect_url = append_sid("{$phpbb_root_path}view$mode.$phpEx", "$u_url=$match_id&start=$start"); - if ($_GET['watch'] == $mode && check_link_hash($token, "{$mode}_$match_id")) + if ($request->variable('watch', '', false, phpbb_request_interface::GET) == $mode && check_link_hash($token, "{$mode}_$match_id")) { $is_watching = true; @@ -1162,7 +1163,7 @@ function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, } else { - if (isset($_GET['unwatch']) && $_GET['unwatch'] == $mode) + if ($request->variable('unwatch', '', false, phpbb_request_interface::GET) == $mode) { login_box(); } diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php new file mode 100644 index 0000000000..87bf7a91a6 --- /dev/null +++ b/phpBB/includes/functions_download.php @@ -0,0 +1,409 @@ +<?php +/** +* +* @package phpBB3 +* @copyright (c) 2005 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* A simplified function to deliver avatars +* The argument needs to be checked before calling this function. +*/ +function send_avatar_to_browser($file, $browser) +{ + global $config, $phpbb_root_path; + + $prefix = $config['avatar_salt'] . '_'; + $image_dir = $config['avatar_path']; + + // Adjust image_dir path (no trailing slash) + if (substr($image_dir, -1, 1) == '/' || substr($image_dir, -1, 1) == '\\') + { + $image_dir = substr($image_dir, 0, -1) . '/'; + } + $image_dir = str_replace(array('../', '..\\', './', '.\\'), '', $image_dir); + + if ($image_dir && ($image_dir[0] == '/' || $image_dir[0] == '\\')) + { + $image_dir = ''; + } + $file_path = $phpbb_root_path . $image_dir . '/' . $prefix . $file; + + if ((@file_exists($file_path) && @is_readable($file_path)) && !headers_sent()) + { + header('Pragma: public'); + + $image_data = @getimagesize($file_path); + header('Content-Type: ' . image_type_to_mime_type($image_data[2])); + + if (strpos(strtolower($browser), 'msie') !== false && strpos(strtolower($browser), 'msie 8.0') === false) + { + header('Content-Disposition: attachment; ' . header_filename($file)); + + if (strpos(strtolower($browser), 'msie 6.0') !== false) + { + header('Expires: -1'); + } + else + { + header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + } + } + else + { + header('Content-Disposition: inline; ' . header_filename($file)); + header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + } + + $size = @filesize($file_path); + if ($size) + { + header("Content-Length: $size"); + } + + if (@readfile($file_path) == false) + { + $fp = @fopen($file_path, 'rb'); + + if ($fp !== false) + { + while (!feof($fp)) + { + echo fread($fp, 8192); + } + fclose($fp); + } + } + + flush(); + } + else + { + header('HTTP/1.0 404 Not Found'); + } +} + +/** +* Wraps an url into a simple html page. Used to display attachments in IE. +* this is a workaround for now; might be moved to template system later +* direct any complaints to 1 Microsoft Way, Redmond +*/ +function wrap_img_in_html($src, $title) +{ + echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-Strict.dtd">'; + echo '<html>'; + echo '<head>'; + echo '<meta http-equiv="content-type" content="text/html; charset=UTF-8" />'; + echo '<title>' . $title . '</title>'; + echo '</head>'; + echo '<body>'; + echo '<div>'; + echo '<img src="' . $src . '" alt="' . $title . '" />'; + echo '</div>'; + echo '</body>'; + echo '</html>'; +} + +/** +* Send file to browser +*/ +function send_file_to_browser($attachment, $upload_dir, $category) +{ + global $user, $db, $config, $phpbb_root_path; + + $filename = $phpbb_root_path . $upload_dir . '/' . $attachment['physical_filename']; + + if (!@file_exists($filename)) + { + trigger_error($user->lang['ERROR_NO_ATTACHMENT'] . '<br /><br />' . sprintf($user->lang['FILE_NOT_FOUND_404'], $filename)); + } + + // Correct the mime type - we force application/octetstream for all files, except images + // Please do not change this, it is a security precaution + if ($category != ATTACHMENT_CATEGORY_IMAGE || strpos($attachment['mimetype'], 'image') !== 0) + { + $attachment['mimetype'] = (strpos(strtolower($user->browser), 'msie') !== false || strpos(strtolower($user->browser), 'opera') !== false) ? 'application/octetstream' : 'application/octet-stream'; + } + + if (@ob_get_length()) + { + @ob_end_clean(); + } + + // Now send the File Contents to the Browser + $size = @filesize($filename); + + // To correctly display further errors we need to make sure we are using the correct headers for both (unsetting content-length may not work) + + // Check if headers already sent or not able to get the file contents. + if (headers_sent() || !@file_exists($filename) || !@is_readable($filename)) + { + // PHP track_errors setting On? + if (!empty($php_errormsg)) + { + trigger_error($user->lang['UNABLE_TO_DELIVER_FILE'] . '<br />' . sprintf($user->lang['TRACKED_PHP_ERROR'], $php_errormsg)); + } + + trigger_error('UNABLE_TO_DELIVER_FILE'); + } + + // Now the tricky part... let's dance + header('Pragma: public'); + + /** + * Commented out X-Sendfile support. To not expose the physical filename within the header if xsendfile is absent we need to look into methods of checking it's status. + * + * Try X-Sendfile since it is much more server friendly - only works if the path is *not* outside of the root path... + * lighttpd has core support for it. An apache2 module is available at http://celebnamer.celebworld.ws/stuff/mod_xsendfile/ + * + * Not really ideal, but should work fine... + * <code> + * if (strpos($upload_dir, '/') !== 0 && strpos($upload_dir, '../') === false) + * { + * header('X-Sendfile: ' . $filename); + * } + * </code> + */ + + // Send out the Headers. Do not set Content-Disposition to inline please, it is a security measure for users using the Internet Explorer. + $is_ie8 = (strpos(strtolower($user->browser), 'msie 8.0') !== false); + header('Content-Type: ' . $attachment['mimetype']); + + if ($is_ie8) + { + header('X-Content-Type-Options: nosniff'); + } + + if ($category == ATTACHMENT_CATEGORY_FLASH && request_var('view', 0) === 1) + { + // We use content-disposition: inline for flash files and view=1 to let it correctly play with flash player 10 - any other disposition will fail to play inline + header('Content-Disposition: inline'); + } + else + { + if (empty($user->browser) || (!$is_ie8 && (strpos(strtolower($user->browser), 'msie') !== false))) + { + header('Content-Disposition: attachment; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); + if (empty($user->browser) || (strpos(strtolower($user->browser), 'msie 6.0') !== false)) + { + header('expires: -1'); + } + } + else + { + header('Content-Disposition: ' . ((strpos($attachment['mimetype'], 'image') === 0) ? 'inline' : 'attachment') . '; ' . header_filename(htmlspecialchars_decode($attachment['real_filename']))); + if ($is_ie8 && (strpos($attachment['mimetype'], 'image') !== 0)) + { + header('X-Download-Options: noopen'); + } + } + } + + if ($size) + { + header("Content-Length: $size"); + } + + // Close the db connection before sending the file + $db->sql_close(); + + if (!set_modified_headers($attachment['filetime'], $user->browser)) + { + // Try to deliver in chunks + @set_time_limit(0); + + $fp = @fopen($filename, 'rb'); + + if ($fp !== false) + { + while (!feof($fp)) + { + echo fread($fp, 8192); + } + fclose($fp); + } + else + { + @readfile($filename); + } + + flush(); + } + file_gc(); +} + +/** +* Get a browser friendly UTF-8 encoded filename +*/ +function header_filename($file) +{ + $user_agent = (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; + + // There be dragons here. + // Not many follows the RFC... + if (strpos($user_agent, 'MSIE') !== false || strpos($user_agent, 'Safari') !== false || strpos($user_agent, 'Konqueror') !== false) + { + return "filename=" . rawurlencode($file); + } + + // follow the RFC for extended filename for the rest + return "filename*=UTF-8''" . rawurlencode($file); +} + +/** +* Check if downloading item is allowed +*/ +function download_allowed() +{ + global $config, $user, $db; + + if (!$config['secure_downloads']) + { + return true; + } + + $url = (!empty($_SERVER['HTTP_REFERER'])) ? trim($_SERVER['HTTP_REFERER']) : trim(getenv('HTTP_REFERER')); + + if (!$url) + { + return ($config['secure_allow_empty_referer']) ? true : false; + } + + // Split URL into domain and script part + $url = @parse_url($url); + + if ($url === false) + { + return ($config['secure_allow_empty_referer']) ? true : false; + } + + $hostname = $url['host']; + unset($url); + + $allowed = ($config['secure_allow_deny']) ? false : true; + $iplist = array(); + + if (($ip_ary = @gethostbynamel($hostname)) !== false) + { + foreach ($ip_ary as $ip) + { + if ($ip) + { + $iplist[] = $ip; + } + } + } + + // Check for own server... + $server_name = $user->host; + + // Forcing server vars is the only way to specify/override the protocol + if ($config['force_server_vars'] || !$server_name) + { + $server_name = $config['server_name']; + } + + if (preg_match('#^.*?' . preg_quote($server_name, '#') . '.*?$#i', $hostname)) + { + $allowed = true; + } + + // Get IP's and Hostnames + if (!$allowed) + { + $sql = 'SELECT site_ip, site_hostname, ip_exclude + FROM ' . SITELIST_TABLE; + $result = $db->sql_query($sql); + + while ($row = $db->sql_fetchrow($result)) + { + $site_ip = trim($row['site_ip']); + $site_hostname = trim($row['site_hostname']); + + if ($site_ip) + { + foreach ($iplist as $ip) + { + if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_ip, '#')) . '$#i', $ip)) + { + if ($row['ip_exclude']) + { + $allowed = ($config['secure_allow_deny']) ? false : true; + break 2; + } + else + { + $allowed = ($config['secure_allow_deny']) ? true : false; + } + } + } + } + + if ($site_hostname) + { + if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($site_hostname, '#')) . '$#i', $hostname)) + { + if ($row['ip_exclude']) + { + $allowed = ($config['secure_allow_deny']) ? false : true; + break; + } + else + { + $allowed = ($config['secure_allow_deny']) ? true : false; + } + } + } + } + $db->sql_freeresult($result); + } + + return $allowed; +} + +/** +* Check if the browser has the file already and set the appropriate headers- +* @returns false if a resend is in order. +*/ +function set_modified_headers($stamp, $browser) +{ + // let's see if we have to send the file at all + $last_load = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime(trim($_SERVER['HTTP_IF_MODIFIED_SINCE'])) : false; + if ((strpos(strtolower($browser), 'msie 6.0') === false) && (strpos(strtolower($browser), 'msie 8.0') === false)) + { + if ($last_load !== false && $last_load >= $stamp) + { + send_status_line(304, 'Not Modified'); + // seems that we need those too ... browsers + header('Pragma: public'); + header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000)); + return true; + } + else + { + header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $stamp) . ' GMT'); + } + } + return false; +} + +function file_gc() +{ + global $cache, $db; + if (!empty($cache)) + { + $cache->unload(); + } + $db->sql_close(); + exit; +} diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php index d0e7c8cfc8..194cba7291 100644 --- a/phpBB/includes/functions_module.php +++ b/phpBB/includes/functions_module.php @@ -314,6 +314,7 @@ class p_master function module_auth($module_auth, $forum_id = false) { global $auth, $config; + global $request; $module_auth = trim($module_auth); @@ -361,7 +362,7 @@ class p_master $forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id; $is_auth = false; - eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z0-9_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z0-9_]+)#', '#cfg_([a-z0-9_]+)#', '#request_([a-zA-Z0-9_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '!empty($_REQUEST[\'\\1\'])'), $module_auth) . ');'); + eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z0-9_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z0-9_]+)#', '#cfg_([a-z0-9_]+)#', '#request_([a-zA-Z0-9_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '$request->variable(\'\\1\', false)'), $module_auth) . ');'); return $is_auth; } diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php index 6fd87db663..cbea0a1e77 100644 --- a/phpBB/includes/functions_posting.php +++ b/phpBB/includes/functions_posting.php @@ -564,26 +564,27 @@ function get_supported_image_types($type = false) switch ($type) { // GIF - case 1: + case IMAGETYPE_GIF: $new_type = ($format & IMG_GIF) ? IMG_GIF : false; break; // JPG, JPC, JP2 - case 2: - case 9: - case 10: - case 11: - case 12: + case IMAGETYPE_JPEG: + case IMAGETYPE_JPC: + case IMAGETYPE_JPEG2000: + case IMAGETYPE_JP2: + case IMAGETYPE_JPX: + case IMAGETYPE_JB2: $new_type = ($format & IMG_JPG) ? IMG_JPG : false; break; // PNG - case 3: + case IMAGETYPE_PNG: $new_type = ($format & IMG_PNG) ? IMG_PNG : false; break; // WBMP - case 15: + case IMAGETYPE_WBMP: $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false; break; } diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php index 3937cf9c21..3ad06a3383 100644 --- a/phpBB/includes/functions_profile_fields.php +++ b/phpBB/includes/functions_profile_fields.php @@ -610,6 +610,7 @@ class custom_profile function get_var($field_validation, &$profile_row, $default_value, $preview) { global $user; + global $request; $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; $user_ident = $profile_row['field_ident']; @@ -622,7 +623,7 @@ class custom_profile { if (isset($_REQUEST[$profile_row['field_ident']])) { - $value = ($_REQUEST[$profile_row['field_ident']] === '') ? NULL : request_var($profile_row['field_ident'], $default_value); + $value = ($request->variable($profile_row['field_ident'], '') === '') ? NULL : $request->variable($profile_row['field_ident'], $default_value); } else { @@ -894,6 +895,7 @@ class custom_profile { global $phpbb_root_path, $phpEx; global $config; + global $request; $var_name = 'pf_' . $profile_row['field_ident']; @@ -938,7 +940,7 @@ class custom_profile break; case FIELD_INT: - if (isset($_REQUEST[$var_name]) && $_REQUEST[$var_name] === '') + if (isset($_REQUEST[$var_name]) && $request->variable($var_name, '') === '') { $var = NULL; } diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php index 7f09cc1640..983ccdfc82 100644 --- a/phpBB/includes/functions_upload.php +++ b/phpBB/includes/functions_upload.php @@ -976,7 +976,7 @@ class fileupload /** - * Check for allowed extension + * Check for bad content (IE mime-sniffing) */ function valid_content(&$file) { @@ -989,22 +989,22 @@ class fileupload function image_types() { return array( - 1 => array('gif'), - 2 => array('jpg', 'jpeg'), - 3 => array('png'), - 4 => array('swf'), - 5 => array('psd'), - 6 => array('bmp'), - 7 => array('tif', 'tiff'), - 8 => array('tif', 'tiff'), - 9 => array('jpg', 'jpeg'), - 10 => array('jpg', 'jpeg'), - 11 => array('jpg', 'jpeg'), - 12 => array('jpg', 'jpeg'), - 13 => array('swc'), - 14 => array('iff'), - 15 => array('wbmp'), - 16 => array('xbm'), + IMAGETYPE_GIF => array('gif'), + IMAGETYPE_JPEG => array('jpg', 'jpeg'), + IMAGETYPE_PNG => array('png'), + IMAGETYPE_SWF => array('swf'), + IMAGETYPE_PSD => array('psd'), + IMAGETYPE_BMP => array('bmp'), + IMAGETYPE_TIFF_II => array('tif', 'tiff'), + IMAGETYPE_TIFF_MM => array('tif', 'tiff'), + IMAGETYPE_JPC => array('jpg', 'jpeg'), + IMAGETYPE_JP2 => array('jpg', 'jpeg'), + IMAGETYPE_JPX => array('jpg', 'jpeg'), + IMAGETYPE_JB2 => array('jpg', 'jpeg'), + IMAGETYPE_SWC => array('swc'), + IMAGETYPE_IFF => array('iff'), + IMAGETYPE_WBMP => array('wbmp'), + IMAGETYPE_XBM => array('xbm'), ); } } diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index f2c80705ba..0eecc903e5 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -1774,15 +1774,15 @@ function validate_jabber($jid) return false; } - $seperator_pos = strpos($jid, '@'); + $separator_pos = strpos($jid, '@'); - if ($seperator_pos === false) + if ($separator_pos === false) { return 'WRONG_DATA'; } - $username = substr($jid, 0, $seperator_pos); - $realm = substr($jid, $seperator_pos + 1); + $username = substr($jid, 0, $separator_pos); + $realm = substr($jid, $separator_pos + 1); if (strlen($username) == 0 || strlen($realm) < 3) { diff --git a/phpBB/includes/mcp/mcp_forum.php b/phpBB/includes/mcp/mcp_forum.php index b70601b479..ddd13cb080 100644 --- a/phpBB/includes/mcp/mcp_forum.php +++ b/phpBB/includes/mcp/mcp_forum.php @@ -23,6 +23,7 @@ function mcp_forum_view($id, $mode, $action, $forum_info) { global $template, $db, $user, $auth, $cache, $module; global $phpEx, $phpbb_root_path, $config; + global $request; $user->add_lang(array('viewtopic', 'viewforum')); @@ -34,7 +35,10 @@ function mcp_forum_view($id, $mode, $action, $forum_info) if ($merge_select) { // Fixes a "bug" that makes forum_view use the same ordering as topic_view - unset($_POST['sk'], $_POST['sd'], $_REQUEST['sk'], $_REQUEST['sd']); + $request->overwrite('sk', null); + $request->overwrite('sd', null); + $request->overwrite('sk', null, phpbb_request_interface::POST); + $request->overwrite('sd', null, phpbb_request_interface::POST); } $forum_id = $forum_info['forum_id']; diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php index d5551f5114..14286f98e9 100644 --- a/phpBB/includes/mcp/mcp_main.php +++ b/phpBB/includes/mcp/mcp_main.php @@ -532,6 +532,7 @@ function mcp_move_topic($topic_ids) { global $auth, $user, $db, $template; global $phpEx, $phpbb_root_path; + global $request; // Here we limit the operation to one forum only $forum_id = check_ids($topic_ids, TOPICS_TABLE, 'topic_id', array('m_move'), true); @@ -585,8 +586,8 @@ function mcp_move_topic($topic_ids) if (!$to_forum_id || $additional_msg) { - unset($_POST['confirm']); - unset($_REQUEST['confirm_key']); + $request->overwrite('confirm', null, phpbb_request_interface::POST); + $request->overwrite('confirm_key', null); } if (confirm_box(true)) @@ -1037,8 +1038,8 @@ function mcp_fork_topic($topic_ids) if ($additional_msg) { - unset($_POST['confirm']); - unset($_REQUEST['confirm_key']); + $request->overwrite('confirm', null, phpbb_request_interface::POST); + $request->overwrite('confirm_key', null); } if (confirm_box(true)) diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php index c419da5574..dc34f04db4 100644 --- a/phpBB/includes/mcp/mcp_queue.php +++ b/phpBB/includes/mcp/mcp_queue.php @@ -744,6 +744,7 @@ function disapprove_post($post_id_list, $id, $mode) { global $db, $template, $user, $config; global $phpEx, $phpbb_root_path; + global $request; if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve'))) { @@ -778,7 +779,7 @@ function disapprove_post($post_id_list, $id, $mode) if (!$row || (!$reason && strtolower($row['reason_title']) == 'other')) { $additional_msg = $user->lang['NO_REASON_DISAPPROVAL']; - unset($_POST['confirm']); + $request->overwrite('confirm', null, phpbb_request_interface::POST); } else { diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php index 952b55cc8c..e0b2bb1496 100644 --- a/phpBB/includes/message_parser.php +++ b/phpBB/includes/message_parser.php @@ -1532,9 +1532,10 @@ class parse_message extends bbcode_firstpass function get_submitted_attachment_data($check_user_id = false) { global $user, $db, $phpbb_root_path, $phpEx, $config; + global $request; $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); - $attachment_data = (isset($_POST['attachment_data'])) ? $_POST['attachment_data'] : array(); + $attachment_data = $request->variable('attachment_data', array(0 => array('' => '')), true, phpbb_request_interface::POST); $this->attachment_data = array(); $check_user_id = ($check_user_id === false) ? $user->data['user_id'] : $check_user_id; @@ -1572,7 +1573,7 @@ class parse_message extends bbcode_firstpass { $pos = $not_orphan[$row['attach_id']]; $this->attachment_data[$pos] = $row; - set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); + $this->attachment_data[$pos]['attach_comment'] = $attachment_data[$pos]['attach_comment']; unset($not_orphan[$row['attach_id']]); } @@ -1598,7 +1599,7 @@ class parse_message extends bbcode_firstpass { $pos = $orphan[$row['attach_id']]; $this->attachment_data[$pos] = $row; - set_var($this->attachment_data[$pos]['attach_comment'], $_POST['attachment_data'][$pos]['attach_comment'], 'string', true); + $this->attachment_data[$pos]['attach_comment'] = $attachment_data[$pos]['attach_comment']; unset($orphan[$row['attach_id']]); } diff --git a/phpBB/includes/request/deactivated_super_global.php b/phpBB/includes/request/deactivated_super_global.php new file mode 100644 index 0000000000..d7a5b3145f --- /dev/null +++ b/phpBB/includes/request/deactivated_super_global.php @@ -0,0 +1,121 @@ +<?php +/** +* +* @package phpbb_request +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* Replacement for a superglobal (like $_GET or $_POST) which calls +* trigger_error on all operations but isset, overloads the [] operator with SPL. +* +* @package phpbb_request +*/ +class phpbb_request_deactivated_super_global implements ArrayAccess, Countable, IteratorAggregate +{ + /** + * @var string Holds the name of the superglobal this is replacing. + */ + private $name; + + /** + * @var phpbb_request_interface::POST|GET|REQUEST|COOKIE Super global constant. + */ + private $super_global; + + /** + * @var phpbb_request_interface The request class instance holding the actual request data. + */ + private $request; + + /** + * Constructor generates an error message fitting the super global to be used within the other functions. + * + * @param phpbb_request_interface $request A request class instance holding the real super global data. + * @param string $name Name of the super global this is a replacement for - e.g. '_GET'. + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global The variable's super global constant. + */ + public function __construct(phpbb_request_interface $request, $name, $super_global) + { + $this->request = $request; + $this->name = $name; + $this->super_global = $super_global; + } + + /** + * Calls trigger_error with the file and line number the super global was used in. + */ + private function error() + { + $file = ''; + $line = 0; + + $message = 'Illegal use of $' . $this->name . '. You must use the request class or request_var() to access input data. Found in %s on line %d. This error message was generated'; + + $backtrace = debug_backtrace(); + if (isset($backtrace[1])) + { + $file = $backtrace[1]['file']; + $line = $backtrace[1]['line']; + } + trigger_error(sprintf($message, $file, $line), E_USER_ERROR); + } + + /** + * Redirects isset to the correct request class call. + * + * @param string $offset The key of the super global being accessed. + * + * @return bool Whether the key on the super global exists. + */ + public function offsetExists($offset) + { + return $this->request->is_set($offset, $this->super_global); + } + + /**#@+ + * Part of the ArrayAccess implementation, will always result in a FATAL error. + */ + public function offsetGet($offset) + { + $this->error(); + } + + public function offsetSet($offset, $value) + { + $this->error(); + } + + public function offsetUnset($offset) + { + $this->error(); + } + /**#@-*/ + + /** + * Part of the Countable implementation, will always result in a FATAL error + */ + public function count() + { + $this->error(); + } + + /** + * Part of the Traversable/IteratorAggregate implementation, will always result in a FATAL error + */ + public function getIterator() + { + $this->error(); + } +} + diff --git a/phpBB/includes/request/interface.php b/phpBB/includes/request/interface.php new file mode 100644 index 0000000000..7b5b600100 --- /dev/null +++ b/phpBB/includes/request/interface.php @@ -0,0 +1,103 @@ +<?php +/** +* +* @package phpbb_request +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* An interface through which all application input can be accessed. +* +* @package phpbb_request +*/ +interface phpbb_request_interface +{ + /**#@+ + * Constant identifying the super global with the same name. + */ + const POST = 0; + const GET = 1; + const REQUEST = 2; + const COOKIE = 3; + /**#@-*/ + + /** + * This function allows overwriting or setting a value in one of the super global arrays. + * + * Changes which are performed on the super globals directly will not have any effect on the results of + * other methods this class provides. Using this function should be avoided if possible! It will + * consume twice the the amount of memory of the value + * + * @param string $var_name The name of the variable that shall be overwritten + * @param mixed $value The value which the variable shall contain. + * If this is null the variable will be unset. + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies which super global shall be changed + */ + public function overwrite($var_name, $value, $super_global = phpbb_request_interface::REQUEST); + + /** + * Central type safe input handling function. + * All variables in GET or POST requests should be retrieved through this function to maximise security. + * + * @param string|array $var_name The form variable's name from which data shall be retrieved. + * If the value is an array this may be an array of indizes which will give + * direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") + * then specifying array("var", 1) as the name will return "a". + * @param mixed $default A default value that is returned if the variable was not set. + * This function will always return a value of the same type as the default. + * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies which super global should be used + * + * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the + * the same as that of $default. If the variable is not set $default is returned. + */ + public function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST); + + /** + * Checks whether a certain variable was sent via POST. + * To make sure that a request was sent using POST you should call this function + * on at least one variable. + * + * @param string $name The name of the form variable which should have a + * _p suffix to indicate the check in the code that creates the form too. + * + * @return bool True if the variable was set in a POST request, false otherwise. + */ + public function is_set_post($name); + + /** + * Checks whether a certain variable is set in one of the super global + * arrays. + * + * @param string $var Name of the variable + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies the super global which shall be checked + * + * @return bool True if the variable was sent as input + */ + public function is_set($var, $super_global = phpbb_request_interface::REQUEST); + + /** + * Returns all variable names for a given super global + * + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * The super global from which names shall be taken + * + * @return array All variable names that are set for the super global. + * Pay attention when using these, they are unsanitised! + */ + public function variable_names($super_global = phpbb_request_interface::REQUEST); +} diff --git a/phpBB/includes/request/request.php b/phpBB/includes/request/request.php new file mode 100644 index 0000000000..7d284a9bf7 --- /dev/null +++ b/phpBB/includes/request/request.php @@ -0,0 +1,292 @@ +<?php +/** +* +* @package phpbb_request +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* All application input is accessed through this class. +* +* It provides a method to disable access to input data through super globals. +* This should force MOD authors to read about data validation. +* +* @package phpbb_request +*/ +class phpbb_request implements phpbb_request_interface +{ + /** + * @var array The names of super global variables that this class should protect if super globals are disabled. + */ + protected $super_globals = array( + phpbb_request_interface::POST => '_POST', + phpbb_request_interface::GET => '_GET', + phpbb_request_interface::REQUEST => '_REQUEST', + phpbb_request_interface::COOKIE => '_COOKIE' + ); + + /** + * @var array Stores original contents of $_REQUEST array. + */ + protected $original_request = null; + + /** + * @var + */ + protected $super_globals_disabled = false; + + /** + * @var array An associative array that has the value of super global constants as keys and holds their data as values. + */ + protected $input; + + /** + * @var phpbb_request_type_cast_helper_interface An instance of a type cast helper providing convenience methods for type conversions. + */ + protected $type_cast_helper; + + /** + * Initialises the request class, that means it stores all input data in {@link $input input} + * and then calls {@link phpbb_request_deactivated_super_global phpbb_request_deactivated_super_global} + */ + public function __construct(phpbb_request_type_cast_helper_interface $type_cast_helper = null, $disable_super_globals = true) + { + if ($type_cast_helper) + { + $this->type_cast_helper = $type_cast_helper; + } + else + { + $this->type_cast_helper = new phpbb_request_type_cast_helper(); + } + + foreach ($this->super_globals as $const => $super_global) + { + $this->input[$const] = isset($GLOBALS[$super_global]) ? $GLOBALS[$super_global] : array(); + } + + // simulate request_order = GP + $this->original_request = $this->input[phpbb_request_interface::REQUEST]; + $this->input[phpbb_request_interface::REQUEST] = $this->input[phpbb_request_interface::POST] + $this->input[phpbb_request_interface::GET]; + + if ($disable_super_globals) + { + $this->disable_super_globals(); + } + } + + /** + * Getter for $super_globals_disabled + * + * @return bool Whether super globals are disabled or not. + */ + public function super_globals_disabled() + { + return $this->super_globals_disabled; + } + + /** + * Disables access of super globals specified in $super_globals. + * This is achieved by overwriting the super globals with instances of {@link phpbb_request_deactivated_super_global phpbb_request_deactivated_super_global} + */ + public function disable_super_globals() + { + if (!$this->super_globals_disabled) + { + foreach ($this->super_globals as $const => $super_global) + { + unset($GLOBALS[$super_global]); + $GLOBALS[$super_global] = new phpbb_request_deactivated_super_global($this, $super_global, $const); + } + + $this->super_globals_disabled = true; + } + } + + /** + * Enables access of super globals specified in $super_globals if they were disabled by {@link disable_super_globals disable_super_globals}. + * This is achieved by making the super globals point to the data stored within this class in {@link $input input}. + */ + public function enable_super_globals() + { + if ($this->super_globals_disabled) + { + foreach ($this->super_globals as $const => $super_global) + { + $GLOBALS[$super_global] = $this->input[$const]; + } + + $GLOBALS['_REQUEST'] = $this->original_request; + + $this->super_globals_disabled = false; + } + } + + /** + * This function allows overwriting or setting a value in one of the super global arrays. + * + * Changes which are performed on the super globals directly will not have any effect on the results of + * other methods this class provides. Using this function should be avoided if possible! It will + * consume twice the the amount of memory of the value + * + * @param string $var_name The name of the variable that shall be overwritten + * @param mixed $value The value which the variable shall contain. + * If this is null the variable will be unset. + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies which super global shall be changed + */ + public function overwrite($var_name, $value, $super_global = phpbb_request_interface::REQUEST) + { + if (!isset($this->super_globals[$super_global])) + { + return; + } + + $this->type_cast_helper->add_magic_quotes($value); + + // setting to null means unsetting + if ($value === null) + { + unset($this->input[$super_global][$var_name]); + if (!$this->super_globals_disabled()) + { + unset($GLOBALS[$this->super_globals[$super_global]][$var_name]); + } + } + else + { + $this->input[$super_global][$var_name] = $value; + if (!$this->super_globals_disabled()) + { + $GLOBALS[$this->super_globals[$super_global]][$var_name] = $value; + } + } + + if (!$this->super_globals_disabled()) + { + unset($GLOBALS[$this->super_globals[$super_global]][$var_name]); + $GLOBALS[$this->super_globals[$super_global]][$var_name] = $value; + } + } + + /** + * Central type safe input handling function. + * All variables in GET or POST requests should be retrieved through this function to maximise security. + * + * @param string|array $var_name The form variable's name from which data shall be retrieved. + * If the value is an array this may be an array of indizes which will give + * direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") + * then specifying array("var", 1) as the name will return "a". + * @param mixed $default A default value that is returned if the variable was not set. + * This function will always return a value of the same type as the default. + * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies which super global should be used + * + * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the + * the same as that of $default. If the variable is not set $default is returned. + */ + public function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request_interface::REQUEST) + { + $path = false; + + // deep direct access to multi dimensional arrays + if (is_array($var_name)) + { + $path = $var_name; + // make sure at least the variable name is specified + if (empty($path)) + { + return (is_array($default)) ? array() : $default; + } + // the variable name is the first element on the path + $var_name = array_shift($path); + } + + if (!isset($this->input[$super_global][$var_name])) + { + return (is_array($default)) ? array() : $default; + } + $var = $this->input[$super_global][$var_name]; + + if ($path) + { + // walk through the array structure and find the element we are looking for + foreach ($path as $key) + { + if (is_array($var) && isset($var[$key])) + { + $var = $var[$key]; + } + else + { + return (is_array($default)) ? array() : $default; + } + } + } + + $this->type_cast_helper->recursive_set_var($var, $default, $multibyte); + + return $var; + } + + /** + * Checks whether a certain variable was sent via POST. + * To make sure that a request was sent using POST you should call this function + * on at least one variable. + * + * @param string $name The name of the form variable which should have a + * _p suffix to indicate the check in the code that creates the form too. + * + * @return bool True if the variable was set in a POST request, false otherwise. + */ + public function is_set_post($name) + { + return $this->is_set($name, phpbb_request_interface::POST); + } + + /** + * Checks whether a certain variable is set in one of the super global + * arrays. + * + * @param string $var Name of the variable + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * Specifies the super global which shall be checked + * + * @return bool True if the variable was sent as input + */ + public function is_set($var, $super_global = phpbb_request_interface::REQUEST) + { + return isset($this->input[$super_global][$var]); + } + + /** + * Returns all variable names for a given super global + * + * @param phpbb_request_interface::POST|GET|REQUEST|COOKIE $super_global + * The super global from which names shall be taken + * + * @return array All variable names that are set for the super global. + * Pay attention when using these, they are unsanitised! + */ + public function variable_names($super_global = phpbb_request_interface::REQUEST) + { + if (!isset($this->input[$super_global])) + { + return array(); + } + + return array_keys($this->input[$super_global]); + } +} diff --git a/phpBB/includes/request/type_cast_helper.php b/phpBB/includes/request/type_cast_helper.php new file mode 100644 index 0000000000..29855a9804 --- /dev/null +++ b/phpBB/includes/request/type_cast_helper.php @@ -0,0 +1,183 @@ +<?php +/** +* +* @package phpbb_request +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* A helper class that provides convenience methods for type casting. +* +* @package phpbb_request +*/ +class phpbb_request_type_cast_helper implements phpbb_request_type_cast_helper_interface +{ + + /** + * @var string Whether slashes need to be stripped from input + */ + protected $strip; + + /** + * Initialises the type cast helper class. + * All it does is find out whether magic quotes are turned on. + */ + public function __construct() + { + if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) + { + $this->strip = false; + } + else + { + $this->strip = (@get_magic_quotes_gpc()) ? true : false; + } + } + + /** + * Recursively applies addslashes to a variable. + * + * @param mixed &$var Variable passed by reference to which slashes will be added. + */ + public function addslashes_recursively(&$var) + { + if (is_string($var)) + { + $var = addslashes($var); + } + else if (is_array($var)) + { + $var_copy = $var; + $var = array(); + foreach ($var_copy as $key => $value) + { + if (is_string($key)) + { + $key = addslashes($key); + } + $var[$key] = $value; + + $this->addslashes_recursively($var[$key]); + } + } + } + + /** + * Recursively applies addslashes to a variable if magic quotes are turned on. + * + * @param mixed &$var Variable passed by reference to which slashes will be added. + */ + public function add_magic_quotes(&$var) + { + if ($this->strip) + { + $this->addslashes_recursively($var); + } + } + + /** + * Set variable $result to a particular type. + * + * @param mixed &$result The variable to fill + * @param mixed $var The contents to fill with + * @param mixed $type The variable type. Will be used with {@link settype()} + * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. + */ + public function set_var(&$result, $var, $type, $multibyte = false) + { + settype($var, $type); + $result = $var; + + if ($type == 'string') + { + $result = trim(htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result), ENT_COMPAT, 'UTF-8')); + + if ($multibyte) + { + $result = utf8_normalize_nfc($result); + } + + if (!empty($result)) + { + // Make sure multibyte characters are wellformed + if ($multibyte) + { + if (!preg_match('/^./u', $result)) + { + $result = ''; + } + } + else + { + // no multibyte, allow only ASCII (0-127) + $result = preg_replace('/[\x80-\xFF]/', '?', $result); + } + } + + $result = ($this->strip) ? stripslashes($result) : $result; + } + } + + /** + * Recursively sets a variable to a given type using {@link set_var set_var} + * + * @param string $var The value which shall be sanitised (passed by reference). + * @param mixed $default Specifies the type $var shall have. + * If it is an array and $var is not one, then an empty array is returned. + * Otherwise var is cast to the same type, and if $default is an array all + * keys and values are cast recursively using this function too. + * @param bool $multibyte Indicates whether string keys and values may contain UTF-8 characters. + * Default is false, causing all bytes outside the ASCII range (0-127) to + * be replaced with question marks. + */ + public function recursive_set_var(&$var, $default, $multibyte) + { + if (is_array($var) !== is_array($default)) + { + $var = (is_array($default)) ? array() : $default; + return; + } + + if (!is_array($default)) + { + $type = gettype($default); + $this->set_var($var, $var, $type, $multibyte); + } + else + { + // make sure there is at least one key/value pair to use get the + // types from + if (empty($default)) + { + $var = array(); + return; + } + + list($default_key, $default_value) = each($default); + $value_type = gettype($default_value); + $key_type = gettype($default_key); + + $_var = $var; + $var = array(); + + foreach ($_var as $k => $v) + { + $this->set_var($k, $k, $key_type, $multibyte, $multibyte); + + $this->recursive_set_var($v, $default_value, $multibyte); + $var[$k] = $v; + } + } + } +} diff --git a/phpBB/includes/request/type_cast_helper_interface.php b/phpBB/includes/request/type_cast_helper_interface.php new file mode 100644 index 0000000000..366bd2e6ce --- /dev/null +++ b/phpBB/includes/request/type_cast_helper_interface.php @@ -0,0 +1,63 @@ +<?php +/** +* +* @package phpbb_request +* @copyright (c) 2010 phpBB Group +* @license http://opensource.org/licenses/gpl-license.php GNU Public License +* +*/ + +/** +* @ignore +*/ +if (!defined('IN_PHPBB')) +{ + exit; +} + +/** +* An interface for type cast operations. +* +* @package phpbb_request +*/ +interface phpbb_request_type_cast_helper_interface +{ + /** + * Recursively applies addslashes to a variable. + * + * @param mixed &$var Variable passed by reference to which slashes will be added. + */ + public function addslashes_recursively(&$var); + + /** + * Recursively applies addslashes to a variable if magic quotes are turned on. + * + * @param mixed &$var Variable passed by reference to which slashes will be added. + */ + public function add_magic_quotes(&$var); + + /** + * Set variable $result to a particular type. + * + * @param mixed &$result The variable to fill + * @param mixed $var The contents to fill with + * @param mixed $type The variable type. Will be used with {@link settype()} + * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. + * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. + */ + public function set_var(&$result, $var, $type, $multibyte = false); + + /** + * Recursively sets a variable to a given type using {@link set_var set_var}. + * + * @param string $var The value which shall be sanitised (passed by reference). + * @param mixed $default Specifies the type $var shall have. + * If it is an array and $var is not one, then an empty array is returned. + * Otherwise var is cast to the same type, and if $default is an array all + * keys and values are cast recursively using this function too. + * @param bool $multibyte Indicates whether string keys and values may contain UTF-8 characters. + * Default is false, causing all bytes outside the ASCII range (0-127) to + * be replaced with question marks. + */ + public function recursive_set_var(&$var, $default, $multibyte); +} diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php index 5f5b39fe27..0e6a23762e 100644 --- a/phpBB/includes/session.php +++ b/phpBB/includes/session.php @@ -39,7 +39,7 @@ class session * * @param string $root_path current root path (phpbb_root_path) */ - function extract_current_page($root_path) + static function extract_current_page($root_path) { $page_array = array(); @@ -130,7 +130,7 @@ class session 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), 'page' => $page, - 'forum' => (isset($_REQUEST['f']) && $_REQUEST['f'] > 0) ? (int) $_REQUEST['f'] : 0, + 'forum' => request_var('f', 0), ); return $page_array; @@ -318,7 +318,7 @@ class session } // Is session_id is set or session_id is set and matches the url param if required - if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === $_GET['sid']))) + if (!empty($this->session_id) && (!defined('NEED_SID') || (isset($_GET['sid']) && $this->session_id === request_var('sid', '')))) { $sql = 'SELECT u.*, s.* FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u @@ -994,7 +994,7 @@ class session } // only called from CRON; should be a safe workaround until the infrastructure gets going - if (!class_exists('phpbb_captcha_factory')) + if (!class_exists('phpbb_captcha_factory', false)) { include($phpbb_root_path . "includes/captcha/captcha_factory." . $phpEx); } @@ -1591,11 +1591,12 @@ class user extends session $this->add_lang($lang_set); unset($lang_set); - if (!empty($_GET['style']) && $auth->acl_get('a_styles') && !defined('ADMIN_START')) + $style_request = request_var('style', 0); + if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START')) { global $SID, $_EXTRA_URL; - $style = request_var('style', 0); + $style = $style_request; $SID .= '&style=' . $style; $_EXTRA_URL = array('style=' . $style); } diff --git a/phpBB/includes/ucp/ucp_groups.php b/phpBB/includes/ucp/ucp_groups.php index 1c055a4823..433b9af9d1 100644 --- a/phpBB/includes/ucp/ucp_groups.php +++ b/phpBB/includes/ucp/ucp_groups.php @@ -28,14 +28,15 @@ class ucp_groups { global $config, $phpbb_root_path, $phpEx; global $db, $user, $auth, $cache, $template; + global $request; $user->add_lang('groups'); $return_page = '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], '<a href="' . $this->u_action . '">', '</a>'); $mark_ary = request_var('mark', array(0)); - $submit = (!empty($_POST['submit'])) ? true : false; - $delete = (!empty($_POST['delete'])) ? true : false; + $submit = $request->variable('submit', false, false, phpbb_request_interface::POST); + $delete = $request->variable('delete', false, false, phpbb_request_interface::POST); $error = $data = array(); switch ($mode) diff --git a/phpBB/includes/ucp/ucp_main.php b/phpBB/includes/ucp/ucp_main.php index a6f71669ce..3fde308309 100644 --- a/phpBB/includes/ucp/ucp_main.php +++ b/phpBB/includes/ucp/ucp_main.php @@ -34,6 +34,7 @@ class ucp_main function main($id, $mode) { global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + global $request; switch ($mode) { @@ -435,7 +436,7 @@ class ucp_main $edit = (isset($_REQUEST['edit'])) ? true : false; $submit = (isset($_POST['submit'])) ? true : false; - $draft_id = ($edit) ? intval($_REQUEST['edit']) : 0; + $draft_id = $request->variable('edit', 0); $delete = (isset($_POST['delete'])) ? true : false; $s_hidden_fields = ($edit) ? '<input type="hidden" name="edit" value="' . $draft_id . '" />' : ''; diff --git a/phpBB/includes/ucp/ucp_pm_compose.php b/phpBB/includes/ucp/ucp_pm_compose.php index b596e72c41..e7c0244b99 100644 --- a/phpBB/includes/ucp/ucp_pm_compose.php +++ b/phpBB/includes/ucp/ucp_pm_compose.php @@ -24,6 +24,7 @@ function compose_pm($id, $mode, $action) { global $template, $db, $auth, $user; global $phpbb_root_path, $phpEx, $config; + global $request; // Damn php and globals - i know, this is horrible // Needed for handle_message_list_actions() @@ -49,13 +50,7 @@ function compose_pm($id, $mode, $action) // Reply to all triggered (quote/reply) $reply_to_all = request_var('reply_to_all', 0); - // Do NOT use request_var or specialchars here - $address_list = isset($_REQUEST['address_list']) ? $_REQUEST['address_list'] : array(); - - if (!is_array($address_list)) - { - $address_list = array(); - } + $address_list = $request->variable('address_list', array('' => array(0 => ''))); $submit = (isset($_POST['post'])) ? true : false; $preview = (isset($_POST['preview'])) ? true : false; @@ -1029,7 +1024,7 @@ function compose_pm($id, $mode, $action) $s_hidden_fields = '<input type="hidden" name="lastclick" value="' . $current_time . '" />'; $s_hidden_fields .= (isset($check_value)) ? '<input type="hidden" name="status_switch" value="' . $check_value . '" />' : ''; - $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . ((isset($_REQUEST['draft_loaded'])) ? intval($_REQUEST['draft_loaded']) : $draft_id) . '" />' : ''; + $s_hidden_fields .= ($draft_id || isset($_REQUEST['draft_loaded'])) ? '<input type="hidden" name="draft_loaded" value="' . ((isset($_REQUEST['draft_loaded'])) ? $request->variable('draft_loaded', 0) : $draft_id) . '" />' : ''; $form_enctype = (@ini_get('file_uploads') == '0' || strtolower(@ini_get('file_uploads')) == 'off' || !$config['allow_pm_attach'] || !$auth->acl_get('u_pm_attach')) ? '' : ' enctype="multipart/form-data"'; @@ -1105,11 +1100,12 @@ function compose_pm($id, $mode, $action) function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove_g, $add_to, $add_bcc) { global $auth, $db, $user; + global $request; // Delete User [TO/BCC] - if ($remove_u && !empty($_REQUEST['remove_u']) && is_array($_REQUEST['remove_u'])) + if ($remove_u && $request->variable('remove_u', array(0 => ''))) { - $remove_user_id = array_keys($_REQUEST['remove_u']); + $remove_user_id = array_keys($request->variable('remove_u', array(0 => ''))); if (isset($remove_user_id[0])) { @@ -1118,9 +1114,9 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } // Delete Group [TO/BCC] - if ($remove_g && !empty($_REQUEST['remove_g']) && is_array($_REQUEST['remove_g'])) + if ($remove_g && $request->variable('remove_g', array(0 => ''))) { - $remove_group_id = array_keys($_REQUEST['remove_g']); + $remove_group_id = array_keys($request->variable('remove_g', array(0 => ''))); if (isset($remove_group_id[0])) { @@ -1188,7 +1184,7 @@ function handle_message_list_actions(&$address_list, &$error, $remove_u, $remove } // Add Friends if specified - $friend_list = (isset($_REQUEST['add_' . $type]) && is_array($_REQUEST['add_' . $type])) ? array_map('intval', array_keys($_REQUEST['add_' . $type])) : array(); + $friend_list = array_keys($request->variable('add_' . $type, array(0))); $user_id_ary = array_merge($user_id_ary, $friend_list); foreach ($user_id_ary as $user_id) diff --git a/phpBB/includes/ucp/ucp_pm_viewmessage.php b/phpBB/includes/ucp/ucp_pm_viewmessage.php index 16700c490c..429c8688cf 100644 --- a/phpBB/includes/ucp/ucp_pm_viewmessage.php +++ b/phpBB/includes/ucp/ucp_pm_viewmessage.php @@ -245,7 +245,7 @@ function view_message($id, $mode, $folder_id, $msg_id, $folder, $message_row) } } - if (!isset($_REQUEST['view']) || $_REQUEST['view'] != 'print') + if (!isset($_REQUEST['view']) || $request->variable('view', '') != 'print') { // Message History if (message_history($msg_id, $user->data['user_id'], $message_row, $folder)) diff --git a/phpBB/includes/ucp/ucp_profile.php b/phpBB/includes/ucp/ucp_profile.php index c099e3b3fa..afd85c9975 100644 --- a/phpBB/includes/ucp/ucp_profile.php +++ b/phpBB/includes/ucp/ucp_profile.php @@ -30,12 +30,13 @@ class ucp_profile function main($id, $mode) { global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + global $request; $user->add_lang('posting'); - $preview = (!empty($_POST['preview'])) ? true : false; - $submit = (!empty($_POST['submit'])) ? true : false; - $delete = (!empty($_POST['delete'])) ? true : false; + $preview = $request->variable('preview', false, false, phpbb_request_interface::POST); + $submit = $request->variable('submit', false, false, phpbb_request_interface::POST); + $delete = $request->variable('delete', false, false, phpbb_request_interface::POST); $error = $data = array(); $s_hidden_fields = ''; diff --git a/phpBB/includes/ucp/ucp_register.php b/phpBB/includes/ucp/ucp_register.php index 7fd99da55a..5fab865093 100644 --- a/phpBB/includes/ucp/ucp_register.php +++ b/phpBB/includes/ucp/ucp_register.php @@ -28,6 +28,7 @@ class ucp_register function main($id, $mode) { global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx; + global $request; // if ($config['require_activation'] == USER_ACTIVATION_DISABLE) @@ -37,9 +38,9 @@ class ucp_register include($phpbb_root_path . 'includes/functions_profile_fields.' . $phpEx); - $coppa = (isset($_REQUEST['coppa'])) ? ((!empty($_REQUEST['coppa'])) ? 1 : 0) : false; - $agreed = (!empty($_POST['agreed'])) ? 1 : 0; - $submit = (isset($_POST['submit'])) ? true : false; + $coppa = $request->is_set('coppa') ? (int) $request->variable('coppa', false) : false; + $agreed = (int) $request->variable('agreed', false); + $submit = $request->is_set_post('submit'); $change_lang = request_var('change_lang', ''); $user_lang = request_var('lang', $user->lang_name); @@ -63,7 +64,7 @@ class ucp_register $submit = false; // Setting back agreed to let the user view the agreement in his/her language - $agreed = (empty($_GET['change_lang'])) ? 0 : $agreed; + $agreed = ($request->variable('change_lang', false)) ? 0 : $agreed; } $user->lang_name = $user_lang = $use_lang; diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php index a77952499a..78684df69c 100644 --- a/phpBB/includes/utf/utf_normalizer.php +++ b/phpBB/includes/utf/utf_normalizer.php @@ -77,7 +77,7 @@ class utf_normalizer * @param string &$str The dirty string * @return string The same string, all shiny and cleaned-up */ - function cleanup(&$str) + static function cleanup(&$str) { // The string below is the list of all autorized characters, sorted by frequency in latin text $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"); @@ -119,7 +119,7 @@ class utf_normalizer * @param string &$str Unchecked UTF string * @return string The string, validated and in normal form */ - function nfc(&$str) + static function nfc(&$str) { $pos = strspn($str, UTF8_ASCII_RANGE); $len = strlen($str); @@ -151,7 +151,7 @@ class utf_normalizer * @param string &$str Unchecked UTF string * @return string The string, validated and in normal form */ - function nfkc(&$str) + static function nfkc(&$str) { $pos = strspn($str, UTF8_ASCII_RANGE); $len = strlen($str); @@ -183,7 +183,7 @@ class utf_normalizer * @param string &$str Unchecked UTF string * @return string The string, validated and in normal form */ - function nfd(&$str) + static function nfd(&$str) { $pos = strspn($str, UTF8_ASCII_RANGE); $len = strlen($str); @@ -209,7 +209,7 @@ class utf_normalizer * @param string &$str Unchecked UTF string * @return string The string, validated and in normal form */ - function nfkd(&$str) + static function nfkd(&$str) { $pos = strspn($str, UTF8_ASCII_RANGE); $len = strlen($str); @@ -242,7 +242,7 @@ class utf_normalizer * * @access private */ - function recompose($str, $pos, $len, &$qc, &$decomp_map) + static function recompose($str, $pos, $len, &$qc, &$decomp_map) { global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index; @@ -944,7 +944,7 @@ class utf_normalizer * * @access private */ - function decompose($str, $pos, $len, &$decomp_map) + static function decompose($str, $pos, $len, &$decomp_map) { global $utf_combining_class; |